diff --git a/include/struct.h b/include/struct.h index b3d184d8c..c1064d724 100644 --- a/include/struct.h +++ b/include/struct.h @@ -722,6 +722,7 @@ struct MOTDLine { struct LoopStruct { unsigned do_garbage_collect : 1; + unsigned config_test : 1; unsigned ircd_booted : 1; unsigned ircd_forked : 1; unsigned do_bancheck : 1; /* perform *line bancheck? */ diff --git a/src/conf.c b/src/conf.c index 1d1321cbd..5a1e0dd6b 100644 --- a/src/conf.c +++ b/src/conf.c @@ -1953,7 +1953,7 @@ int init_conf(char *rootconf, int rehash) RunHook0(HOOKTYPE_REHASH_COMPLETE); } postconf(); - config_status("Configuration loaded without any problems."); + config_status("Configuration loaded."); clicap_post_rehash(); return 0; } diff --git a/src/ircd.c b/src/ircd.c index 4500a7f94..717cfdc37 100644 --- a/src/ircd.c +++ b/src/ircd.c @@ -1113,6 +1113,9 @@ int InitUnrealIRCd(int argc, char *argv[]) case 'C': config_verbose = atoi(p); break; + case 'c': + loop.config_test = 1; + break; case 'x': #ifdef DEBUGMODE debuglevel = atoi(p); @@ -1227,7 +1230,8 @@ int InitUnrealIRCd(int argc, char *argv[]) init_CommandHash(); initwhowas(); initstats(); - DeleteTempModules(); + if (!loop.config_test) + DeleteTempModules(); booted = FALSE; #if !defined(_WIN32) && !defined(_AMIGA) && !defined(OSXTIGER) && DEFAULT_PERMISSIONS != 0 /* Hack to stop people from being able to read the config file */ @@ -1277,6 +1281,12 @@ int InitUnrealIRCd(int argc, char *argv[]) #endif exit(9); } + if (loop.config_test) + { + ircd_log(LOG_ERROR, "Configuration test passed OK"); + fflush(stderr); + exit(0); + } #ifndef _WIN32 fprintf(stderr, "Dynamic configuration initialized.. booting IRCd.\n"); #endif diff --git a/src/misc.c b/src/misc.c index 238cefd23..f4c340940 100644 --- a/src/misc.c +++ b/src/misc.c @@ -123,6 +123,11 @@ void ircd_log(int flags, FORMAT_STRING(const char *format), ...) return; recursion_trap = 1; + + /* NOTE: past this point you CANNOT just 'return'. + * You must set 'recursion_trap = 0;' before 'return'! + */ + va_start(ap, format); ircvsnprintf(buf, sizeof(buf), format, ap); va_end(ap); @@ -134,6 +139,13 @@ void ircd_log(int flags, FORMAT_STRING(const char *format), ...) if (!loop.ircd_forked && (flags & LOG_ERROR)) fprintf(stderr, "%s", buf); + /* In case of './unrealircd configtest': don't write to log file, only to stderr */ + if (loop.config_test) + { + recursion_trap = 0; + return; + } + for (logs = conf_log; logs; logs = logs->next) { #ifdef HAVE_SYSLOG if (!strcasecmp(logs->file, "syslog") && logs->flags & flags) { diff --git a/src/modules.c b/src/modules.c index 7c2da04c8..2932728df 100644 --- a/src/modules.c +++ b/src/modules.c @@ -75,7 +75,8 @@ void *obsd_dlsym(void *handle, char *symbol) void deletetmp(char *path) { #ifndef NOREMOVETMP - remove(path); + if (!loop.config_test) + remove(path); #endif } @@ -309,25 +310,34 @@ char *Module_Create(char *path_) if (module_already_in_testing(relpath)) return 0; - tmppath = unreal_mktemp(TMPDIR, unreal_getmodfilename(path)); - if (!tmppath) - return "Unable to create temporary file!"; - if (!file_exists(path)) { snprintf(errorbuf, sizeof(errorbuf), "Cannot open module file: %s", strerror(errno)); return errorbuf; } - /* For OpenBSD, do not do a hardlinkink attempt first because it checks inode - * numbers to see if a certain module is already loaded. -- Syzop - * EDIT (2009): Looks like Linux got smart too, from now on we always copy.... - */ - ret = unreal_copyfileex(path, tmppath, 0); - if (!ret) + + if (loop.config_test) { - snprintf(errorbuf, sizeof(errorbuf), "Failed to copy module file."); - return errorbuf; + /* For './unrealircd configtest' we don't have to do any copying and shit */ + tmppath = path; + } else { + tmppath = unreal_mktemp(TMPDIR, unreal_getmodfilename(path)); + if (!tmppath) + return "Unable to create temporary file!"; + + /* We have to copy the module, because otherwise the dynamic loader + * will not load the new .so if we rehash while holding the original .so + * We used to hardlink here instead of copy, but then OpenBSD and Linux + * got smart and detected that, so now we always copy. + */ + ret = unreal_copyfileex(path, tmppath, 0); + if (!ret) + { + snprintf(errorbuf, sizeof(errorbuf), "Failed to copy module file."); + return errorbuf; + } } + if ((Mod = irc_dlopen(tmppath, RTLD_NOW))) { /* We have engaged the borg cube. Scan for lifesigns. */ diff --git a/unrealircd.in b/unrealircd.in index 2a6a43b9d..dfce6cd8b 100644 --- a/unrealircd.in +++ b/unrealircd.in @@ -108,6 +108,8 @@ elif [ "$1" = "croncheck" ] ; then # PID file not found or found but stale echo "UnrealIRCd is not running. Starting now..." $0 start +elif [ "$1" = "configtest" ] ; then + @BINDIR@/unrealircd -c elif [ "$1" = "reloadtls" ] ; then echo "Reloading SSL/TLS certificates" if [ ! -r $PID_FILE ] ; then