summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-04-04 08:34:31 +0000
committerRainer Gerhards <rgerhards@adiscon.com>2008-04-04 08:34:31 +0000
commitf5250a3a92ec4c1738556f3cc5139dbc15579add (patch)
tree796ab385480e9d1cb7079c4c3b90378b0e254466
parent54751c7e6e374c130d6d6d5cee5db493f7919fef (diff)
downloadrsyslog-f5250a3a92ec4c1738556f3cc5139dbc15579add.tar.gz
rsyslog-f5250a3a92ec4c1738556f3cc5139dbc15579add.tar.xz
rsyslog-f5250a3a92ec4c1738556f3cc5139dbc15579add.zip
changed command line processing. -v, -M, -c options are now parsed and
processed before all other options. Inter-option dependencies have been relieved. Among others, permits to specify intial module load path via -M only (not the environment) which makes it much easier to work with non-standard module library locations. Thanks to varmojfekoj for suggesting this change. Matches bugzilla bug 55.
-rw-r--r--ChangeLog6
-rw-r--r--glbl.h1
-rw-r--r--modules.c11
-rw-r--r--obj.c7
-rw-r--r--syslogd.c251
-rw-r--r--wtp.h1
6 files changed, 208 insertions, 69 deletions
diff --git a/ChangeLog b/ChangeLog
index 6371a746..0024a47f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,12 @@ Version 3.17.0 (rgerhards), 2008-04-??
the full size, but will modify the outputs so that only 32 characters
max are used by default. If you need large tags in the output, you need
to provide custom templates.
+- changed command line processing. -v, -M, -c options are now parsed
+ and processed before all other options. Inter-option dependencies
+ have been relieved. Among others, permits to specify intial module
+ load path via -M only (not the environment) which makes it much
+ easier to work with non-standard module library locations. Thanks
+ to varmojfekoj for suggesting this change. Matches bugzilla bug 55.
---------------------------------------------------------------------------
Version 3.15.1 (rgerhards), 2008-04-??
- disabled atomic operations for the time being because they introduce some
diff --git a/glbl.h b/glbl.h
index fb55fb76..6d08ddd5 100644
--- a/glbl.h
+++ b/glbl.h
@@ -33,6 +33,7 @@
#define glblGetIOBufSize() 4096 /* size of the IO buffer, e.g. for strm class */
+extern uchar *glblModPath; /* module load path */
extern uchar *pszWorkDir;
#define glblGetWorkDir() (pszWorkDir == NULL ? (uchar*) "" : pszWorkDir)
diff --git a/modules.c b/modules.c
index 86ee64a5..623a2f10 100644
--- a/modules.c
+++ b/modules.c
@@ -783,6 +783,17 @@ BEGINAbstractObjClassInit(module, 1, OBJ_IS_CORE_MODULE) /* class, version - CHA
SetModDir(pModPath);
}
+ /* now check if another module path was set via the command line (-M)
+ * if so, that overrides the environment. Please note that we must use
+ * a global setting here because the command line parser can NOT call
+ * into the module object, because it is not initialized at that point. So
+ * instead a global setting is changed and we pick it up as soon as we
+ * initialize -- rgerhards, 2008-04-04
+ */
+ if(glblModPath != NULL) {
+ SetModDir(glblModPath);
+ }
+
/* request objects we use */
CHKiRet(objUse(errmsg, CORE_COMPONENT));
ENDObjClassInit(module)
diff --git a/obj.c b/obj.c
index d408c4bb..51c7c9df 100644
--- a/obj.c
+++ b/obj.c
@@ -1073,7 +1073,7 @@ RegisterObj(uchar *pszObjName, objInfo_t *pInfo)
if(i >= OBJ_NUM_IDS) ABORT_FINALIZE(RS_RET_OBJ_REGISTRY_OUT_OF_SPACE);
arrObjInfo[i] = pInfo;
- dbgprintf("object '%s' successfully registered with index %d, qIF %p\n", pszObjName, i, pInfo->QueryIF);
+ /* DEV debug only: dbgprintf("object '%s' successfully registered with index %d, qIF %p\n", pszObjName, i, pInfo->QueryIF); */
finalize_it:
if(iRet != RS_RET_OK) {
@@ -1113,7 +1113,7 @@ UnregisterObj(uchar *pszObjName, objInfo_t *pInfo)
ABORT_FINALIZE(RS_RET_OBJ_NOT_REGISTERED);
InfoDestruct(&arrObjInfo[i]);
- dbgprintf("object '%s' successfully unregistered with index %d\n", pszObjName, i);
+ /* DEV debug only: dbgprintf("object '%s' successfully unregistered with index %d\n", pszObjName, i); */
finalize_it:
if(iRet != RS_RET_OK) {
@@ -1137,7 +1137,7 @@ UseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf)
objInfo_t *pObjInfo;
- dbgprintf("source file %s requests object '%s', ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded);
+ /* DEV debug only: dbgprintf("source file %s requests object '%s', ifIsLoaded %d\n", srcFile, pObjName, pIf->ifIsLoaded); */
if(pIf->ifIsLoaded == 1) {
ABORT_FINALIZE(RS_RET_OK); /* we are already set */
@@ -1170,7 +1170,6 @@ UseObj(char *srcFile, uchar *pObjName, uchar *pObjFile, interface_t *pIf)
}
/* if we reach this point, we have a valid pObjInfo */
- //if(pObjInfo->pModInfo != NULL) { /* NULL means core module */
if(pObjFile != NULL) { /* NULL means core module */
module.Use(srcFile, pObjInfo->pModInfo); /* increase refcount */
}
diff --git a/syslogd.c b/syslogd.c
index 0a786c1f..bb161528 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -302,6 +302,7 @@ static int bEscapeCCOnRcv = 1; /* escape control characters on reception: 0 - n
int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
uchar *pszWorkDir = NULL;/* name of rsyslog's spool directory (without trailing slash) */
+extern uchar *glblModPath = NULL; /* module load path - only used during initial init, only settable via -M command line option */
/* end global config file state variables */
char LocalHostName[MAXHOSTNAMELEN+1];/* our hostname - read-only after startup */
@@ -2197,8 +2198,7 @@ init(void)
pDfltProgNameCmp = NULL;
eDfltHostnameCmpMode = HN_NO_COMP;
- dbgprintf("rsyslog %s.\n", VERSION);
- dbgprintf("Called init.\n");
+ dbgprintf("rsyslog %s - called init()\n", VERSION);
/* delete the message queue, which also flushes all messages left over */
if(pMsgQueue != NULL) {
@@ -2792,7 +2792,6 @@ static void mainThread()
pTmp = template_StdPgSQLFmt;
tplLastStaticInit(tplAddLine(" StdPgSQLFmt", &pTmp));
- dbgprintf("Starting.\n");
init();
if(Debug) {
dbgprintf("Debugging enabled, SIGUSR1 to turn off debugging.\n");
@@ -2809,6 +2808,7 @@ static void mainThread()
* do the init() and then restart things.
* rgerhards, 2005-10-24
*/
+ dbgprintf("initialization completed, transitioning to regular run mode\n");
mainloop();
ENDfunc
@@ -2962,6 +2962,72 @@ dbgprintf("post strExit()\n");
}
+/* some support for command line option parsing. Any non-trivial options must be
+ * buffered until the complete command line has been parsed. This is necessary to
+ * prevent dependencies between the options. That, in turn, means we need to have
+ * something that is capable of buffering options and there values. The follwing
+ * functions handle that.
+ * rgerhards, 2008-04-04
+ */
+typedef struct bufOpt {
+ struct bufOpt *pNext;
+ char optchar;
+ char *arg;
+} bufOpt_t;
+static bufOpt_t *bufOptRoot = NULL;
+static bufOpt_t *bufOptLast = NULL;
+
+/* add option buffer */
+static rsRetVal
+bufOptAdd(char opt, char *arg)
+{
+ DEFiRet;
+ bufOpt_t *pBuf;
+
+ if((pBuf = malloc(sizeof(bufOpt_t))) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ pBuf->optchar = opt;
+ pBuf->arg = arg;
+ pBuf->pNext = NULL;
+
+ if(bufOptLast == NULL) {
+ bufOptRoot = pBuf; /* then there is also no root! */
+ } else {
+ bufOptLast->pNext = pBuf;
+ }
+ bufOptLast = pBuf;
+
+finalize_it:
+ RETiRet;
+}
+
+
+
+/* remove option buffer from top of list, return values and destruct buffer itself.
+ * returns RS_RET_END_OF_LINKEDLIST when no more options are present.
+ * (we use int *opt instead of char *opt to keep consistent with getopt())
+ */
+static rsRetVal
+bufOptRemove(int *opt, char **arg)
+{
+ DEFiRet;
+ bufOpt_t *pBuf;
+
+ if(bufOptRoot == NULL)
+ ABORT_FINALIZE(RS_RET_END_OF_LINKEDLIST);
+ pBuf = bufOptRoot;
+
+ *opt = pBuf->optchar;
+ *arg = pBuf->arg;
+
+ bufOptRoot = pBuf->pNext;
+ free(pBuf);
+
+finalize_it:
+ RETiRet;
+}
+
/* This is the main entry point into rsyslogd. Over time, we should try to
* modularize it a bit more...
@@ -2981,8 +3047,106 @@ int realMain(int argc, char **argv)
int bIsFirstOption = 1;
int bEOptionWasGiven = 0;
int bImUxSockLoaded = 0; /* already generated a $ModLoad imuxsock? */
+ char *arg; /* for command line option processing */
uchar legacyConfLine[80];
+ /* first, parse the command line options. We do not carry out any actual work, just
+ * see what we should do. This relieves us from certain anomalies and we can process
+ * the parameters down below in the correct order. For example, we must know the
+ * value of -M before we can do the init, but at the same time we need to have
+ * the base classes init before we can process most of the options. Now, with the
+ * split of functionality, this is no longer a problem. Thanks to varmofekoj for
+ * suggesting this algo.
+ * Note: where we just need to set some flags and can do so without knowledge
+ * of other options, we do this during the inital option processing. With later
+ * versions (if a dependency on -c option is introduced), we must move that code
+ * to other places, but I think it is quite appropriate and saves code to do this
+ * only when actually neeeded.
+ * rgerhards, 2008-04-04
+ */
+ while ((ch = getopt(argc, argv, "46Ac:dehi:f:g:l:m:M:nqQr::s:t:u:vwx")) != EOF) {
+ switch((char)ch) {
+ case '4':
+ case '6':
+ case 'A':
+ case 'a':
+ case 'f': /* configuration file */
+ case 'h':
+ case 'i': /* pid file name */
+ case 'l':
+ case 'm': /* mark interval */
+ case 'n': /* don't fork */
+ case 'o':
+ case 'p':
+ case 'q': /* add hostname if DNS resolving has failed */
+ case 'Q': /* dont resolve hostnames in ACL to IPs */
+ case 's':
+ case 'u': /* misc user settings */
+ case 'w': /* disable disallowed host warnigs */
+ case 'x': /* disable dns for remote messages */
+ CHKiRet(bufOptAdd(ch, optarg));
+ break;
+ case 'c': /* compatibility mode */
+ if(!bIsFirstOption) {
+ fprintf(stderr, "-c option MUST be specified as the first option - aborting...\n");
+ usage();
+ exit(1);
+ }
+ iCompatibilityMode = atoi(optarg);
+ break;
+ case 'd': /* debug - must be handled now, so that debug is active during init! */
+ Debug = 1;
+ break;
+ case 'e': /* log every message (no repeat message supression) */
+ fprintf(stderr, "note: -e option is no longer supported, every message is now logged by default\n");
+ bEOptionWasGiven = 1;
+ break;
+ case 'g': /* enable tcp gssapi logging */
+#if defined(SYSLOG_INET) && defined(USE_GSSAPI)
+ CHKiRet(bufOptAdd('g', optarg));
+#else
+ fprintf(stderr, "rsyslogd: -g not valid - not compiled with gssapi support");
+#endif
+ break;
+ case 'M': /* default module load path -- this MUST be carried out immediately! */
+ glblModPath = (uchar*) optarg;
+ break;
+ case 'r': /* accept remote messages */
+#ifdef SYSLOG_INET
+ CHKiRet(bufOptAdd(ch, optarg));
+#else
+ fprintf(stderr, "rsyslogd: -r not valid - not compiled with network support\n");
+#endif
+ break;
+ case 't': /* enable tcp logging */
+#ifdef SYSLOG_INET
+ CHKiRet(bufOptAdd(ch, optarg));
+#else
+ fprintf(stderr, "rsyslogd: -t not valid - not compiled with network support\n");
+#endif
+ break;
+ case 'v': /* MUST be carried out immediately! */
+ printVersion();
+ exit(0); /* exit for -v option - so this is a "good one" */
+ case '?':
+ default:
+ usage();
+ }
+ bIsFirstOption = 0; /* we already saw an option character */
+ }
+
+ if ((argc -= optind))
+ usage();
+
+ dbgprintf("rsyslogd %s startup, compatibility mode %d, module path '%s'\n",
+ VERSION, iCompatibilityMode, glblModPath == NULL ? "" : (char*)glblModPath);
+
+ /* we are done with the initial option parsing and processing. Now we init the system. */
+
+ ppid = getpid();
+
+ if(chdir ("/") != 0)
+ fprintf(stderr, "Can not do 'cd /' - still trying to run\n");
CHKiRet_Hdlr(InitGlobalClasses()) {
fprintf(stderr, "rsyslogd initializiation failed - global classes could not be initialized.\n"
@@ -3005,14 +3169,10 @@ int realMain(int argc, char **argv)
exit(1); /* "good" exit, leaving at init for fatal error */
}
- ppid = getpid();
-
- if(chdir ("/") != 0)
- fprintf(stderr, "Can not do 'cd /' - still trying to run\n");
+ /* END core initializations - we now come back to carrying out command line options*/
- /* END core initializations */
-
- while ((ch = getopt(argc, argv, "46Ac:dehi:f:g:l:m:M:nqQr::s:t:u:vwx")) != EOF) {
+ while((iRet = bufOptRemove(&ch, &arg)) == RS_RET_OK) {
+dbgprintf("deque option %c, optarg '%s'\n", ch, arg);
switch((char)ch) {
case '4':
family = PF_INET;
@@ -3029,39 +3189,20 @@ int realMain(int argc, char **argv)
legacyOptsEnq((uchar *) "ModLoad imuxsock");
bImUxSockLoaded = 1;
}
- snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "addunixlistensocket %s", optarg);
+ snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "addunixlistensocket %s", arg);
legacyOptsEnq(legacyConfLine);
} else {
fprintf(stderr, "error -a is no longer supported, use module imuxsock instead");
}
break;
- case 'c': /* compatibility mode */
- if(!bIsFirstOption) {
- fprintf(stderr, "-c option MUST be specified as the first option - aborting...\n");
- usage();
- exit(1);
- }
- iCompatibilityMode = atoi(optarg);
- break;
- case 'd': /* debug */
- Debug = 1;
- break;
- case 'e': /* log every message (no repeat message supression) */
- fprintf(stderr, "note: -e option is no longer supported, every message is now logged by default\n");
- bEOptionWasGiven = 1;
- break;
case 'f': /* configuration file */
- ConfFile = (uchar*) optarg;
+ ConfFile = (uchar*) arg;
break;
case 'g': /* enable tcp gssapi logging */
-#if defined(SYSLOG_INET) && defined(USE_GSSAPI)
if(iCompatibilityMode < 3) {
- legacyOptsParseTCP(ch, optarg);
+ legacyOptsParseTCP(ch, arg);
} else
fprintf(stderr, "-g option only supported in compatibility modes 0 to 2 - ignored\n");
-#else
- fprintf(stderr, "rsyslogd: -g not valid - not compiled with gssapi support");
-#endif
break;
case 'h':
if(iCompatibilityMode < 3) {
@@ -3071,25 +3212,22 @@ int realMain(int argc, char **argv)
}
break;
case 'i': /* pid file name */
- PidFile = optarg;
+ PidFile = arg;
break;
case 'l':
if (LocalHosts) {
fprintf (stderr, "rsyslogd: Only one -l argument allowed, the first one is taken.\n");
} else {
- LocalHosts = crunch_list(optarg);
+ LocalHosts = crunch_list(arg);
}
break;
case 'm': /* mark interval */
if(iCompatibilityMode < 3) {
- MarkInterval = atoi(optarg) * 60;
+ MarkInterval = atoi(arg) * 60;
} else
fprintf(stderr,
"-m option only supported in compatibility modes 0 to 2 - ignored\n");
break;
- case 'M': /* default module load path */
- module.SetModDir((uchar*)optarg);
- break;
case 'n': /* don't fork */
NoFork = 1;
break;
@@ -3110,7 +3248,7 @@ int realMain(int argc, char **argv)
legacyOptsEnq((uchar *) "ModLoad imuxsock");
bImUxSockLoaded = 1;
}
- snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "SystemLogSocketName %s", optarg);
+ snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "SystemLogSocketName %s", arg);
legacyOptsEnq(legacyConfLine);
} else {
fprintf(stderr, "error -p is no longer supported, use module imuxsock instead");
@@ -3122,42 +3260,30 @@ int realMain(int argc, char **argv)
*net.pACLDontResolve = 1;
break;
case 'r': /* accept remote messages */
-#ifdef SYSLOG_INET
if(iCompatibilityMode < 3) {
legacyOptsEnq((uchar *) "ModLoad imudp");
- snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "UDPServerRun %s", optarg);
+ snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "UDPServerRun %s", arg);
legacyOptsEnq(legacyConfLine);
} else
- fprintf(stderr,
- "-r option only supported in compatibility modes 0 to 2 - ignored\n");
-#else
- fprintf(stderr, "rsyslogd: -r not valid - not compiled with network support\n");
-#endif
+ fprintf(stderr, "-r option only supported in compatibility modes 0 to 2 - ignored\n");
break;
case 's':
if (StripDomains) {
fprintf (stderr, "rsyslogd: Only one -s argument allowed, the first one is taken.\n");
} else {
- StripDomains = crunch_list(optarg);
+ StripDomains = crunch_list(arg);
}
break;
case 't': /* enable tcp logging */
-#ifdef SYSLOG_INET
if(iCompatibilityMode < 3) {
- legacyOptsParseTCP(ch, optarg);
+ legacyOptsParseTCP(ch, arg);
} else
fprintf(stderr, "-t option only supported in compatibility modes 0 to 2 - ignored\n");
-#else
- fprintf(stderr, "rsyslogd: -t not valid - not compiled with network support\n");
-#endif
break;
case 'u': /* misc user settings */
- if(atoi(optarg) == 1)
+ if(atoi(arg) == 1)
bParseHOSTNAMEandTAG = 0;
break;
- case 'v':
- printVersion();
- exit(0); /* exit for -v option - so this is a "good one" */
case 'w': /* disable disallowed host warnigs */
option_DisallowWarning = 0;
break;
@@ -3168,15 +3294,12 @@ int realMain(int argc, char **argv)
default:
usage();
}
- bIsFirstOption = 0; /* we already saw an option character */
}
- if ((argc -= optind))
- usage();
+ if(iRet != RS_RET_END_OF_LINKEDLIST)
+ FINALIZE;
- /* TODO: this should go away at a reasonable stage of v3 development.
- * rgerhards, 2007-12-19
- */
+ /* process compatibility mode settings */
if(iCompatibilityMode < 3) {
errmsg.LogError(NO_ERRCODE, "WARNING: rsyslogd is running in compatibility mode. Automatically "
"generated config directives may interfer with your rsyslog.conf settings. "
@@ -3202,7 +3325,7 @@ int realMain(int argc, char **argv)
checkPermissions();
thrdInit();
- if ( !(Debug || NoFork) )
+ if( !(Debug || NoFork) )
{
dbgprintf("Checking pidfile.\n");
if (!check_pid(PidFile))
@@ -3241,8 +3364,6 @@ int realMain(int argc, char **argv)
else
debugging_on = 1;
- dbgprintf("Compatibility Mode: %d\n", iCompatibilityMode);
-
/* tuck my process id away */
dbgprintf("Writing pidfile %s.\n", PidFile);
if (!check_pid(PidFile))
diff --git a/wtp.h b/wtp.h
index b928b149..e47f9fe6 100644
--- a/wtp.h
+++ b/wtp.h
@@ -100,6 +100,7 @@ rsRetVal wtpShutdownAll(wtp_t *pThis, wtpState_t tShutdownCmd, struct timespec *
int wtpGetCurNumWrkr(wtp_t *pThis, int bLockMutex);
PROTOTYPEObjClassInit(wtp);
PROTOTYPEpropSetMethFP(wtp, pfChkStopWrkr, rsRetVal(*pVal)(void*, int));
+PROTOTYPEpropSetMethFP(wtp, pfRateLimiter, rsRetVal(*pVal)(void*));
PROTOTYPEpropSetMethFP(wtp, pfIsIdle, rsRetVal(*pVal)(void*, int));
PROTOTYPEpropSetMethFP(wtp, pfDoWork, rsRetVal(*pVal)(void*, void*, int));
PROTOTYPEpropSetMethFP(wtp, pfOnIdle, rsRetVal(*pVal)(void*, int));