From: Michael Poole Date: Fri, 10 Sep 2004 23:02:56 +0000 (+0000) Subject: Implement chkconf-like option for ircd. X-Git-Url: http://git.pk910.de/?a=commitdiff_plain;h=9eec5de4d75bb415ff63b27709bd9b5272c361b8;p=ircu2.10.12-pk.git Implement chkconf-like option for ircd. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1114 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- diff --git a/ChangeLog b/ChangeLog index 09876b4..d09f1ec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2004-09-10 Michael Poole + + * ircd/ircd.c: Add -k as a chkconf-like option to exit after + reading the configuration file. + + * ircd/chkconf.c: Remove as unused. + + * ircd/Makefile.in: Remove last mentions of chkconf from Makefile. + 2004-09-10 Michael Poole * doc/example.conf: Remove examples for unused features (TIMESEC, diff --git a/ircd/Makefile.in b/ircd/Makefile.in index 0fa39e2..7da7752 100644 --- a/ircd/Makefile.in +++ b/ircd/Makefile.in @@ -287,7 +287,6 @@ install-with-symlink: build mkbindir ${RM} -f ${SYMLINK}; \ ${LN_S} ircd.`cat /tmp/ircd.tag` ${SYMLINK}; ) @${RM} /tmp/ircd.tag -# ${INSTALL} -s -m 700 -o ${IRCDOWN} -g ${IRCDGRP} chkconf ${BINDIR} ${INSTALL} -s -m 700 -o ${IRCDOWN} -g ${IRCDGRP} umkpasswd ${BINDIR} ${INSTALL} -m 600 -o ${IRCDOWN} -g ${IRCDGRP} ${top_srcdir}/doc/example.conf ${DPATH} # ( cd ${DPATH}; \ @@ -306,7 +305,6 @@ install-no-symlink: build mkbindir fi @echo "Installing new ircd as ${BINDIR}/ircd :" ${INSTALL} -m ${IRCDMODE} -o ${IRCDOWN} -g ${IRCDGRP} ircd ${BINDIR}/ircd -# ${INSTALL} -s -m 700 -o ${IRCDOWN} -g ${IRCDGRP} chkconf ${BINDIR} ${INSTALL} -m 600 -o ${IRCDOWN} -g ${IRCDGRP} ${top_srcdir}/doc/example.conf ${DPATH} # ( cd ${DPATH}; \ # ${TOUCH} ${MPATH}; \ @@ -316,13 +314,13 @@ install-no-symlink: build mkbindir uninstall: @if [ "${BINDIR}" != "${DPATH}" ]; then \ - echo "${RM} -f ${BINDIR}/${SYMLINK} ${BINDIR}/ircd.9* ${BINDIR}/chkconf"; \ - ${RM} -f ${BINDIR}/${SYMLINK} ${BINDIR}/ircd.9* ${BINDIR}/chkconf; \ + echo "${RM} -f ${BINDIR}/${SYMLINK} ${BINDIR}/ircd.9*"; \ + ${RM} -f ${BINDIR}/${SYMLINK} ${BINDIR}/ircd.9*; \ fi @echo "Please remove the contents of ${DPATH} manually" clean: - ${RM} -f *.o *.bak ircd version.c chkconf umkpasswd ircd_osdep.c chattr.tab.c table_gen y.tab.* lex.yy.* + ${RM} -f *.o *.bak ircd version.c umkpasswd ircd_osdep.c chattr.tab.c table_gen y.tab.* lex.yy.* distclean: clean ${RM} -f Makefile stamp-m diff --git a/ircd/chkconf.c b/ircd/chkconf.c deleted file mode 100644 index 0169c63..0000000 --- a/ircd/chkconf.c +++ /dev/null @@ -1,611 +0,0 @@ -/* - * IRC - Internet Relay Chat, ircd/chkconf.c - * Copyright (C) 1993 Darren Reed - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 1, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id$ - */ -#include "config.h" - -#include "s_conf.h" -#include "client.h" -#include "class.h" -#include "fileio.h" -#include "ircd.h" -#include "ircd_alloc.h" -#include "ircd_chattr.h" -#include "ircd_string.h" -#include "sys.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * stuff that isn't used by s_conf.c anymore - */ -#define CONF_ME 0x0040 -#define CONF_KILL 0x0080 -#define CONF_ADMIN 0x0100 -#define CONF_CLASS 0x0400 -#define CONF_LISTEN_PORT 0x2000 -#define CONF_IPKILL 0x00010000 -#define CONF_CRULEALL 0x00200000 -#define CONF_CRULEAUTO 0x00400000 -#define CONF_TLINES 0x00800000 - -#define CONF_KLINE (CONF_KILL | CONF_IPKILL) -#define CONF_CRULE (CONF_CRULEALL | CONF_CRULEAUTO) - -/* DEFAULTMAXSENDQLENGTH went into the features subsystem... */ -#define DEFAULTMAXSENDQLENGTH 40000 - -/* - * For the connect rule patch.. these really should be in a header, - * but i see h.h isn't included for some reason.. so they're here. - */ -struct CRuleNode; - -struct CRuleNode* crule_parse(const char* rule); -void crule_free(struct CRuleNode** elem); - -static void new_class(int cn); -static char confchar(unsigned int status); -static char *getfield(char *newline); -static int validate(struct ConfItem *top); -static struct ConfItem *chk_initconf(void); -static struct ConnectionClass *get_class(int cn, int ism); - -static int numclasses = 0, *classarr = (int *)NULL, debugflag = 0; -static char *chk_configfile = ""; -static char nullfield[] = ""; -static char maxsendq[12]; - -/* A few dummy variables and functions needed to link with runmalloc.o */ -time_t CurrentTime; -struct Client me; -void debug(int level, const char *form, ...) -{ - va_list vl; - va_start(vl, form); - if (debugflag > 8) - { - vfprintf(stderr, form, vl); - fprintf(stderr, "\n"); - } - va_end(vl); -} -void sendto_one(struct Client *to, char *pattern, ...) -{ -} -char *rpl_str(int numeric) -{ - return ""; -} - -int main(int argc, char *argv[]) -{ - const char *dpath = "./"; - chk_configfile = "ircd.conf"; - - while (argc > 1) - { - if (*argv[1] == '-') - { - switch (argv[1][1]) - { - case 'd': - if (argc > 2) - { - dpath = argv[2]; - --argc; - ++argv; - } - else - { - fprintf(stderr, "-d: Missing path\n"); - exit(-1); - } - break; - case 'x': - debugflag = 1; - if (isdigit(argv[1][2])) - debugflag = atoi(&argv[1][2]); - break; - default: - fprintf(stderr, "Ignoring unknown option -%c\n", argv[1][1]); - } - } - else - chk_configfile = argv[1]; - --argc; - ++argv; - } - - if (chdir(dpath)) - { - fprintf(stderr, "chdir(\"%s\") : %s\n", dpath, - (strerror(errno)) ? strerror(errno) : "Unknown error"); - exit(-1); - } - else if (debugflag > 1) - fprintf(stderr, "chdir(\"%s\") : Success", dpath); - - new_class(0); - - return validate(chk_initconf()); -} - -/* - * chk_initconf() - * - * Read configuration file. - * - * Returns -1, if file cannot be opened - * 0, if file opened. - */ -static struct ConfItem *chk_initconf(void) -{ - FBFILE *file; - char line[512]; - char *tmp; - struct CRuleNode* crule; - int ccount = 0, flags = 0; - struct ConfItem *aconf = NULL, *ctop = NULL; - - fprintf(stderr, "chk_initconf(): ircd.conf = %s\n", chk_configfile); - if (NULL == (file = fbopen(chk_configfile, "r"))) - { - perror("open"); - return NULL; - } - - while (fbgets(line, sizeof(line) - 1, file)) - { - if (aconf) { - if (aconf->host) - MyFree(aconf->host); - if (aconf->passwd) - MyFree(aconf->passwd); - if (aconf->name) - MyFree(aconf->name); - } - else { - aconf = (struct ConfItem*) MyMalloc(sizeof(struct ConfItem)); - assert(0 != aconf); - } - aconf->host = NULL; - aconf->passwd = NULL; - aconf->name = NULL; - aconf->conn_class = NULL; - aconf->dns_pending = 0; - - if ((tmp = strchr(line, '\n'))) - *tmp = 0; - /* - * Do quoting of characters and # detection. - */ - for (tmp = line; *tmp; ++tmp) { - if (*tmp == '\\') { - switch (*(tmp + 1)) { - case 'n': - *tmp = '\n'; - break; - case 'r': - *tmp = '\r'; - break; - case 't': - *tmp = '\t'; - break; - case '0': - *tmp = '\0'; - break; - default: - *tmp = *(tmp + 1); - break; - } - if ('\0' == *(tmp + 1)) - break; - else - strcpy(tmp + 1, tmp + 2); - } - else if (*tmp == '#') - *tmp = '\0'; - } - if (!*line || *line == '#' || *line == '\n' || - *line == ' ' || *line == '\t') - continue; - - if (line[1] != ':') - { - fprintf(stderr, "ERROR: Bad config line (%s)\n", line); - continue; - } - - if (debugflag) - printf("\n%s\n", line); - fflush(stdout); - - tmp = getfield(line); - if (!tmp) - { - fprintf(stderr, "\tERROR: no fields found\n"); - continue; - } - - aconf->status = CONF_ILLEGAL; - - switch (*tmp) - { - case 'A': /* Name, e-mail address of administrator */ - case 'a': /* of this server. */ - aconf->status = CONF_ADMIN; - break; - case 'C': /* Server where I should try to connect */ - case 'c': /* in case of lp failures */ - ccount++; - aconf->status = CONF_SERVER; - break; - /* Connect rule */ - case 'D': - aconf->status = CONF_CRULEALL; - break; - /* Connect rule - autos only */ - case 'd': - aconf->status = CONF_CRULEAUTO; - break; - case 'H': /* Hub server line */ - case 'h': - aconf->status = CONF_HUB; - break; - case 'I': /* Just plain normal irc client trying */ - case 'i': /* to connect me */ - aconf->status = CONF_CLIENT; - break; - case 'K': /* Kill user line on irc.conf */ - aconf->status = CONF_KILL; - break; - case 'k': /* Kill user line based on IP in ircd.conf */ - aconf->status = CONF_IPKILL; - break; - /* Operator. Line should contain at least */ - /* password and host where connection is */ - case 'L': /* guaranteed leaf server */ - case 'l': - aconf->status = CONF_LEAF; - break; - /* Me. Host field is name used for this host */ - /* and port number is the number of the port */ - case 'M': - case 'm': - aconf->status = CONF_ME; - break; - case 'O': - aconf->status = CONF_OPERATOR; - break; - /* Local Operator, (limited privs --SRB) */ - case 'o': - aconf->status = CONF_LOCOP; - break; - case 'P': /* listen port line */ - case 'p': - aconf->status = CONF_LISTEN_PORT; - break; - case 'T': - case 't': - aconf->status = CONF_TLINES; - break; - case 'U': - case 'u': - aconf->status = CONF_UWORLD; - break; - case 'Y': - case 'y': - aconf->status = CONF_CLASS; - break; - default: - fprintf(stderr, "\tERROR: unknown conf line letter (%c)\n", *tmp); - break; - } - - if (IsIllegal(aconf)) - continue; - - for (;;) /* Fake loop, that I can use break here --msa */ - { - if ((tmp = getfield(NULL)) == NULL) - break; - DupString(aconf->host, tmp); - if ((tmp = getfield(NULL)) == NULL) - break; - DupString(aconf->passwd, tmp); - if ((tmp = getfield(NULL)) == NULL) - break; - DupString(aconf->name, tmp); - if ((tmp = getfield(NULL)) == NULL) - break; - aconf->port = atoi(tmp); - if ((tmp = getfield(NULL)) == NULL) - break; - if (!(aconf->status & (CONF_CLASS | CONF_ME))) - { - aconf->conn_class = get_class(atoi(tmp), 0); - break; - } - if (aconf->status & CONF_ME) - aconf->conn_class = get_class(atoi(tmp), 1); - break; - } - if (!aconf->conn_class && (aconf->status & (CONF_SERVER | - CONF_ME | CONF_OPS | CONF_CLIENT))) - { - fprintf(stderr, "\tWARNING: No class. Default 0\n"); - aconf->conn_class = get_class(0, 0); - } - /* - * If conf line is a class definition, create a class entry - * for it and make the conf_line illegal and delete it. - */ - if (aconf->status & CONF_CLASS) - { - if (!aconf->host) - { - fprintf(stderr, "\tERROR: no class #\n"); - continue; - } - if (!tmp) - { - fprintf(stderr, "\tWARNING: missing sendq field\n"); - fprintf(stderr, "\t\t default: %d\n", DEFAULTMAXSENDQLENGTH); - sprintf(maxsendq, "%d", DEFAULTMAXSENDQLENGTH); - } - else - sprintf(maxsendq, "%d", atoi(tmp)); - new_class(atoi(aconf->host)); - aconf->conn_class = get_class(atoi(aconf->host), 0); - goto print_confline; - } - - if (aconf->status & CONF_LISTEN_PORT) - { - if (!aconf->host) - fprintf(stderr, "\tERROR: %s\n", "null host field in P-line"); - else if (strchr(aconf->host, '/')) - fprintf(stderr, "\t%s\n", "WARNING: / present in P-line " - "for non-UNIXPORT configuration"); - aconf->conn_class = get_class(0, 0); - goto print_confline; - } - - if (aconf->status & CONF_SERVER && - (!aconf->host || strchr(aconf->host, '*') || strchr(aconf->host, '?'))) - { - fprintf(stderr, "\tERROR: bad host field\n"); - continue; - } - - if (aconf->status & CONF_SERVER && BadPtr(aconf->passwd)) - { - fprintf(stderr, "\tERROR: empty/no password field\n"); - continue; - } - - if (aconf->status & CONF_SERVER && !aconf->name) - { - fprintf(stderr, "\tERROR: bad name field\n"); - continue; - } - - if (aconf->status & (CONF_OPS)) - if (!strchr(aconf->host, '@')) - { - char *newhost; - int len = 3; /* *@\0 = 3 */ - - len += strlen(aconf->host); - newhost = (char *)MyMalloc(len); - sprintf(newhost, "*@%s", aconf->host); - MyFree(aconf->host); - aconf->host = newhost; - } - - /* parse the connect rules to detect errors, but free - * any allocated storage immediately -- we're just looking - * for errors.. */ - if (aconf->status & CONF_CRULE) - if ((crule = crule_parse(aconf->name)) != NULL) - crule_free(&crule); - - if (!aconf->conn_class) - aconf->conn_class = get_class(0, 0); - sprintf(maxsendq, "%d", ConfClass(aconf)); - - if ((aconf->status & CONF_ADMIN) && (!aconf->name || - !aconf->passwd || !aconf->host)) - fprintf(stderr, "ERROR: Your A: line must have 4 fields!\n"); - - if (!aconf->name) - DupString(aconf->name, nullfield); - if (!aconf->passwd) - DupString(aconf->passwd, nullfield); - if (!aconf->host) - DupString(aconf->host, nullfield); - if (aconf->status & (CONF_ME | CONF_ADMIN)) - { - if (flags & aconf->status) - fprintf(stderr, "ERROR: multiple %c-lines\n", - ToUpper(confchar(aconf->status))); - else - flags |= aconf->status; - } -print_confline: - if (debugflag > 8) - printf("(%d) (%s) (%s) (%s) (%u) (%s)\n", - aconf->status, aconf->host, aconf->passwd, - aconf->name, aconf->port, maxsendq); - fflush(stdout); - if (aconf->status & (CONF_SERVER | CONF_HUB | CONF_LEAF)) - { - aconf->next = ctop; - ctop = aconf; - aconf = NULL; - } - } - fbclose(file); - return ctop; -} - -static struct ConnectionClass *get_class(int cn, int ism) -{ - static struct ConnectionClass cls; - if (ism == 1) - { - cls.cc_class = (unsigned int)-1; - if ((cn >= 1) && (cn <= 64)) - cls.cc_class = cn; - else - fprintf(stderr, "\tWARNING: server numeric %d is not 1-64\n", cn); - } - else - { - int i = numclasses - 1; - cls.cc_class = (unsigned int)-1; - for (; i >= 0; i--) - if (classarr[i] == cn) - { - cls.cc_class = cn; - break; - } - if (i == -1) - fprintf(stderr, "\tWARNING: class %d not found\n", cn); - } - return &cls; -} - -static void new_class(int cn) -{ - numclasses++; - if (classarr && numclasses & 0xF == 0) - { - int **tmp_arr = MyMalloc(classarr * (numclasses + 0x10)); - MyFree(classarr); - memcpy(tmp_arr, classarr, classarr * (numclasses - 1)); - } - else - classarr = (int *)MyMalloc(sizeof(int) * numclasses); - classarr[numclasses - 1] = cn; -} - -/* - * field breakup for ircd.conf file. - */ -static char *getfield(char *newline) -{ - static char *line = NULL; - char *end, *field; - - if (newline) - line = newline; - if (line == NULL) - return (NULL); - - field = line; - if ((end = strchr(line, ':')) == NULL) - { - line = NULL; - if ((end = strchr(field, '\n')) == NULL) - end = field + strlen(field); - } - else - line = end + 1; - *end = '\0'; - return (field); -} - -static int validate(struct ConfItem *top) -{ - struct ConfItem *aconf, *bconf; - unsigned int otype, valid = 0; - - if (!top) - return 0; - - for (aconf = top; aconf; aconf = aconf->next) - { - if (aconf->status & CONF_MATCH) - continue; - - if (aconf->status & CONF_SERVER) - { - otype = CONF_SERVER; - - for (bconf = top; bconf; bconf = bconf->next) - { - if (bconf == aconf || !(bconf->status & otype)) - continue; - if (bconf->conn_class == aconf->conn_class && - 0 == ircd_strcmp(bconf->name, aconf->name) && - 0 == ircd_strcmp(bconf->host, aconf->host)) - { - aconf->status |= CONF_MATCH; - bconf->status |= CONF_MATCH; - break; - } - } - } - else - for (bconf = top; bconf; bconf = bconf->next) - { - if ((bconf == aconf) || !(bconf->status & CONF_SERVER)) - continue; - if (0 == ircd_strcmp(bconf->name, aconf->name)) - { - aconf->status |= CONF_MATCH; - break; - } - } - } - - fprintf(stderr, "\n"); - for (aconf = top; aconf; aconf = aconf->next) { - if (aconf->status & CONF_MATCH) - valid++; - else if ('N' != confchar(aconf->status)) - fprintf(stderr, "Unmatched %c:%s:%s:%s\n", - confchar(aconf->status), aconf->host, aconf->passwd, aconf->name); - } - return valid ? 0 : -1; -} - -static char confchar(unsigned int status) -{ - static char letrs[] = "ICNoOMKARYLPH"; - char *s = letrs; - - status &= ~(CONF_MATCH | CONF_ILLEGAL); - - for (; *s; s++, status >>= 1) - if (status & 1) - return *s; - return '-'; -} diff --git a/ircd/ircd.c b/ircd/ircd.c index b8c7cb4..f6002fe 100644 --- a/ircd/ircd.c +++ b/ircd/ircd.c @@ -85,7 +85,8 @@ extern void mem_dbg_initialise(void); *--------------------------------------------------------------------------*/ enum { BOOT_DEBUG = 1, - BOOT_TTY = 2 + BOOT_TTY = 2, + BOOT_CHKCONF = 3 }; @@ -464,7 +465,7 @@ static void check_pings(struct Event* ev) { * debugmode *--------------------------------------------------------------------------*/ static void parse_command_line(int argc, char** argv) { - const char *options = "d:f:h:ntvx:"; + const char *options = "d:f:h:nktvx:"; int opt; if (thisServer.euid != thisServer.uid) @@ -475,6 +476,7 @@ static void parse_command_line(int argc, char** argv) { */ while ((opt = getopt(argc, argv, options)) != EOF) switch (opt) { + case 'k': thisServer.bootopt |= BOOT_CHKCONF; break; case 'n': case 't': thisServer.bootopt |= BOOT_TTY; break; case 'd': dpath = optarg; break; @@ -641,15 +643,13 @@ int main(int argc, char **argv) { !check_file_access(configfile, 'C', R_OK)) return 4; - debug_init(thisServer.bootopt & BOOT_TTY); - daemon_init(thisServer.bootopt & BOOT_TTY); event_init(MAXCONNECTIONS); setup_signals(); feature_init(); /* initialize features... */ log_init(*argv); set_nomem_handler(outofmemory); - + if (!init_string()) { log_write(LS_SYSTEM, L_CRIT, 0, "Failed to initialize string module"); return 6; @@ -677,6 +677,13 @@ int main(int argc, char **argv) { return 7; } + if(thisServer.bootopt & BOOT_CHKCONF) { + fprintf(stdout, "Configuration file checked okay.\n"); + return 0; + } + + debug_init(thisServer.bootopt & BOOT_TTY); + daemon_init(thisServer.bootopt & BOOT_TTY); if (check_pid()) { Debug((DEBUG_FATAL, "Failed to acquire PID file lock after fork")); exit(2);