summaryrefslogtreecommitdiffstats
path: root/syslogd.c
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 /syslogd.c
parent54751c7e6e374c130d6d6d5cee5db493f7919fef (diff)
downloadrsyslog-f5250a3a92ec4c1738556f3cc5139dbc15579add.zip
rsyslog-f5250a3a92ec4c1738556f3cc5139dbc15579add.tar.gz
rsyslog-f5250a3a92ec4c1738556f3cc5139dbc15579add.tar.xz
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.
Diffstat (limited to 'syslogd.c')
-rw-r--r--syslogd.c251
1 files changed, 186 insertions, 65 deletions
diff --git a/syslogd.c b/syslogd.c
index 0a786c1..bb16152 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))