2 * \brief This is the main file of the rsyslogd daemon.
4 * Please visit the rsyslog project at
6 * http://www.rsyslog.com
8 * to learn more about it and discuss any questions you may have.
10 * rsyslog had initially been forked from the sysklogd project.
11 * I would like to express my thanks to the developers of the sysklogd
12 * package - without it, I would have had a much harder start...
14 * Please note that while rsyslog started from the sysklogd code base,
15 * it nowadays has almost nothing left in common with it. Allmost all
16 * parts of the code have been rewritten.
18 * This Project was intiated and is maintained by
19 * Rainer Gerhards <rgerhards@hq.adiscon.com>. See
20 * AUTHORS to learn who helped make it become a reality.
22 * If you have questions about rsyslogd in general, please email
23 * info@adiscon.com. To learn more about rsyslogd, please visit
24 * http://www.rsyslog.com.
26 * \author Rainer Gerhards <rgerhards@adiscon.com>
28 * Some initial modifications on the sysklogd package to support
29 * liblogging. These have actually not yet been merged to the
30 * source you see currently (but they hopefully will)
33 * Restarted the modifications of sysklogd. This time, we
34 * focus on a simpler approach first. The initial goal is to
35 * provide MySQL database support (so that syslogd can log
38 * rsyslog - An Enhanced syslogd Replacement.
39 * Copyright 2003-2008 Rainer Gerhards and Adiscon GmbH.
41 * This file is part of rsyslog.
43 * Rsyslog is free software: you can redistribute it and/or modify
44 * it under the terms of the GNU General Public License as published by
45 * the Free Software Foundation, either version 3 of the License, or
46 * (at your option) any later version.
48 * Rsyslog is distributed in the hope that it will be useful,
49 * but WITHOUT ANY WARRANTY; without even the implied warranty of
50 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51 * GNU General Public License for more details.
53 * You should have received a copy of the GNU General Public License
54 * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>.
56 * A copy of the GPL can be found in the file "COPYING" in this distribution.
61 /* change the following setting to e.g. 32768 if you would like to
62 * support large message sizes for IHE (32k is the current maximum
63 * needed for IHE). I was initially tempted to increase it to 32k,
64 * but there is a large memory footprint with the current
65 * implementation in rsyslog. This will change as the processing
66 * changes, but I have re-set it to 1k, because the vast majority
67 * of messages is below that and the memory savings is huge, at
68 * least compared to the overall memory footprint.
70 * If you intend to receive Windows Event Log data (e.g. via
71 * EventReporter - www.eventreporter.com), you might want to
72 * increase this number to an even higher value, as event
73 * log messages can be very lengthy.
74 * rgerhards, 2005-07-05
76 * during my recent testing, it showed that 4k seems to be
77 * the typical maximum for UDP based syslog. This is a IP stack
78 * restriction. Not always ... but very often. If you go beyond
79 * that value, be sure to test that rsyslogd actually does what
80 * you think it should do ;) Also, it is a good idea to check the
81 * doc set for anything on IHE - it most probably has information on
83 * rgerhards, 2005-08-05
85 * I have increased the default message size to 2048 to be in sync
86 * with recent IETF syslog standardization efforts.
87 * rgerhards, 2006-11-30
89 #define DEFUPRI (LOG_USER|LOG_NOTICE)
90 #define TIMERINTVL 30 /* interval for checking flush, mark */
108 # include <sys/errno.h>
110 #include <sys/ioctl.h>
111 #include <sys/wait.h>
112 #include <sys/file.h>
114 #if HAVE_SYS_TIMESPEC_H
115 # include <sys/timespec.h>
119 # include <sys/stat.h>
134 #include "stringbuf.h"
135 #include "syslogd-types.h"
136 #include "template.h"
137 #include "outchannel.h"
143 #include "tcpsyslog.h"
144 #include "iminternal.h"
145 #include "cfsysline.h"
147 #include "omusrmsg.h"
150 #include "omdiscard.h"
164 #include "datetime.h"
167 /* definitions for objects we access */
169 DEFobjCurrIf(datetime)
176 DEFobjCurrIf(net) /* TODO: make go away! */
179 /* forward definitions */
180 static rsRetVal GlobalClassExit(void);
182 /* We define our own set of syslog defintions so that we
183 * do not need to rely on (possibly different) implementations.
184 * 2007-07-19 rgerhards
186 /* missing definitions for solaris
190 # define LOG_AUTHPRIV LOG_AUTH
192 #define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
193 #define LOG_FTP (11<<3) /* ftp daemon */
198 #define UTMP_FILE UTMP_FILENAME
201 #define UTMP_FILE _PATH_UTMP
203 #define UTMP_FILE "/etc/utmp"
208 #ifndef _PATH_LOGCONF
209 #define _PATH_LOGCONF "/etc/rsyslog.conf"
213 #define _PATH_MODDIR "/lib/rsyslog/"
216 #if defined(SYSLOGD_PIDNAME)
220 # define _PATH_VARRUN "/var/run/"
222 # if defined(__sun) || defined(__hpux)
223 # define _PATH_VARRUN "/var/run/"
225 # define _PATH_LOGPID _PATH_VARRUN SYSLOGD_PIDNAME
227 # define _PATH_LOGPID "/etc/" SYSLOGD_PIDNAME
230 # ifndef _PATH_LOGPID
231 # if defined(__sun) || defined(__hpux)
232 # define _PATH_VARRUN "/var/run/"
235 # define _PATH_LOGPID _PATH_VARRUN "rsyslogd.pid"
237 # define _PATH_LOGPID "/etc/rsyslogd.pid"
243 # define _PATH_DEV "/dev/"
246 #ifndef _PATH_CONSOLE
247 #define _PATH_CONSOLE "/dev/console"
251 #define _PATH_TTY "/dev/tty"
254 static uchar *ConfFile = (uchar*) _PATH_LOGCONF; /* read-only after startup */
255 static char *PidFile = _PATH_LOGPID; /* read-only after startup */
256 char ctty[] = _PATH_CONSOLE; /* this is read-only; used by omfile -- TODO: remove that dependency */
258 static pid_t myPid; /* our pid for use in self-generated messages, e.g. on startup */
259 /* mypid is read-only after the initial fork() */
260 static int restart = 0; /* do restart (config read) - multithread safe */
262 int glblHadMemShortage = 0; /* indicates if we had memory shortage some time during the run */
265 static int bParseHOSTNAMEandTAG = 1; /* global config var: should the hostname and tag be
266 * parsed inside message - rgerhards, 2006-03-13 */
267 static int bFinished = 0; /* used by termination signal handler, read-only except there
268 * is either 0 or the number of the signal that requested the
272 /* Intervals at which we flush out "message repeated" messages,
273 * in seconds after previous message is logged. After each flush,
274 * we move to the next interval until we reach the largest.
275 * TODO: this shall go into action object! -- rgerhards, 2008-01-29
277 int repeatinterval[2] = { 30, 60 }; /* # of secs before flush */
279 #define LIST_DELIMITER ':' /* delimiter between two hosts */
281 struct filed *Files = NULL; /* read-only after init() (but beware of sigusr1!) */
283 static pid_t ppid; /* This is a quick and dirty hack used for spliting main/startup thread */
285 typedef struct legacyOptsLL_s {
287 struct legacyOptsLL_s *next;
289 legacyOptsLL_t *pLegacyOptsLL = NULL;
291 /* global variables for config file state */
292 static int bDropTrailingLF = 1; /* drop trailing LF's on reception? */
293 int iCompatibilityMode = 0; /* version we should be compatible with; 0 means sysklogd. It is
294 the default, so if no -c<n> option is given, we make ourselvs
295 as compatible to sysklogd as possible. */
296 static int bDebugPrintTemplateList = 1;/* output template list in debug mode? */
297 static int bDebugPrintCfSysLineHandlerList = 1;/* output cfsyslinehandler list in debug mode? */
298 static int bDebugPrintModuleList = 1;/* output module list in debug mode? */
299 int bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */
300 static uchar cCCEscapeChar = '\\';/* character to be used to start an escape sequence for control chars */
301 static int bEscapeCCOnRcv = 1; /* escape control characters on reception: 0 - no, 1 - yes */
302 int bReduceRepeatMsgs; /* reduce repeated message - 0 - no, 1 - yes */
303 int bActExecWhenPrevSusp; /* execute action only when previous one was suspended? */
304 uchar *pszWorkDir = NULL;/* name of rsyslog's spool directory (without trailing slash) */
305 /* end global config file state variables */
307 char LocalHostName[MAXHOSTNAMELEN+1];/* our hostname - read-only after startup */
308 char *LocalDomain; /* our local domain name - read-only after startup */
309 int MarkInterval = 20 * 60; /* interval between marks in seconds - read-only after startup */
310 int family = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both), set via cmdline */
311 int send_to_all = 0; /* send message to all IPv4/IPv6 addresses */
312 static int NoFork = 0; /* don't fork - don't run in daemon mode - read-only after startup */
313 int DisableDNS = 0; /* don't look up IP addresses of remote messages */
314 char **StripDomains = NULL;/* these domains may be stripped before writing logs - r/o after s.u., never touched by init */
315 char **LocalHosts = NULL;/* these hosts are logged with their hostname - read-only after startup, never touched by init */
316 static int bHaveMainQueue = 0;/* set to 1 if the main queue - in queueing mode - is available
317 * If the main queue is either not yet ready or not running in
318 * queueing mode (mode DIRECT!), then this is set to 0.
323 /* main message queue and its configuration parameters */
324 static queue_t *pMsgQueue = NULL; /* the main message queue */
325 static int iMainMsgQueueSize = 10000; /* size of the main message queue above */
326 static int iMainMsgQHighWtrMark = 8000; /* high water mark for disk-assisted queues */
327 static int iMainMsgQLowWtrMark = 2000; /* low water mark for disk-assisted queues */
328 static int iMainMsgQDiscardMark = 9800; /* begin to discard messages */
329 static int iMainMsgQDiscardSeverity = 8; /* by default, discard nothing to prevent unintentional loss */
330 static int iMainMsgQueueNumWorkers = 1; /* number of worker threads for the mm queue above */
331 static queueType_t MainMsgQueType = QUEUETYPE_FIXED_ARRAY; /* type of the main message queue above */
332 static uchar *pszMainMsgQFName = NULL; /* prefix for the main message queue file */
333 static int64 iMainMsgQueMaxFileSize = 1024*1024;
334 static int iMainMsgQPersistUpdCnt = 0; /* persist queue info every n updates */
335 static int iMainMsgQtoQShutdown = 0; /* queue shutdown */
336 static int iMainMsgQtoActShutdown = 1000; /* action shutdown (in phase 2) */
337 static int iMainMsgQtoEnq = 2000; /* timeout for queue enque */
338 static int iMainMsgQtoWrkShutdown = 60000; /* timeout for worker thread shutdown */
339 static int iMainMsgQWrkMinMsgs = 100; /* minimum messages per worker needed to start a new one */
340 static int iMainMsgQDeqSlowdown = 0; /* dequeue slowdown (simple rate limiting) */
341 static int bMainMsgQSaveOnShutdown = 1; /* save queue on shutdown (when DA enabled)? */
342 static int64 iMainMsgQueMaxDiskSpace = 0; /* max disk space allocated 0 ==> unlimited */
345 /* support for simple textual representation of FIOP names
346 * rgerhards, 2005-09-27
348 static char* getFIOPName(unsigned iFIOP)
358 case FIOP_STARTSWITH:
372 /* Reset config variables to default values.
373 * rgerhards, 2007-07-17
375 static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __attribute__((unused)) *pVal)
378 bActExecWhenPrevSusp = 0;
379 bDebugPrintTemplateList = 1;
380 bDebugPrintCfSysLineHandlerList = 1;
381 bDebugPrintModuleList = 1;
382 bEscapeCCOnRcv = 1; /* default is to escape control characters */
383 bReduceRepeatMsgs = 0;
385 if(pszWorkDir != NULL) {
389 if(pszMainMsgQFName != NULL) {
390 free(pszMainMsgQFName);
391 pszMainMsgQFName = NULL;
393 iMainMsgQueueSize = 10000;
394 iMainMsgQHighWtrMark = 8000;
395 iMainMsgQLowWtrMark = 2000;
396 iMainMsgQDiscardMark = 9800;
397 iMainMsgQDiscardSeverity = 4;
398 iMainMsgQueMaxFileSize = 1024 * 1024;
399 iMainMsgQueueNumWorkers = 1;
400 iMainMsgQPersistUpdCnt = 0;
401 iMainMsgQtoQShutdown = 0;
402 iMainMsgQtoActShutdown = 1000;
403 iMainMsgQtoEnq = 2000;
404 iMainMsgQtoWrkShutdown = 60000;
405 iMainMsgQWrkMinMsgs = 100;
406 iMainMsgQDeqSlowdown = 0;
407 bMainMsgQSaveOnShutdown = 1;
408 MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
409 iMainMsgQueMaxDiskSpace = 0;
410 glbliActionResumeRetryCount = 0;
417 int option_DisallowWarning = 1; /* complain if message from disallowed sender is received */
420 /* hardcoded standard templates (used for defaults) */
421 static uchar template_SyslogProtocol23Format[] = "\"<%PRI%>1 %TIMESTAMP:::date-rfc3339% %HOSTNAME% %APP-NAME% %PROCID% %MSGID% %STRUCTURED-DATA% %msg%\n\"";
422 static uchar template_TraditionalFileFormat[] = "\"%TIMESTAMP% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\"";
423 static uchar template_FileFormat[] = "\"%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag%%msg:::drop-last-lf%\n\"";
424 static uchar template_WallFmt[] = "\"\r\n\7Message from syslogd@%HOSTNAME% at %timegenerated% ...\r\n %syslogtag%%msg%\n\r\"";
425 static uchar template_ForwardFormat[] = "\"<%PRI%>%TIMESTAMP:::date-rfc3339% %HOSTNAME% %syslogtag:1:32%%msg%\"";
426 static uchar template_TraditionalForwardFormat[] = "\"<%PRI%>%TIMESTAMP% %HOSTNAME% %syslogtag:1:32%%msg%\"";
427 static uchar template_StdUsrMsgFmt[] = "\" %syslogtag%%msg%\n\r\"";
428 static uchar template_StdDBFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-mysql%', '%timegenerated:::date-mysql%', %iut%, '%syslogtag%')\",SQL";
429 static uchar template_StdPgSQLFmt[] = "\"insert into SystemEvents (Message, Facility, FromHost, Priority, DeviceReportedTime, ReceivedAt, InfoUnitID, SysLogTag) values ('%msg%', %syslogfacility%, '%HOSTNAME%', %syslogpriority%, '%timereported:::date-pgsql%', '%timegenerated:::date-pgsql%', %iut%, '%syslogtag%')\",STDSQL";
433 /* up to the next comment, prototypes that should be removed by reordering */
434 /* Function prototypes. */
435 static char **crunch_list(char *list);
436 static void reapchild();
437 static void debug_switch();
438 static void sighup_handler();
439 static void freeSelectors(void);
440 static void processImInternal(void);
443 static int usage(void)
445 fprintf(stderr, "usage: rsyslogd [-cversion] [-46AdnqQvwx] [-lhostlist] [-sdomainlist]\n"
446 " [-fconffile] [-ipidfile]\n"
447 "To run rsyslogd in native mode, use \"rsyslogd -c3 <other options>\"\n\n"
448 "For further information see http://www.rsyslog.com/doc\n");
449 exit(1); /* "good" exit - done to terminate usage() */
453 /* function to destruct a selector_t object
454 * rgerhards, 2007-08-01
457 selectorDestruct(void *pVal)
459 selector_t *pThis = (selector_t *) pVal;
461 assert(pThis != NULL);
463 if(pThis->pCSHostnameComp != NULL)
464 rsCStrDestruct(&pThis->pCSHostnameComp);
465 if(pThis->pCSProgNameComp != NULL)
466 rsCStrDestruct(&pThis->pCSProgNameComp);
468 if(pThis->f_filter_type == FILTER_PROP) {
469 if(pThis->f_filterData.prop.pCSPropName != NULL)
470 rsCStrDestruct(&pThis->f_filterData.prop.pCSPropName);
471 if(pThis->f_filterData.prop.pCSCompValue != NULL)
472 rsCStrDestruct(&pThis->f_filterData.prop.pCSCompValue);
473 } else if(pThis->f_filter_type == FILTER_EXPR) {
474 if(pThis->f_filterData.f_expr != NULL)
475 expr.Destruct(&pThis->f_filterData.f_expr);
478 llDestroy(&pThis->llActList);
485 /* function to construct a selector_t object
486 * rgerhards, 2007-08-01
489 selectorConstruct(selector_t **ppThis)
494 assert(ppThis != NULL);
496 if((pThis = (selector_t*) calloc(1, sizeof(selector_t))) == NULL) {
497 glblHadMemShortage = 1;
498 ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
500 CHKiRet(llInit(&pThis->llActList, actionDestruct, NULL, NULL));
503 if(iRet != RS_RET_OK) {
505 selectorDestruct(pThis);
513 /* rgerhards, 2005-10-24: crunch_list is called only during option processing. So
514 * it is never called once rsyslogd is running (not even when HUPed). This code
515 * contains some exits, but they are considered safe because they only happen
516 * during startup. Anyhow, when we review the code here, we might want to
517 * reconsider the exit()s.
519 static char **crunch_list(char *list)
523 char **result = NULL;
527 /* strip off trailing delimiters */
528 while (p[strlen(p)-1] == LIST_DELIMITER) {
530 p[strlen(p)-1] = '\0';
532 /* cut off leading delimiters */
533 while (p[0] == LIST_DELIMITER) {
538 /* count delimiters to calculate elements */
539 for (count=i=0; p[i]; i++)
540 if (p[i] == LIST_DELIMITER) count++;
542 if ((result = (char **)malloc(sizeof(char *) * (count+2))) == NULL) {
543 printf ("Sorry, can't get enough memory, exiting.\n");
544 exit(0); /* safe exit, because only called during startup */
548 * We now can assume that the first and last
549 * characters are different from any delimiters,
550 * so we don't have to care about this.
553 while ((q=strchr(p, LIST_DELIMITER))) {
554 result[count] = (char *) malloc((q - p + 1) * sizeof(char));
555 if (result[count] == NULL) {
556 printf ("Sorry, can't get enough memory, exiting.\n");
557 exit(0); /* safe exit, because only called during startup */
559 strncpy(result[count], p, q - p);
560 result[count][q - p] = '\0';
564 if ((result[count] = \
565 (char *)malloc(sizeof(char) * strlen(p) + 1)) == NULL) {
566 printf ("Sorry, can't get enough memory, exiting.\n");
567 exit(0); /* safe exit, because only called during startup */
569 strcpy(result[count],p);
570 result[++count] = NULL;
574 while (result[count])
575 dbgprintf("#%d: %s\n", count, StripDomains[count++]);
594 i = open(_PATH_TTY, O_RDWR);
596 # if !defined(__hpux)
597 (void) ioctl(i, (int) TIOCNOTTY, (char *)0);
599 /* TODO: we need to implement something for HP UX! -- rgerhards, 2008-03-04 */
600 /* actually, HP UX should have setsid, so the code directly above should
601 * trigger. So the actual question is why it doesn't do that...
611 /* Take a raw input line, decode the message, and print the message
612 * on the appropriate log files.
613 * rgerhards 2004-11-08: Please note
614 * that this function does only a partial decoding. At best, it splits
615 * the PRI part. No further decode happens. The rest is done in
617 * Added the iSource parameter so that we know if we have to parse
618 * HOSTNAME or not. rgerhards 2004-11-16.
619 * changed parameter iSource to bParseHost. For details, see comment in
620 * printchopped(). rgerhards 2005-10-06
621 * rgerhards: 2008-03-06: added "flags" to allow an input module to specify
622 * flags, most importantly to request ignoring the messages' timestamp.
624 * rgerhards, 2008-03-19:
625 * I added an additional calling parameter to permit specifying the flow
626 * control capability of the source.
628 rsRetVal printline(char *hname, char *msg, int bParseHost, int flags, flowControl_t flowCtlType)
635 /* Now it is time to create the message object (rgerhards)
637 CHKiRet(msgConstruct(&pMsg));
638 MsgSetFlowControlType(pMsg, flowCtlType);
639 MsgSetRawMsg(pMsg, msg);
641 pMsg->bParseHOSTNAME = bParseHost;
642 /* test for special codes */
647 while (isdigit((int) *++p))
649 pri = 10 * pri + (*p - '0');
654 if (pri &~ (LOG_FACMASK|LOG_PRIMASK))
656 pMsg->iFacility = LOG_FAC(pri);
657 pMsg->iSeverity = LOG_PRI(pri);
659 /* Now we look at the HOSTNAME. That is a bit complicated...
660 * If we have a locally received message, it does NOT
661 * contain any hostname information in the message itself.
662 * As such, the HOSTNAME is the same as the system that
663 * the message was received from (that, for obvious reasons,
664 * being the local host). rgerhards 2004-11-16
667 MsgSetHOSTNAME(pMsg, hname);
668 MsgSetRcvFrom(pMsg, hname);
670 /* rgerhards 2004-11-19: well, well... we've now seen that we
671 * have the "hostname problem" also with the traditional Unix
672 * message. As we like to emulate it, we need to add the hostname
675 if(MsgSetUxTradMsg(pMsg, p) != 0)
676 ABORT_FINALIZE(RS_RET_ERR);
678 logmsg(pMsg, flags | SYNC_FILE);
685 /* This takes a received message that must be decoded and submits it to
686 * the main message queue. The function calls the necessary parser.
688 * rgerhards, 2006-11-30: I have greatly changed this function. Formerly,
689 * it tried to reassemble multi-part messages, which is a legacy stock
690 * sysklogd concept. In essence, that was that messages not ending with
691 * \0 were glued together. As far as I can see, this is a sysklogd
692 * specific feature and, from looking at the code, seems to be used
693 * pretty seldom (if at all). I remove this now, not the least because it is totally
694 * incompatible with upcoming IETF syslog standards. If you experience
695 * strange behaviour with messages beeing split across multiple lines,
696 * this function here might be the place to look at.
698 * Some previous history worth noting:
699 * I added the "iSource" parameter. This is needed to distinguish between
700 * messages that have a hostname in them (received from the internet) and
701 * those that do not have (most prominently /dev/log). rgerhards 2004-11-16
702 * And now I removed the "iSource" parameter and changed it to be "bParseHost",
703 * because all that it actually controls is whether the host is parsed or not.
704 * For rfc3195 support, we needed to modify the algo for host parsing, so we can
705 * no longer rely just on the source (rfc3195d forwarded messages arrive via
706 * unix domain sockets but contain the hostname). rgerhards, 2005-10-06
708 * rgerhards, 2008-02-18:
709 * This function was previously called "printchopped"() and has been renamed
710 * as part of the effort to create a clean internal message submission interface.
711 * It also has been adopted to our usual calling interface, but currently does
712 * not provide any useful return states. But we now have the hook and things can
713 * improve in the future. <-- TODO!
715 * rgerhards, 2008-03-19:
716 * I added an additional calling parameter to permit specifying the flow
717 * control capability of the source.
720 parseAndSubmitMessage(char *hname, char *msg, int len, int bParseHost, int flags, flowControl_t flowCtlType)
727 char tmpline[MAXLINE + 1];
729 char deflateBuf[MAXLINE + 1];
733 assert(hname != NULL);
737 /* we first check if we have a NUL character at the very end of the
738 * message. This seems to be a frequent problem with a number of senders.
739 * So I have now decided to drop these NULs. However, if they are intentional,
740 * that may cause us some problems, e.g. with syslog-sign. On the other hand,
741 * current code always has problems with intentional NULs (as it needs to escape
742 * them to prevent problems with the C string libraries), so that does not
743 * really matter. Just to be on the save side, we'll log destruction of such
744 * NULs in the debug log.
745 * rgerhards, 2007-09-14
747 if(*(msg + len - 1) == '\0') {
748 dbgprintf("dropped NUL at very end of message\n");
752 /* then we check if we need to drop trailing LFs, which often make
753 * their way into syslog messages unintentionally. In order to remain
754 * compatible to recent IETF developments, we allow the user to
755 * turn on/off this handling. rgerhards, 2007-07-23
757 if(bDropTrailingLF && *(msg + len - 1) == '\n') {
758 dbgprintf("dropped LF at very end of message (DropTrailingLF is set)\n");
762 iMsg = 0; /* initialize receiving buffer index */
763 pMsg = tmpline; /* set receiving buffer pointer */
764 pData = msg; /* set source buffer pointer */
765 pEnd = msg + len; /* this is one off, which is intensional */
768 /* we first need to check if we have a compressed record. If so,
769 * we must decompress it.
771 if(len > 0 && *msg == 'z') { /* compressed data present? (do NOT change order if conditions!) */
772 /* we have compressed data, so let's deflate it. We support a maximum
773 * message size of MAXLINE. If it is larger, an error message is logged
774 * and the message is dropped. We do NOT try to decompress larger messages
775 * as such might be used for denial of service. It might happen to later
776 * builds that such functionality be added as an optional, operator-configurable
780 iLenDefBuf = MAXLINE;
781 ret = uncompress((uchar *) deflateBuf, &iLenDefBuf, (uchar *) msg+1, len-1);
782 dbgprintf("Compressed message uncompressed with status %d, length: new %ld, old %d.\n",
783 ret, (long) iLenDefBuf, len-1);
784 /* Now check if the uncompression worked. If not, there is not much we can do. In
785 * that case, we log an error message but ignore the message itself. Storing the
786 * compressed text is dangerous, as it contains control characters. So we do
787 * not do this. If someone would like to have a copy, this code here could be
788 * modified to do a hex-dump of the buffer in question. We do not include
789 * this functionality right now.
790 * rgerhards, 2006-12-07
793 errmsg.LogError(NO_ERRCODE, "Uncompression of a message failed with return code %d "
794 "- enable debug logging if you need further information. "
795 "Message ignored.", ret);
796 FINALIZE; /* unconditional exit, nothing left to do... */
799 pEnd = deflateBuf + iLenDefBuf;
801 # else /* ifdef USE_NETZIP */
802 /* in this case, we still need to check if the message is compressed. If so, we must
803 * tell the user we can not accept it.
805 if(len > 0 && *msg == 'z') {
806 errmsg.LogError(NO_ERRCODE, "Received a compressed message, but rsyslogd does not have compression "
807 "support enabled. The message will be ignored.");
810 # endif /* ifdef USE_NETZIP */
812 while(pData < pEnd) {
813 if(iMsg >= MAXLINE) {
814 /* emergency, we now need to flush, no matter if
815 * we are at end of message or not...
817 if(iMsg == MAXLINE) {
818 *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
819 printline(hname, tmpline, bParseHost, flags, flowCtlType);
821 /* This case in theory never can happen. If it happens, we have
822 * a logic error. I am checking for it, because if I would not,
823 * we would address memory invalidly with the code above. I
824 * do not care much about this case, just a debug log entry
825 * (I couldn't do any more smart things anyway...).
826 * rgerhards, 2007-9-20
828 dbgprintf("internal error: iMsg > MAXLINE in printchopped()\n");
830 FINALIZE; /* in this case, we are done... nothing left we can do */
832 if(*pData == '\0') { /* guard against \0 characters... */
833 /* changed to the sequence (somewhat) proposed in
834 * draft-ietf-syslog-protocol-19. rgerhards, 2006-11-30
836 if(iMsg + 3 < MAXLINE) { /* do we have space? */
837 *(pMsg + iMsg++) = cCCEscapeChar;
838 *(pMsg + iMsg++) = '0';
839 *(pMsg + iMsg++) = '0';
840 *(pMsg + iMsg++) = '0';
841 } /* if we do not have space, we simply ignore the '\0'... */
842 /* log an error? Very questionable... rgerhards, 2006-11-30 */
843 /* decided: we do not log an error, it won't help... rger, 2007-06-21 */
845 } else if(bEscapeCCOnRcv && iscntrl((int) *pData)) {
846 /* we are configured to escape control characters. Please note
847 * that this most probably break non-western character sets like
848 * Japanese, Korean or Chinese. rgerhards, 2007-07-17
849 * Note: sysklogd logs octal values only for DEL and CCs above 127.
850 * For others, it logs ^n where n is the control char converted to an
851 * alphabet character. We like consistency and thus escape it to octal
852 * in all cases. If someone complains, we may change the mode. At least
853 * we known now what's going on.
854 * rgerhards, 2007-07-17
856 if(iMsg + 3 < MAXLINE) { /* do we have space? */
857 *(pMsg + iMsg++) = cCCEscapeChar;
858 *(pMsg + iMsg++) = '0' + ((*pData & 0300) >> 6);
859 *(pMsg + iMsg++) = '0' + ((*pData & 0070) >> 3);
860 *(pMsg + iMsg++) = '0' + ((*pData & 0007));
861 } /* again, if we do not have space, we ignore the char - see comment at '\0' */
864 *(pMsg + iMsg++) = *pData++;
868 *(pMsg + iMsg) = '\0'; /* space *is* reserved for this! */
870 /* typically, we should end up here! */
871 printline(hname, tmpline, bParseHost, flags, flowCtlType);
877 /* rgerhards 2004-11-09: the following is a function that can be used
878 * to log a message orginating from the syslogd itself. In sysklogd code,
879 * this is done by simply calling logmsg(). However, logmsg() is changed in
880 * rsyslog so that it takes a msg "object". So it can no longer be called
881 * directly. This method here solves the need. It provides an interface that
882 * allows to construct a locally-generated message. Please note that this
883 * function here probably is only an interim solution and that we need to
884 * think on the best way to do this.
887 logmsgInternal(int pri, char *msg, int flags)
892 CHKiRet(msgConstruct(&pMsg));
893 MsgSetUxTradMsg(pMsg, msg);
894 MsgSetRawMsg(pMsg, msg);
895 MsgSetHOSTNAME(pMsg, LocalHostName);
896 MsgSetRcvFrom(pMsg, LocalHostName);
897 MsgSetTAG(pMsg, "rsyslogd:");
898 pMsg->iFacility = LOG_FAC(pri);
899 pMsg->iSeverity = LOG_PRI(pri);
900 pMsg->bParseHOSTNAME = 0;
901 datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
902 flags |= INTERNAL_MSG;
904 if(bHaveMainQueue == 0) { /* not yet in queued mode */
905 iminternalAddMsg(pri, pMsg, flags);
907 /* we have the queue, so we can simply provide the
908 * message to the queue engine.
916 /* This functions looks at the given message and checks if it matches the
917 * provided filter condition. If so, it returns true, else it returns
918 * false. This is a helper to logmsg() and meant to drive the decision
919 * process if a message is to be processed or not. As I expect this
920 * decision code to grow more complex over time AND logmsg() is already
921 * a very lengthy function, I thought a separate function is more appropriate.
922 * 2005-09-19 rgerhards
923 * 2008-02-25 rgerhards: changed interface, now utilizes iRet, bProcessMsg
924 * returns is message should be procesed.
926 static rsRetVal shouldProcessThisMessage(selector_t *f, msg_t *pMsg, int *bProcessMsg)
929 unsigned short pbMustBeFreed;
933 var_t *pResult = NULL;
936 assert(pMsg != NULL);
938 /* we first have a look at the global, BSD-style block filters (for tag
939 * and host). Only if they match, we evaluate the actual filter.
940 * rgerhards, 2005-10-18
942 if(f->eHostnameCmpMode == HN_NO_COMP) {
943 /* EMPTY BY INTENSION - we check this value first, because
944 * it is the one most often used, so this saves us time!
946 } else if(f->eHostnameCmpMode == HN_COMP_MATCH) {
947 if(rsCStrSzStrCmp(f->pCSHostnameComp, (uchar*) getHOSTNAME(pMsg), getHOSTNAMELen(pMsg))) {
948 /* not equal, so we are already done... */
949 dbgprintf("hostname filter '+%s' does not match '%s'\n",
950 rsCStrGetSzStrNoNULL(f->pCSHostnameComp), getHOSTNAME(pMsg));
953 } else { /* must be -hostname */
954 if(!rsCStrSzStrCmp(f->pCSHostnameComp, (uchar*) getHOSTNAME(pMsg), getHOSTNAMELen(pMsg))) {
955 /* not equal, so we are already done... */
956 dbgprintf("hostname filter '-%s' does not match '%s'\n",
957 rsCStrGetSzStrNoNULL(f->pCSHostnameComp), getHOSTNAME(pMsg));
962 if(f->pCSProgNameComp != NULL) {
963 int bInv = 0, bEqv = 0, offset = 0;
964 if(*(rsCStrGetSzStrNoNULL(f->pCSProgNameComp)) == '-') {
965 if(*(rsCStrGetSzStrNoNULL(f->pCSProgNameComp) + 1) == '-')
972 if(!rsCStrOffsetSzStrCmp(f->pCSProgNameComp, offset, (uchar*) getProgramName(pMsg), getProgramNameLen(pMsg)))
975 if((!bEqv && !bInv) || (bEqv && bInv)) {
976 /* not equal or inverted selection, so we are already done... */
977 dbgprintf("programname filter '%s' does not match '%s'\n",
978 rsCStrGetSzStrNoNULL(f->pCSProgNameComp), getProgramName(pMsg));
983 /* done with the BSD-style block filters */
985 if(f->f_filter_type == FILTER_PRI) {
986 /* skip messages that are incorrect priority */
987 if ( (f->f_filterData.f_pmask[pMsg->iFacility] == TABLE_NOPRI) || \
988 ((f->f_filterData.f_pmask[pMsg->iFacility] & (1<<pMsg->iSeverity)) == 0) )
992 } else if(f->f_filter_type == FILTER_EXPR) {
993 CHKiRet(vm.Construct(&pVM));
994 CHKiRet(vm.ConstructFinalize(pVM));
995 CHKiRet(vm.SetMsg(pVM, pMsg));
996 CHKiRet(vm.ExecProg(pVM, f->f_filterData.f_expr->pVmprg));
997 CHKiRet(vm.PopBoolFromStack(pVM, &pResult));
998 dbgprintf("result of expression evaluation: %lld\n", pResult->val.num);
999 /* VM is destructed on function exit */
1000 bRet = (pResult->val.num) ? 1 : 0;
1002 assert(f->f_filter_type == FILTER_PROP); /* assert() just in case... */
1003 pszPropVal = MsgGetProp(pMsg, NULL, f->f_filterData.prop.pCSPropName, &pbMustBeFreed);
1005 /* Now do the compares (short list currently ;)) */
1006 switch(f->f_filterData.prop.operation ) {
1008 if(rsCStrLocateInSzStr(f->f_filterData.prop.pCSCompValue, (uchar*) pszPropVal) != -1)
1012 if(rsCStrSzStrCmp(f->f_filterData.prop.pCSCompValue,
1013 (uchar*) pszPropVal, strlen(pszPropVal)) == 0)
1014 bRet = 1; /* process message! */
1016 case FIOP_STARTSWITH:
1017 if(rsCStrSzStrStartsWithCStr(f->f_filterData.prop.pCSCompValue,
1018 (uchar*) pszPropVal, strlen(pszPropVal)) == 0)
1019 bRet = 1; /* process message! */
1022 if(rsCStrSzStrMatchRegex(f->f_filterData.prop.pCSCompValue,
1023 (unsigned char*) pszPropVal) == 0)
1027 /* here, it handles NOP (for performance reasons) */
1028 assert(f->f_filterData.prop.operation == FIOP_NOP);
1029 bRet = 1; /* as good as any other default ;) */
1033 /* now check if the value must be negated */
1034 if(f->f_filterData.prop.isNegated)
1035 bRet = (bRet == 1) ? 0 : 1;
1038 dbgprintf("Filter: check for property '%s' (value '%s') ",
1039 rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSPropName),
1041 if(f->f_filterData.prop.isNegated)
1043 dbgprintf("%s '%s': %s\n",
1044 getFIOPName(f->f_filterData.prop.operation),
1045 rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSCompValue),
1046 bRet ? "TRUE" : "FALSE");
1055 /* destruct in any case, not just on error, but it makes error handling much easier */
1060 var.Destruct(&pResult);
1062 *bProcessMsg = bRet;
1067 /* helper to processMsg(), used to call the configured actions. It is
1068 * executed from within llExecFunc() of the action list.
1069 * rgerhards, 2007-08-02
1071 typedef struct processMsgDoActions_s {
1072 int bPrevWasSuspended; /* was the previous action suspended? */
1074 } processMsgDoActions_t;
1075 DEFFUNC_llExecFunc(processMsgDoActions)
1078 rsRetVal iRetMod; /* return value of module - we do not always pass that back */
1079 action_t *pAction = (action_t*) pData;
1080 processMsgDoActions_t *pDoActData = (processMsgDoActions_t*) pParam;
1082 assert(pAction != NULL);
1084 if((pAction->bExecWhenPrevSusp == 1) && (pDoActData->bPrevWasSuspended == 0)) {
1085 dbgprintf("not calling action because the previous one is not suspended\n");
1086 ABORT_FINALIZE(RS_RET_OK);
1089 iRetMod = actionCallAction(pAction, pDoActData->pMsg);
1090 if(iRetMod == RS_RET_DISCARDMSG) {
1091 ABORT_FINALIZE(RS_RET_DISCARDMSG);
1092 } else if(iRetMod == RS_RET_SUSPENDED) {
1093 /* indicate suspension for next module to be called */
1094 pDoActData->bPrevWasSuspended = 1;
1096 pDoActData->bPrevWasSuspended = 0;
1104 /* Process (consume) a received message. Calls the actions configured.
1105 * rgerhards, 2005-10-13
1108 processMsg(msg_t *pMsg)
1113 processMsgDoActions_t DoActData;
1117 assert(pMsg != NULL);
1119 /* log the message to the particular outputs */
1122 for (f = Files; f != NULL && bContinue ; f = f->f_next) {
1123 /* first check the filters... */
1124 iRet = shouldProcessThisMessage(f, pMsg, &bProcessMsg);
1129 /* ok -- from here, we have action-specific code, nothing really selector-specific -- rger 2007-08-01 */
1130 DoActData.pMsg = pMsg;
1131 DoActData.bPrevWasSuspended = 0;
1132 if(llExecFunc(&f->llActList, processMsgDoActions, (void*)&DoActData) == RS_RET_DISCARDMSG)
1139 /* The consumer of dequeued messages. This function is called by the
1140 * queue engine on dequeueing of a message. It runs on a SEPARATE
1142 * NOTE: Having more than one worker requires guarding of some
1143 * message object structures and potentially others - need to be checked
1144 * before we support multiple worker threads on the message queue.
1145 * Please note: the message object is destructed by the queue itself!
1148 msgConsumer(void __attribute__((unused)) *notNeeded, void *pUsr)
1151 msg_t *pMsg = (msg_t*) pUsr;
1153 assert(pMsg != NULL);
1162 /* Helper to parseRFCSyslogMsg. This function parses a field up to
1163 * (and including) the SP character after it. The field contents is
1164 * returned in a caller-provided buffer. The parsepointer is advanced
1165 * to after the terminating SP. The caller must ensure that the
1166 * provided buffer is large enough to hold the to be extracted value.
1167 * Returns 0 if everything is fine or 1 if either the field is not
1168 * SP-terminated or any other error occurs.
1171 static int parseRFCField(char **pp2parse, char *pResult)
1176 assert(pp2parse != NULL);
1177 assert(*pp2parse != NULL);
1178 assert(pResult != NULL);
1180 p2parse = *pp2parse;
1182 /* this is the actual parsing loop */
1183 while(*p2parse && *p2parse != ' ') {
1184 *pResult++ = *p2parse++;
1188 ++p2parse; /* eat SP, but only if not at end of string */
1190 iRet = 1; /* there MUST be an SP! */
1193 /* set the new parse pointer */
1194 *pp2parse = p2parse;
1199 /* Helper to parseRFCSyslogMsg. This function parses the structured
1200 * data field of a message. It does NOT parse inside structured data,
1201 * just gets the field as whole. Parsing the single entities is left
1202 * to other functions. The parsepointer is advanced
1203 * to after the terminating SP. The caller must ensure that the
1204 * provided buffer is large enough to hold the to be extracted value.
1205 * Returns 0 if everything is fine or 1 if either the field is not
1206 * SP-terminated or any other error occurs.
1209 static int parseRFCStructuredData(char **pp2parse, char *pResult)
1215 assert(pp2parse != NULL);
1216 assert(*pp2parse != NULL);
1217 assert(pResult != NULL);
1219 p2parse = *pp2parse;
1221 /* this is the actual parsing loop
1222 * Remeber: structured data starts with [ and includes any characters
1223 * until the first ] followed by a SP. There may be spaces inside
1224 * structured data. There may also be \] inside the structured data, which
1225 * do NOT terminate an element.
1228 return 1; /* this is NOT structured data! */
1231 if(*p2parse == '\0') {
1232 iRet = 1; /* this is not valid! */
1234 } else if(*p2parse == '\\' && *(p2parse+1) == ']') {
1235 /* this is escaped, need to copy both */
1236 *pResult++ = *p2parse++;
1237 *pResult++ = *p2parse++;
1238 } else if(*p2parse == ']' && *(p2parse+1) == ' ') {
1239 /* found end, just need to copy the ] and eat the SP */
1240 *pResult++ = *p2parse;
1244 *pResult++ = *p2parse++;
1249 ++p2parse; /* eat SP, but only if not at end of string */
1251 iRet = 1; /* there MUST be an SP! */
1254 /* set the new parse pointer */
1255 *pp2parse = p2parse;
1259 /* parse a RFC-formatted syslog message. This function returns
1260 * 0 if processing of the message shall continue and 1 if something
1261 * went wrong and this messe should be ignored. This function has been
1262 * implemented in the effort to support syslog-protocol. Please note that
1263 * the name (parse *RFC*) stems from the hope that syslog-protocol will
1264 * some time become an RFC. Do not confuse this with informational
1265 * RFC 3164 (which is legacy syslog).
1267 * currently supported format:
1269 * <PRI>VERSION SP TIMESTAMP SP HOSTNAME SP APP-NAME SP PROCID SP MSGID SP [SD-ID]s SP MSG
1271 * <PRI> is already stripped when this function is entered. VERSION already
1272 * has been confirmed to be "1", but has NOT been stripped from the message.
1276 static int parseRFCSyslogMsg(msg_t *pMsg, int flags)
1282 assert(pMsg != NULL);
1283 assert(pMsg->pszUxTradMsg != NULL);
1284 p2parse = (char*) pMsg->pszUxTradMsg;
1286 /* do a sanity check on the version and eat it */
1287 assert(p2parse[0] == '1' && p2parse[1] == ' ');
1290 /* Now get us some memory we can use as a work buffer while parsing.
1291 * We simply allocated a buffer sufficiently large to hold all of the
1292 * message, so we can not run into any troubles. I think this is
1293 * more wise then to use individual buffers.
1295 if((pBuf = malloc(sizeof(char)* strlen(p2parse) + 1)) == NULL)
1299 * Validation is not actually done below nor are any errors handled. I have
1300 * NOT included this for the current proof of concept. However, it is strongly
1301 * advisable to add it when this code actually goes into production.
1302 * rgerhards, 2005-11-24
1306 if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == FALSE) {
1307 dbgprintf("no TIMESTAMP detected!\n");
1312 if (flags & ADDDATE) {
1313 datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
1318 parseRFCField(&p2parse, pBuf);
1319 MsgSetHOSTNAME(pMsg, pBuf);
1321 /* we can not parse, so we get the system we
1322 * received the data from.
1324 MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
1329 parseRFCField(&p2parse, pBuf);
1330 MsgSetAPPNAME(pMsg, pBuf);
1335 parseRFCField(&p2parse, pBuf);
1336 MsgSetPROCID(pMsg, pBuf);
1341 parseRFCField(&p2parse, pBuf);
1342 MsgSetMSGID(pMsg, pBuf);
1345 /* STRUCTURED-DATA */
1347 parseRFCStructuredData(&p2parse, pBuf);
1348 MsgSetStructuredData(pMsg, pBuf);
1352 MsgSetMSG(pMsg, p2parse);
1355 return 0; /* all ok */
1359 /* parse a legay-formatted syslog message. This function returns
1360 * 0 if processing of the message shall continue and 1 if something
1361 * went wrong and this messe should be ignored. This function has been
1362 * implemented in the effort to support syslog-protocol.
1364 * As of 2006-01-10, I am removing the logic to continue parsing only
1365 * when a valid TIMESTAMP is detected. Validity of other fields already
1366 * is ignored. This is due to the fact that the parser has grown smarter
1367 * and is now more able to understand different dialects of the syslog
1368 * message format. I do not expect any bad side effects of this change,
1369 * but I thought I log it in this comment.
1370 * rgerhards, 2006-01-10
1372 static int parseLegacySyslogMsg(msg_t *pMsg, int flags)
1379 int bTAGCharDetected;
1381 assert(pMsg != NULL);
1382 assert(pMsg->pszUxTradMsg != NULL);
1383 p2parse = (char*) pMsg->pszUxTradMsg;
1385 /* Check to see if msg contains a timestamp. We stary trying with a
1386 * high-precision one...
1388 if(datetime.ParseTIMESTAMP3339(&(pMsg->tTIMESTAMP), &p2parse) == TRUE)
1389 /* we are done - parse pointer is moved by ParseTIMESTAMP3339 */;
1390 else if(datetime.ParseTIMESTAMP3164(&(pMsg->tTIMESTAMP), p2parse) == TRUE)
1396 /* here we need to check if the timestamp is valid. If it is not,
1397 * we can not continue to parse but must treat the rest as the
1398 * MSG part of the message (as of RFC 3164).
1399 * rgerhards 2004-12-03
1401 if(flags & ADDDATE) {
1402 datetime.getCurrTime(&(pMsg->tTIMESTAMP)); /* use the current time! */
1405 /* rgerhards, 2006-03-13: next, we parse the hostname and tag. But we
1406 * do this only when the user has not forbidden this. I now introduce some
1407 * code that allows a user to configure rsyslogd to treat the rest of the
1408 * message as MSG part completely. In this case, the hostname will be the
1409 * machine that we received the message from and the tag will be empty. This
1410 * is meant to be an interim solution, but for now it is in the code.
1412 if(bParseHOSTNAMEandTAG && !(flags & INTERNAL_MSG)) {
1413 /* parse HOSTNAME - but only if this is network-received!
1414 * rger, 2005-11-14: we still have a problem with BSD messages. These messages
1415 * do NOT include a host name. In most cases, this leads to the TAG to be treated
1416 * as hostname and the first word of the message as the TAG. Clearly, this is not
1417 * of advantage ;) I think I have now found a way to handle this situation: there
1418 * are certain characters which are frequently used in TAG (e.g. ':'), which are
1419 * *invalid* in host names. So while parsing the hostname, I check for these characters.
1420 * If I find them, I set a simple flag but continue. After parsing, I check the flag.
1421 * If it was set, then we most probably do not have a hostname but a TAG. Thus, I change
1422 * the fields. I think this logic shall work with any type of syslog message.
1424 bTAGCharDetected = 0;
1425 if(pMsg->bParseHOSTNAME) {
1426 /* TODO: quick and dirty memory allocation */
1427 /* the memory allocated is far too much in most cases. But on the plus side,
1428 * it is quite fast... - rgerhards, 2007-09-20
1430 if((pBuf = malloc(sizeof(char)* (strlen(p2parse) +1))) == NULL)
1433 /* this is the actual parsing loop */
1434 while(*p2parse && *p2parse != ' ' && *p2parse != ':') {
1435 if(*p2parse == '[' || *p2parse == ']' || *p2parse == '/')
1436 bTAGCharDetected = 1;
1437 *pWork++ = *p2parse++;
1439 /* we need to handle ':' seperately, because it terminates the
1440 * TAG - so we also need to terminate the parser here!
1441 * rgerhards, 2007-09-10 *p2parse points to a valid address here in
1442 * any case. We can reach this point only if we are at end of string,
1443 * or we have a ':' or ' '. What the if below does is check if we are
1444 * not at end of string and, if so, advance the parse pointer. If we
1445 * are already at end of string, *p2parse is equal to '\0', neither if
1446 * will be true and the parse pointer remain as is. This is perfectly
1449 if(*p2parse == ':') {
1450 bTAGCharDetected = 1;
1451 /* We will move hostname to tag, so preserve ':' (otherwise we
1452 * will needlessly change the message format) */
1453 *pWork++ = *p2parse++;
1454 } else if(*p2parse == ' ')
1457 MsgAssignHOSTNAME(pMsg, pBuf);
1459 /* check if we seem to have a TAG */
1460 if(bTAGCharDetected) {
1461 /* indeed, this smells like a TAG, so lets use it for this. We take
1462 * the HOSTNAME from the sender system instead.
1464 dbgprintf("HOSTNAME contains invalid characters, assuming it to be a TAG.\n");
1465 moveHOSTNAMEtoTAG(pMsg);
1466 MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
1469 /* now parse TAG - that should be present in message from all sources.
1470 * This code is somewhat not compliant with RFC 3164. As of 3164,
1471 * the TAG field is ended by any non-alphanumeric character. In
1472 * practice, however, the TAG often contains dashes and other things,
1473 * which would end the TAG. So it is not desirable. As such, we only
1474 * accept colon and SP to be terminators. Even there is a slight difference:
1475 * a colon is PART of the TAG, while a SP is NOT part of the tag
1476 * (it is CONTENT). Starting 2008-04-04, we have removed the 32 character
1477 * size limit (from RFC3164) on the tag. This had bad effects on existing
1478 * envrionments, as sysklogd didn't obey it either (probably another bug
1479 * in RFC3164...). We now receive the full size, but will modify the
1480 * outputs so that only 32 characters max are used by default.
1482 /* The following code in general is quick & dirty - I need to get
1483 * it going for a test, rgerhards 2004-11-16 */
1484 /* lol.. we tried to solve it, just to remind ourselfs that 32 octets
1485 * is the max size ;) we need to shuffle the code again... Just for
1486 * the records: the code is currently clean, but we could optimize it! */
1487 if(!bTAGCharDetected) {
1489 if(rsCStrConstruct(&pStrB) != RS_RET_OK)
1491 rsCStrSetAllocIncrement(pStrB, 33);
1494 while(*p2parse && *p2parse != ':' && *p2parse != ' ') {
1495 rsCStrAppendChar(pStrB, *p2parse++);
1498 if(*p2parse == ':') {
1500 rsCStrAppendChar(pStrB, ':');
1502 rsCStrFinish(pStrB);
1504 rsCStrConvSzStrAndDestruct(pStrB, &pszTAG, 1);
1506 { /* rger, 2005-11-10: no TAG found - this implies that what
1507 * we have considered to be the HOSTNAME is most probably the
1508 * TAG. We consider it so probable, that we now adjust it
1509 * that way. So we pick up the previously set hostname, assign
1510 * it to tag and use the sender system (from IP stack) as
1511 * the hostname. This situation is the standard case with
1512 * stock BSD syslogd.
1514 dbgprintf("No TAG in message, assuming that HOSTNAME is missing.\n");
1515 moveHOSTNAMEtoTAG(pMsg);
1516 MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
1517 } else { /* we have a TAG, so we can happily set it ;) */
1518 MsgAssignTAG(pMsg, pszTAG);
1521 /* we have no TAG, so we ... */
1525 /* we enter this code area when the user has instructed rsyslog NOT
1526 * to parse HOSTNAME and TAG - rgerhards, 2006-03-13
1528 if(!(flags & INTERNAL_MSG))
1530 dbgprintf("HOSTNAME and TAG not parsed by user configuraton.\n");
1531 MsgSetHOSTNAME(pMsg, getRcvFrom(pMsg));
1535 /* The rest is the actual MSG */
1536 MsgSetMSG(pMsg, p2parse);
1538 return 0; /* all ok */
1542 /* submit a fully created message to the main message queue. The message is
1543 * fully processed and parsed, so no parsing at all happens. This is primarily
1544 * a hook to prevent the need for callers to know about the main message queue
1545 * (which may change in the future as we will probably have multiple rule
1546 * sets and thus queues...).
1547 * rgerhards, 2008-02-13
1550 submitMsg(msg_t *pMsg)
1554 ISOBJ_TYPE_assert(pMsg, msg);
1556 MsgPrepareEnqueue(pMsg);
1557 queueEnqObj(pMsgQueue, pMsg->flowCtlType, (void*) pMsg);
1564 * Log a message to the appropriate log files, users, etc. based on
1566 * rgerhards 2004-11-08: actually, this also decodes all but the PRI part.
1567 * rgerhards 2004-11-09: ... but only, if syslogd could properly be initialized
1568 * if not, we use emergency logging to the console and in
1569 * this case, no further decoding happens.
1570 * changed to no longer receive a plain message but a msg object instead.
1571 * rgerhards-2004-11-16: OK, we are now up to another change... This method
1572 * actually needs to PARSE the message. How exactly this needs to happen depends on
1573 * a number of things. Most importantly, it depends on the source. For example,
1574 * locally received messages (SOURCE_UNIXAF) do NOT have a hostname in them. So
1575 * we need to treat them differntly form network-received messages which have.
1576 * Well, actually not all network-received message really have a hostname. We
1577 * can just hope they do, but we can not be sure. So this method tries to find
1578 * whatever can be found in the message and uses that... Obviously, there is some
1579 * potential for misinterpretation, which we simply can not solve under the
1580 * circumstances given.
1583 logmsg(msg_t *pMsg, int flags)
1588 assert(pMsg != NULL);
1589 assert(pMsg->pszUxTradMsg != NULL);
1590 msg = (char*) pMsg->pszUxTradMsg;
1591 dbgprintf("logmsg: flags %x, from '%s', msg %s\n", flags, getRcvFrom(pMsg), msg);
1593 /* rger 2005-11-24 (happy thanksgiving!): we now need to check if we have
1594 * a traditional syslog message or one formatted according to syslog-protocol.
1595 * We need to apply different parsers depending on that. We use the
1596 * -protocol VERSION field for the detection.
1598 if(msg[0] == '1' && msg[1] == ' ') {
1599 dbgprintf("Message has syslog-protocol format.\n");
1600 setProtocolVersion(pMsg, 1);
1601 if(parseRFCSyslogMsg(pMsg, flags) == 1) {
1605 } else { /* we have legacy syslog */
1606 dbgprintf("Message has legacy syslog format.\n");
1607 setProtocolVersion(pMsg, 0);
1608 if(parseLegacySyslogMsg(pMsg, flags) == 1) {
1614 /* ---------------------- END PARSING ---------------- */
1616 /* now submit the message to the main queue - then we are done */
1617 pMsg->msgFlags = flags;
1618 MsgPrepareEnqueue(pMsg);
1619 queueEnqObj(pMsgQueue, pMsg->flowCtlType, (void*) pMsg);
1627 int saved_errno = errno;
1628 struct sigaction sigAct;
1630 memset(&sigAct, 0, sizeof (sigAct));
1631 sigemptyset(&sigAct.sa_mask);
1632 sigAct.sa_handler = reapchild;
1633 sigaction(SIGCHLD, &sigAct, NULL); /* reset signal handler -ASP */
1635 while(waitpid(-1, NULL, WNOHANG) > 0);
1636 errno = saved_errno;
1640 /* helper to doFlushRptdMsgs() to flush the individual action links via llExecFunc
1641 * rgerhards, 2007-08-02
1643 DEFFUNC_llExecFunc(flushRptdMsgsActions)
1645 action_t *pAction = (action_t*) pData;
1647 assert(pAction != NULL);
1651 if (pAction->f_prevcount && time(NULL) >= REPEATTIME(pAction)) {
1652 dbgprintf("flush %s: repeated %d times, %d sec.\n",
1653 module.GetStateName(pAction->pMod), pAction->f_prevcount,
1654 repeatinterval[pAction->f_repeatcount]);
1655 actionWriteToAction(pAction);
1661 return RS_RET_OK; /* we ignore errors, we can not do anything either way */
1665 /* This method flushes reapeat messages.
1668 doFlushRptdMsgs(void)
1670 register selector_t *f;
1672 /* see if we need to flush any "message repeated n times"...
1673 * Note that this interferes with objects running on other threads.
1674 * We are using appropriate locking inside the function to handle that.
1676 for (f = Files; f != NULL ; f = f->f_next) {
1677 llExecFunc(&f->llActList, flushRptdMsgsActions, NULL);
1682 static void debug_switch()
1684 struct sigaction sigAct;
1686 if(debugging_on == 0) {
1688 dbgprintf("Switching debugging_on to true\n");
1690 dbgprintf("Switching debugging_on to false\n");
1694 memset(&sigAct, 0, sizeof (sigAct));
1695 sigemptyset(&sigAct.sa_mask);
1696 sigAct.sa_handler = debug_switch;
1697 sigaction(SIGUSR1, &sigAct, NULL);
1701 void legacyOptsEnq(uchar *line)
1703 legacyOptsLL_t *pNew;
1705 pNew = malloc(sizeof(legacyOptsLL_t));
1709 pNew->line = (uchar *) strdup((char *) line);
1712 if(pLegacyOptsLL == NULL)
1713 pLegacyOptsLL = pNew;
1715 legacyOptsLL_t *pThis = pLegacyOptsLL;
1717 while(pThis->next != NULL)
1718 pThis = pThis->next;
1724 void legacyOptsFree(void)
1726 legacyOptsLL_t *pThis = pLegacyOptsLL, *pNext;
1728 while(pThis != NULL) {
1729 if(pThis->line != NULL)
1731 pNext = pThis->next;
1738 void legacyOptsHook(void)
1740 legacyOptsLL_t *pThis = pLegacyOptsLL;
1742 while(pThis != NULL) {
1743 if(pThis->line != NULL) {
1745 errmsg.LogError(NO_ERRCODE, "Warning: backward compatibility layer added to following "
1746 "directive to rsyslog.conf: %s", pThis->line);
1747 conf.cfsysline(pThis->line);
1749 pThis = pThis->next;
1754 void legacyOptsParseTCP(char ch, char *arg)
1757 register char *pArg = arg;
1758 static char conflict = '\0';
1760 if((conflict == 'g' && ch == 't') || (conflict == 't' && ch == 'g')) {
1761 fprintf(stderr, "rsyslog: If you want to use both -g and -t, use directives instead, -%c ignored.\n", ch);
1768 while(isdigit((int) *pArg))
1769 i = i * 10 + *pArg++ - '0';
1771 /* number of sessions */
1772 if(*pArg == '\0' || *pArg == ',') {
1774 legacyOptsEnq((uchar *) "ModLoad imtcp");
1776 legacyOptsEnq((uchar *) "ModLoad imgssapi");
1778 if(i >= 0 && i <= 65535) {
1782 snprintf((char *) line, sizeof(line), "InputTCPServerRun %d", i);
1783 } else if(ch == 'g') {
1784 snprintf((char *) line, sizeof(line), "InputGSSServerRun %d", i);
1786 legacyOptsEnq(line);
1789 fprintf(stderr, "rsyslogd: Invalid TCP listen port %d - changed to 514.\n", i);
1790 legacyOptsEnq((uchar *) "InputTCPServerRun 514");
1791 } else if(ch == 'g') {
1792 fprintf(stderr, "rsyslogd: Invalid GSS listen port %d - changed to 514.\n", i);
1793 legacyOptsEnq((uchar *) "InputGSSServerRun 514");
1799 while(isspace((int) *pArg))
1802 while(isdigit((int) *pArg)) {
1803 i = i * 10 + *pArg++ - '0';
1808 snprintf((char *) line, sizeof(line), "InputTCPMaxSessions %d", i);
1809 legacyOptsEnq(line);
1812 fprintf(stderr, "rsyslogd: TCP session max configured "
1813 "to %d [-t %s] - changing to 1.\n", i, arg);
1814 legacyOptsEnq((uchar *) "InputTCPMaxSessions 1");
1815 } else if (ch == 'g') {
1816 fprintf(stderr, "rsyslogd: GSS session max configured "
1817 "to %d [-g %s] - changing to 1.\n", i, arg);
1818 legacyOptsEnq((uchar *) "InputTCPMaxSessions 1");
1823 fprintf(stderr, "rsyslogd: Invalid -t %s command line option.\n", arg);
1827 /* doDie() is a signal handler. If called, it sets the bFinished variable
1828 * to indicate the program should terminate. However, it does not terminate
1829 * it itself, because that causes issues with multi-threading. The actual
1830 * termination is then done on the main thread. This solution might introduce
1831 * a minimal delay, but it is much cleaner than the approach of doing everything
1832 * inside the signal handler.
1833 * rgerhards, 2005-10-26
1835 static void doDie(int sig)
1837 static int iRetries = 0; /* debug aid */
1838 printf("DoDie called.\n");
1839 if(iRetries++ == 4) {
1840 printf("DoDie called 5 times - unconditional exit\n");
1847 /* This function frees all dynamically allocated memory for program termination.
1848 * It must be called only immediately before exit(). It is primarily an aid
1849 * for memory debuggers, which prevents cluttered outupt.
1850 * rgerhards, 2008-03-20
1853 freeAllDynMemForTermination(void)
1855 if(pszWorkDir != NULL)
1857 if(pszMainMsgQFName != NULL)
1858 free(pszMainMsgQFName);
1864 /* die() is called when the program shall end. This typically only occurs
1865 * during sigterm or during the initialization.
1866 * As die() is intended to shutdown rsyslogd, it is
1867 * safe to call exit() here. Just make sure that die() itself is not called
1868 * at inapropriate places. As a general rule of thumb, it is a bad idea to add
1869 * any calls to die() in new code!
1870 * rgerhards, 2005-10-24
1877 dbgprintf("exiting on signal %d\n", sig);
1879 /* IMPORTANT: we should close the inputs first, and THEN send our termination
1880 * message. If we do it the other way around, logmsgInternal() may block on
1881 * a full queue and the inputs still fill up that queue. Depending on the
1882 * scheduling order, we may end up with logmsgInternal being held for a quite
1883 * long time. When the inputs are terminated first, that should not happen
1884 * because the queue is drained in parallel. The situation could only become
1885 * an issue with extremely long running actions in a queue full environment.
1886 * However, such actions are at least considered poorly written, if not
1887 * outright wrong. So we do not care about this very remote problem.
1888 * rgerhards, 2008-01-11
1891 /* close the inputs */
1892 dbgprintf("Terminating input threads...\n");
1893 thrdTerminateAll(); /* TODO: inputs only, please */
1895 /* and THEN send the termination log message (see long comment above) */
1897 (void) snprintf(buf, sizeof(buf) / sizeof(char),
1898 " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
1899 "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"]" " exiting on signal %d.",
1902 logmsgInternal(LOG_SYSLOG|LOG_INFO, buf, ADDDATE);
1905 /* drain queue (if configured so) and stop main queue worker thread pool */
1906 dbgprintf("Terminating main queue...\n");
1907 queueDestruct(&pMsgQueue);
1910 /* Free ressources and close connections. This includes flushing any remaining
1913 dbgprintf("Terminating outputs...\n");
1916 dbgprintf("all primary multi-thread sources have been terminated - now doing aux cleanup...\n");
1918 * now clean up the in-memory structures. OK, the OS
1919 * would also take care of that, but if we do it
1920 * ourselfs, this makes finding memory leaks a lot
1925 remove_pid(PidFile);
1926 if(glblHadMemShortage)
1927 dbgprintf("Had memory shortage at least once during the run.\n");
1929 /* de-init some modules */
1930 modExitIminternal();
1932 /*dbgPrintAllDebugInfo(); / * this is the last spot where this can be done - below output modules are unloaded! */
1934 /* the following line cleans up CfSysLineHandlers that were not based on loadable
1935 * modules. As such, they are not yet cleared.
1937 unregCfSysLineHdlrs();
1941 /* terminate the remaining classes */
1944 /* TODO: this would also be the right place to de-init the builtin output modules. We
1945 * do not currently do that, because the module interface does not allow for
1946 * it. This will come some time later (it's essential with loadable modules).
1947 * For the time being, this is a memory leak on exit, but as the process is
1948 * terminated, we do not really bother about it.
1949 * rgerhards, 2007-08-03
1950 * I have added some code now, but all that mod init/de-init should be moved to
1951 * init, so that modules are unloaded and reloaded on HUP to. Eventually it should go
1952 * into freeSelectors() - but that needs to be seen. -- rgerhards, 2007-08-09
1954 module.UnloadAndDestructAll(eMOD_LINK_ALL);
1956 dbgprintf("Clean shutdown completed, bye\n");
1957 /* dbgClassExit MUST be the last one, because it de-inits the debug system */
1960 /* free all remaining memory blocks - this is not absolutely necessary, but helps
1961 * us keep memory debugger logs clean and this is in aid in developing. It doesn't
1962 * cost much time, so we do it always. -- rgerhards, 2008-03-20
1964 freeAllDynMemForTermination();
1965 /* NO CODE HERE - feeelAllDynMemForTermination() must be the last thing before exit()! */
1966 exit(0); /* "good" exit, this is the terminator function for rsyslog [die()] */
1970 * Signal handler to terminate the parent process.
1971 * rgerhards, 2005-10-24: this is only called during forking of the
1972 * detached syslogd. I consider this method to be safe.
1974 static void doexit()
1976 exit(0); /* "good" exit, only during child-creation */
1980 /* set the action resume interval
1982 static rsRetVal setActionResumeInterval(void __attribute__((unused)) *pVal, int iNewVal)
1984 return actionSetGlobalResumeInterval(iNewVal);
1988 /* set the processes umask (upon configuration request)
1990 static rsRetVal setUmask(void __attribute__((unused)) *pVal, int iUmask)
1993 dbgprintf("umask set to 0%3.3o.\n", iUmask);
1999 /* helper to freeSelectors(), used with llExecFunc() to flush
2000 * pending output. -- rgerhards, 2007-08-02
2001 * We do not need to lock the action object here as the processing
2002 * queue is already empty and no other threads are running when
2003 * we call this function. -- rgerhards, 2007-12-12
2005 DEFFUNC_llExecFunc(freeSelectorsActions)
2007 action_t *pAction = (action_t*) pData;
2009 assert(pAction != NULL);
2011 /* flush any pending output */
2012 if(pAction->f_prevcount) {
2013 actionWriteToAction(pAction);
2016 return RS_RET_OK; /* never fails ;) */
2020 /* Close all open log files and free selector descriptor array.
2022 static void freeSelectors(void)
2028 dbgprintf("Freeing log structures.\n");
2030 for(f = Files ; f != NULL ; f = f->f_next) {
2031 llExecFunc(&f->llActList, freeSelectorsActions, NULL);
2034 /* actions flushed and ready for destruction - so do that... */
2039 selectorDestruct(fPrev);
2042 /* Reflect the deletion of the selectors linked list. */
2049 /* helper to dbPrintInitInfo, to print out all actions via
2050 * the llExecFunc() facility.
2051 * rgerhards, 2007-08-02
2053 DEFFUNC_llExecFunc(dbgPrintInitInfoAction)
2056 iRet = actionDbgPrint((action_t*) pData);
2062 /* print debug information as part of init(). This pretty much
2063 * outputs the whole config of rsyslogd. I've moved this code
2064 * out of init() to clean it somewhat up.
2065 * rgerhards, 2007-07-31
2067 static void dbgPrintInitInfo(void)
2069 register selector_t *f;
2073 dbgprintf("\nActive selectors:\n");
2074 for (f = Files; f != NULL ; f = f->f_next) {
2075 dbgprintf("Selector %d:\n", iSelNbr++);
2076 if(f->pCSProgNameComp != NULL)
2077 dbgprintf("tag: '%s'\n", rsCStrGetSzStrNoNULL(f->pCSProgNameComp));
2078 if(f->eHostnameCmpMode != HN_NO_COMP)
2079 dbgprintf("hostname: %s '%s'\n",
2080 f->eHostnameCmpMode == HN_COMP_MATCH ?
2082 rsCStrGetSzStrNoNULL(f->pCSHostnameComp));
2083 if(f->f_filter_type == FILTER_PRI) {
2084 for (i = 0; i <= LOG_NFACILITIES; i++)
2085 if (f->f_filterData.f_pmask[i] == TABLE_NOPRI)
2088 dbgprintf("%2X ", f->f_filterData.f_pmask[i]);
2089 } else if(f->f_filter_type == FILTER_EXPR) {
2090 dbgprintf("EXPRESSION-BASED Filter: can currently not be displayed");
2092 dbgprintf("PROPERTY-BASED Filter:\n");
2093 dbgprintf("\tProperty.: '%s'\n",
2094 rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSPropName));
2095 dbgprintf("\tOperation: ");
2096 if(f->f_filterData.prop.isNegated)
2098 dbgprintf("'%s'\n", getFIOPName(f->f_filterData.prop.operation));
2099 dbgprintf("\tValue....: '%s'\n",
2100 rsCStrGetSzStrNoNULL(f->f_filterData.prop.pCSCompValue));
2101 dbgprintf("\tAction...: ");
2104 dbgprintf("\nActions:\n");
2105 llExecFunc(&f->llActList, dbgPrintInitInfoAction, NULL); /* actions */
2110 if(bDebugPrintTemplateList)
2112 if(bDebugPrintModuleList)
2116 if(bDebugPrintCfSysLineHandlerList)
2117 dbgPrintCfSysLineHandlers();
2119 dbgprintf("Messages with malicious PTR DNS Records are %sdropped.\n",
2120 bDropMalPTRMsgs ? "" : "not ");
2122 dbgprintf("Control characters are %sreplaced upon reception.\n",
2123 bEscapeCCOnRcv? "" : "not ");
2126 dbgprintf("Control character escape sequence prefix is '%c'.\n",
2129 dbgprintf("Main queue size %d messages.\n", iMainMsgQueueSize);
2130 dbgprintf("Main queue worker threads: %d, Perists every %d updates.\n",
2131 iMainMsgQueueNumWorkers, iMainMsgQPersistUpdCnt);
2132 dbgprintf("Main queue timeouts: shutdown: %d, action completion shutdown: %d, enq: %d\n",
2133 iMainMsgQtoQShutdown, iMainMsgQtoActShutdown, iMainMsgQtoEnq);
2134 dbgprintf("Main queue watermarks: high: %d, low: %d, discard: %d, discard-severity: %d\n",
2135 iMainMsgQHighWtrMark, iMainMsgQLowWtrMark, iMainMsgQDiscardMark, iMainMsgQDiscardSeverity);
2136 dbgprintf("Main queue save on shutdown %d, max disk space allowed %lld\n",
2137 bMainMsgQSaveOnShutdown, iMainMsgQueMaxDiskSpace);
2139 iActionRetryCount = 0;
2140 iActionRetryInterval = 30000;
2141 static int iMainMsgQtoWrkShutdown = 60000;
2142 static int iMainMsgQtoWrkMinMsgs = 100;
2143 static int iMainMsgQbSaveOnShutdown = 1;
2144 iMainMsgQueMaxDiskSpace = 0;
2145 setQPROP(queueSettoWrkShutdown, "$MainMsgQueueTimeoutWorkerThreadShutdown", 5000);
2146 setQPROP(queueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", 100);
2147 setQPROP(queueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", 1);
2149 dbgprintf("Work Directory: '%s'.\n", pszWorkDir);
2153 /* Start the input modules. This function will probably undergo big changes
2154 * while we implement the input module interface. For now, it does the most
2155 * important thing to get at least my poor initial input modules up and
2156 * running. Almost no config option is taken.
2157 * rgerhards, 2007-12-14
2160 startInputModules(void)
2165 /* loop through all modules and activate them (brr...) */
2166 pMod = module.GetNxtType(NULL, eMOD_IN);
2167 while(pMod != NULL) {
2168 if((iRet = pMod->mod.im.willRun()) == RS_RET_OK) {
2170 thrdCreate(pMod->mod.im.runInput, pMod->mod.im.afterRun);
2172 dbgprintf("module %lx will not run, iRet %d\n", (unsigned long) pMod, iRet);
2174 pMod = module.GetNxtType(pMod, eMOD_IN);
2178 return RS_RET_OK; /* intentional: we do not care about module errors */
2182 /* INIT -- Initialize syslogd from configuration table
2183 * init() is called at initial startup AND each time syslogd is HUPed
2190 char bufStartUpMsg[512];
2191 struct sigaction sigAct;
2193 thrdTerminateAll(); /* stop all running input threads - TODO: reconsider location! */
2195 /* initialize some static variables */
2196 pDfltHostnameCmp = NULL;
2197 pDfltProgNameCmp = NULL;
2198 eDfltHostnameCmpMode = HN_NO_COMP;
2200 dbgprintf("rsyslog %s.\n", VERSION);
2201 dbgprintf("Called init.\n");
2203 /* delete the message queue, which also flushes all messages left over */
2204 if(pMsgQueue != NULL) {
2205 dbgprintf("deleting main message queue\n");
2206 queueDestruct(&pMsgQueue); /* delete pThis here! */
2210 /* Close all open log files and free log descriptor array. This also frees
2211 * all output-modules instance data.
2215 /* Unload all non-static modules */
2216 dbgprintf("Unloading non-static modules.\n");
2217 module.UnloadAndDestructAll(eMOD_LINK_DYNAMIC_LOADED);
2219 dbgprintf("Clearing templates.\n");
2222 /* re-setting values to defaults (where applicable) */
2223 /* TODO: once we have loadable modules, we must re-visit this code. The reason is
2224 * that config variables are not re-set, because the module is not yet loaded. On
2225 * the other hand, that doesn't matter, because the module got unloaded and is then
2226 * re-loaded, so the variables should be re-set via that way. In any case, we should
2227 * think about the whole situation when we implement loadable plugins.
2228 * rgerhards, 2007-07-31
2230 conf.cfsysline((uchar*)"ResetConfigVariables");
2232 /* open the configuration file */
2233 if((iRet = conf.processConfFile(ConfFile)) != RS_RET_OK) {
2234 /* rgerhards: this code is executed to set defaults when the
2235 * config file could not be opened. We might think about
2236 * abandoning the run in this case - but this, too, is not
2237 * very clever... So we stick with what we have.
2238 * We ignore any errors while doing this - we would be lost anyhow...
2240 selector_t *f = NULL;
2241 char szTTYNameBuf[_POSIX_TTY_NAME_MAX+1]; /* +1 for NULL character */
2242 dbgprintf("primary config file could not be opened - using emergency definitions.\n");
2243 conf.cfline((uchar*)"*.ERR\t" _PATH_CONSOLE, &f);
2244 conf.cfline((uchar*)"*.PANIC\t*", &f);
2245 if(ttyname_r(0, szTTYNameBuf, sizeof(szTTYNameBuf)) == 0) {
2246 snprintf(cbuf,sizeof(cbuf), "*.*\t%s", szTTYNameBuf);
2247 conf.cfline((uchar*)cbuf, &f);
2254 /* we are now done with reading the configuration. This is the right time to
2255 * free some objects that were just needed for loading it. rgerhards 2005-10-19
2257 if(pDfltHostnameCmp != NULL) {
2258 rsCStrDestruct(&pDfltHostnameCmp);
2261 if(pDfltProgNameCmp != NULL) {
2262 rsCStrDestruct(&pDfltProgNameCmp);
2266 if(iMainMsgQueueNumWorkers < 1) {
2267 errmsg.LogError(NO_ERRCODE, "$MainMsgQueueNumWorkers must be at least 1! Set to 1.\n");
2268 iMainMsgQueueNumWorkers = 1;
2271 if(MainMsgQueType == QUEUETYPE_DISK) {
2272 errno = 0; /* for logerror! */
2273 if(pszWorkDir == NULL) {
2274 errmsg.LogError(NO_ERRCODE, "No $WorkDirectory specified - can not run main message queue in 'disk' mode. "
2275 "Using 'FixedArray' instead.\n");
2276 MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
2278 if(pszMainMsgQFName == NULL) {
2279 errmsg.LogError(NO_ERRCODE, "No $MainMsgQueueFileName specified - can not run main message queue in "
2280 "'disk' mode. Using 'FixedArray' instead.\n");
2281 MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
2285 /* switch the message object to threaded operation, if necessary */
2286 if(MainMsgQueType == QUEUETYPE_DIRECT || iMainMsgQueueNumWorkers > 1) {
2287 MsgEnableThreadSafety();
2290 /* create message queue */
2291 CHKiRet_Hdlr(queueConstruct(&pMsgQueue, MainMsgQueType, iMainMsgQueueNumWorkers, iMainMsgQueueSize, msgConsumer)) {
2292 /* no queue is fatal, we need to give up in that case... */
2293 fprintf(stderr, "fatal error %d: could not create message queue - rsyslogd can not run!\n", iRet);
2296 /* name our main queue object (it's not fatal if it fails...) */
2297 obj.SetName((obj_t*) pMsgQueue, (uchar*) "main queue");
2299 /* ... set some properties ... */
2300 # define setQPROP(func, directive, data) \
2301 CHKiRet_Hdlr(func(pMsgQueue, data)) { \
2302 errmsg.LogError(NO_ERRCODE, "Invalid " #directive ", error %d. Ignored, running with default setting", iRet); \
2304 # define setQPROPstr(func, directive, data) \
2305 CHKiRet_Hdlr(func(pMsgQueue, data, (data == NULL)? 0 : strlen((char*) data))) { \
2306 errmsg.LogError(NO_ERRCODE, "Invalid " #directive ", error %d. Ignored, running with default setting", iRet); \
2309 setQPROP(queueSetMaxFileSize, "$MainMsgQueueFileSize", iMainMsgQueMaxFileSize);
2310 setQPROP(queueSetsizeOnDiskMax, "$MainMsgQueueMaxDiskSpace", iMainMsgQueMaxDiskSpace);
2311 setQPROPstr(queueSetFilePrefix, "$MainMsgQueueFileName", pszMainMsgQFName);
2312 setQPROP(queueSetiPersistUpdCnt, "$MainMsgQueueCheckpointInterval", iMainMsgQPersistUpdCnt);
2313 setQPROP(queueSettoQShutdown, "$MainMsgQueueTimeoutShutdown", iMainMsgQtoQShutdown );
2314 setQPROP(queueSettoActShutdown, "$MainMsgQueueTimeoutActionCompletion", iMainMsgQtoActShutdown);
2315 setQPROP(queueSettoWrkShutdown, "$MainMsgQueueWorkerTimeoutThreadShutdown", iMainMsgQtoWrkShutdown);
2316 setQPROP(queueSettoEnq, "$MainMsgQueueTimeoutEnqueue", iMainMsgQtoEnq);
2317 setQPROP(queueSetiHighWtrMrk, "$MainMsgQueueHighWaterMark", iMainMsgQHighWtrMark);
2318 setQPROP(queueSetiLowWtrMrk, "$MainMsgQueueLowWaterMark", iMainMsgQLowWtrMark);
2319 setQPROP(queueSetiDiscardMrk, "$MainMsgQueueDiscardMark", iMainMsgQDiscardMark);
2320 setQPROP(queueSetiDiscardSeverity, "$MainMsgQueueDiscardSeverity", iMainMsgQDiscardSeverity);
2321 setQPROP(queueSetiMinMsgsPerWrkr, "$MainMsgQueueWorkerThreadMinimumMessages", iMainMsgQWrkMinMsgs);
2322 setQPROP(queueSetbSaveOnShutdown, "$MainMsgQueueSaveOnShutdown", bMainMsgQSaveOnShutdown);
2323 setQPROP(queueSetiDeqSlowdown, "$MainMsgQueueDequeueSlowdown", iMainMsgQDeqSlowdown);
2328 /* ... and finally start the queue! */
2329 CHKiRet_Hdlr(queueStart(pMsgQueue)) {
2330 /* no queue is fatal, we need to give up in that case... */
2331 fprintf(stderr, "fatal error %d: could not start message queue - rsyslogd can not run!\n", iRet);
2335 bHaveMainQueue = (MainMsgQueType == QUEUETYPE_DIRECT) ? 0 : 1;
2336 dbgprintf("Main processing queue is initialized and running\n");
2338 /* the output part and the queue is now ready to run. So it is a good time
2339 * to start the inputs. Please note that the net code above should be
2340 * shuffled to down here once we have everything in input modules.
2341 * rgerhards, 2007-12-14
2343 startInputModules();
2349 /* we now generate the startup message. It now includes everything to
2350 * identify this instance. -- rgerhards, 2005-08-17
2352 snprintf(bufStartUpMsg, sizeof(bufStartUpMsg)/sizeof(char),
2353 " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION \
2354 "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] restart",
2356 logmsgInternal(LOG_SYSLOG|LOG_INFO, bufStartUpMsg, ADDDATE);
2358 memset(&sigAct, 0, sizeof (sigAct));
2359 sigemptyset(&sigAct.sa_mask);
2360 sigAct.sa_handler = sighup_handler;
2361 sigaction(SIGHUP, &sigAct, NULL);
2363 dbgprintf(" (re)started.\n");
2368 /* add a completely-processed selector (after config line parsing) to
2369 * the linked list of selectors. We now need to check
2370 * if it has any actions associated and, if so, link it to the linked
2371 * list. If it has nothing associated with it, we can simply discard
2373 * We have one special case during initialization: then, the current
2374 * selector is NULL, which means we do not need to care about it at
2375 * all. -- rgerhards, 2007-08-01
2378 selectorAddList(selector_t *f)
2383 static selector_t *nextp = NULL; /* TODO: make this go away (see comment below) */
2386 CHKiRet(llGetNumElts(&f->llActList, &iActionCnt));
2387 if(iActionCnt == 0) {
2388 errmsg.LogError(NO_ERRCODE, "warning: selector line without actions will be discarded");
2389 selectorDestruct(f);
2391 /* successfully created an entry */
2392 dbgprintf("selector line successfully processed\n");
2393 /* TODO: we should use the linked list class for the selector list, else we need to add globals
2394 * ... well nextp could be added temporarily...
2395 * Thanks to varmojfekoj for having the idea to just use "Files" to make this
2396 * code work. I had actually forgotten to fix the code here before moving to 1.18.0.
2397 * And, of course, I also did not migrate the selector_t structure to the linked list class.
2398 * However, that should still be one of the very next things to happen.
2399 * rgerhards, 2007-08-06
2415 /* set the main message queue mode
2416 * rgerhards, 2008-01-03
2418 static rsRetVal setMainMsgQueType(void __attribute__((unused)) *pVal, uchar *pszType)
2422 if (!strcasecmp((char *) pszType, "fixedarray")) {
2423 MainMsgQueType = QUEUETYPE_FIXED_ARRAY;
2424 dbgprintf("main message queue type set to FIXED_ARRAY\n");
2425 } else if (!strcasecmp((char *) pszType, "linkedlist")) {
2426 MainMsgQueType = QUEUETYPE_LINKEDLIST;
2427 dbgprintf("main message queue type set to LINKEDLIST\n");
2428 } else if (!strcasecmp((char *) pszType, "disk")) {
2429 MainMsgQueType = QUEUETYPE_DISK;
2430 dbgprintf("main message queue type set to DISK\n");
2431 } else if (!strcasecmp((char *) pszType, "direct")) {
2432 MainMsgQueType = QUEUETYPE_DIRECT;
2433 dbgprintf("main message queue type set to DIRECT (no queueing at all)\n");
2435 errmsg.LogError(NO_ERRCODE, "unknown mainmessagequeuetype parameter: %s", (char *) pszType);
2436 iRet = RS_RET_INVALID_PARAMS;
2438 free(pszType); /* no longer needed */
2445 * The following function is resposible for handling a SIGHUP signal. Since
2446 * we are now doing mallocs/free as part of init we had better not being
2447 * doing this during a signal handler. Instead this function simply sets
2448 * a flag variable which will tell the main loop to go through a restart.
2450 void sighup_handler()
2452 struct sigaction sigAct;
2456 memset(&sigAct, 0, sizeof (sigAct));
2457 sigemptyset(&sigAct.sa_mask);
2458 sigAct.sa_handler = sighup_handler;
2459 sigaction(SIGHUP, &sigAct, NULL);
2468 * Copy a string byte by byte until the occurrence
2469 * of a given separator.
2471 * \param ppSrc Pointer to a pointer of the source array of characters. If a
2472 separator detected the Pointer points to the next char after the
2473 separator. Except if the end of the string is dedected ('\n').
2474 Then it points to the terminator char.
2475 * \param pDst Pointer to the destination array of characters. Here the substing
2477 * \param DstSize Maximum numbers of characters to store.
2478 * \param cSep Separator char.
2479 * \ret int Returns 0 if no error occured.
2481 * rgerhards, 2008-02-12: some notes are due... I will once again fix this function, this time
2482 * so that it treats ' ' as a request for whitespace. But in general, the function and its callers
2483 * should be changed over time, this is not really very good code...
2485 int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep)
2487 uchar *pSrc = *ppSrc;
2488 int iErr = 0; /* 0 = no error, >0 = error */
2489 while((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0' && DstSize>1) {
2490 *pDst++ = *(pSrc)++;
2493 /* check if the Dst buffer was to small */
2494 if ((cSep == ' ' ? !isspace(*pSrc) : *pSrc != cSep) && *pSrc != '\n' && *pSrc != '\0') {
2495 dbgprintf("in getSubString, error Src buffer > Dst buffer\n");
2498 if (*pSrc == '\0' || *pSrc == '\n')
2499 /* this line was missing, causing ppSrc to be invalid when it
2500 * was returned in case of end-of-string. rgerhards 2005-07-29
2510 /* this function pulls all internal messages from the buffer
2511 * and puts them into the processing engine.
2512 * We can only do limited error handling, as this would not
2513 * really help us. TODO: add error messages?
2514 * rgerhards, 2007-08-03
2516 static void processImInternal(void)
2522 while(iminternalRemoveMsg(&iPri, &pMsg, &iFlags) == RS_RET_OK) {
2523 logmsg(pMsg, iFlags);
2528 /* This is the main processing loop. It is called after successful initialization.
2529 * When it returns, the syslogd terminates.
2530 * Its sole function is to provide some housekeeping things. The real work is done
2531 * by the other threads spawned.
2536 struct timeval tvSelectTimeout;
2540 /* first check if we have any internal messages queued and spit them out */
2541 /* TODO: do we need this any longer? I doubt it, but let's care about it
2542 * later -- rgerhards, 2007-12-21
2544 processImInternal();
2546 /* this is now just a wait */
2547 tvSelectTimeout.tv_sec = TIMERINTVL;
2548 tvSelectTimeout.tv_usec = 0;
2549 select(1, NULL, NULL, NULL, &tvSelectTimeout);
2551 break; /* exit as quickly as possible - see long comment below */
2553 /* If we received a HUP signal, we call doFlushRptdMsgs() a bit early. This
2554 * doesn't matter, because doFlushRptdMsgs() checks timestamps. What may happen,
2555 * however, is that the too-early call may lead to a bit too-late output
2556 * of "last message repeated n times" messages. But that is quite acceptable.
2557 * rgerhards, 2007-12-21
2558 * ... and just to explain, we flush here because that is exactly what the mainloop
2559 * shall do - provide a periodic interval in which not-yet-flushed messages will
2560 * be flushed. Be careful, there is a potential race condition: doFlushRptdMsgs()
2561 * needs to aquire a lock on the action objects. If, however, long-running consumers
2562 * cause the main queue worker threads to lock them for a long time, we may receive
2563 * a starvation condition, resulting in the mainloop being held on lock for an extended
2564 * period of time. That, in turn, could lead to unresponsiveness to termination
2565 * requests. It is especially important that the bFinished flag is checked before
2566 * doFlushRptdMsgs() is called (I know because I ran into that situation). I am
2567 * not yet sure if the remaining probability window of a termination-related
2568 * problem is large enough to justify changing the code - I would consider it
2569 * extremely unlikely that the problem ever occurs in practice. Fixing it would
2570 * require not only a lot of effort but would cost considerable performance. So
2571 * for the time being, I think the remaining risk can be accepted.
2572 * rgerhards, 2008-01-10
2577 dbgprintf("\nReceived SIGHUP, reloading rsyslogd.\n");
2578 /* main queue is stopped as part of init() */
2587 /* If user is not root, prints warnings or even exits
2588 * TODO: check all dynafiles for write permission
2589 * ... but it is probably better to wait here until we have
2590 * a module interface - rgerhards, 2007-07-23
2592 static void checkPermissions()
2595 /* TODO: this function must either be redone or removed - now with the input modules,
2596 * there is no such simple check we can do. What we can check, however, is if there is
2597 * any input module active and terminate, if not. -- rgerhards, 2007-12-26
2599 /* we are not root */
2602 fputs("WARNING: Local messages will not be logged! If you want to log them, run rsyslog as root.\n",stderr);
2604 /* udp enabled and port number less than or equal to 1024 */
2605 if ( AcceptRemote && (atoi(LogPort) <= 1024) )
2606 fprintf(stderr, "WARNING: Will not listen on UDP port %s. Use port number higher than 1024 or run rsyslog as root!\n", LogPort);
2608 /* tcp enabled and port number less or equal to 1024 */
2609 if( bEnableTCP && (atoi(TCPLstnPort) <= 1024) )
2610 fprintf(stderr, "WARNING: Will not listen on TCP port %s. Use port number higher than 1024 or run rsyslog as root!\n", TCPLstnPort);
2612 /* Neither explicit high UDP port nor explicit high TCP port.
2613 * It is useless to run anymore */
2614 if( !(AcceptRemote && (atoi(LogPort) > 1024)) && !( bEnableTCP && (atoi(TCPLstnPort) > 1024)) )
2617 fprintf(stderr, "ERROR: Nothing to log, no reason to run. Please run rsyslog as root.\n");
2627 /* load build-in modules
2628 * very first version begun on 2007-07-23 by rgerhards
2630 static rsRetVal loadBuildInModules(void)
2634 if((iRet = module.doModInit(modInitFile, (uchar*) "builtin-file", NULL)) != RS_RET_OK) {
2638 if((iRet = module.doModInit(modInitFwd, (uchar*) "builtin-fwd", NULL)) != RS_RET_OK) {
2642 if((iRet = module.doModInit(modInitShell, (uchar*) "builtin-shell", NULL)) != RS_RET_OK) {
2645 if((iRet = module.doModInit(modInitDiscard, (uchar*) "builtin-discard", NULL)) != RS_RET_OK) {
2649 /* dirty, but this must be for the time being: the usrmsg module must always be
2650 * loaded as last module. This is because it processes any time of action selector.
2651 * If we load it before other modules, these others will never have a chance of
2652 * working with the config file. We may change that implementation so that a user name
2653 * must start with an alnum, that would definitely help (but would it break backwards
2654 * compatibility?). * rgerhards, 2007-07-23
2655 * User names now must begin with:
2658 if((iRet = module.doModInit(modInitUsrMsg, (uchar*) "builtin-usrmsg", NULL)) != RS_RET_OK)
2661 /* ok, initialization of the command handler probably does not 100% belong right in
2662 * this space here. However, with the current design, this is actually quite a good
2663 * place to put it. We might decide to shuffle it around later, but for the time
2664 * being, the code has found its home here. A not-just-sideeffect of this decision
2665 * is that rsyslog will terminate if we can not register our built-in config commands.
2666 * This, I think, is the right thing to do. -- rgerhards, 2007-07-31
2668 CHKiRet(regCfSysLineHdlr((uchar *)"workdirectory", 0, eCmdHdlrGetWord, NULL, &pszWorkDir, NULL));
2669 CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeretrycount", 0, eCmdHdlrInt, NULL, &glbliActionResumeRetryCount, NULL));
2670 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuefilename", 0, eCmdHdlrGetWord, NULL, &pszMainMsgQFName, NULL));
2671 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesize", 0, eCmdHdlrInt, NULL, &iMainMsgQueueSize, NULL));
2672 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuehighwatermark", 0, eCmdHdlrInt, NULL, &iMainMsgQHighWtrMark, NULL));
2673 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuelowwatermark", 0, eCmdHdlrInt, NULL, &iMainMsgQLowWtrMark, NULL));
2674 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardmark", 0, eCmdHdlrInt, NULL, &iMainMsgQDiscardMark, NULL));
2675 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuediscardseverity", 0, eCmdHdlrSeverity, NULL, &iMainMsgQDiscardSeverity, NULL));
2676 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuecheckpointinterval", 0, eCmdHdlrInt, NULL, &iMainMsgQPersistUpdCnt, NULL));
2677 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetype", 0, eCmdHdlrGetWord, setMainMsgQueType, NULL, NULL));
2678 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreads", 0, eCmdHdlrInt, NULL, &iMainMsgQueueNumWorkers, NULL));
2679 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutshutdown", 0, eCmdHdlrInt, NULL, &iMainMsgQtoQShutdown, NULL));
2680 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutactioncompletion", 0, eCmdHdlrInt, NULL, &iMainMsgQtoActShutdown, NULL));
2681 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuetimeoutenqueue", 0, eCmdHdlrInt, NULL, &iMainMsgQtoEnq, NULL));
2682 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworketimeoutrthreadshutdown", 0, eCmdHdlrInt, NULL, &iMainMsgQtoWrkShutdown, NULL));
2683 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuedequeueslowdown", 0, eCmdHdlrInt, NULL, &iMainMsgQDeqSlowdown, NULL));
2684 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueueworkerthreadminimummessages", 0, eCmdHdlrInt, NULL, &iMainMsgQWrkMinMsgs, NULL));
2685 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxfilesize", 0, eCmdHdlrSize, NULL, &iMainMsgQueMaxFileSize, NULL));
2686 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuemaxdiskspace", 0, eCmdHdlrSize, NULL, &iMainMsgQueMaxDiskSpace, NULL));
2687 CHKiRet(regCfSysLineHdlr((uchar *)"mainmsgqueuesaveonshutdown", 0, eCmdHdlrBinary, NULL, &bMainMsgQSaveOnShutdown, NULL));
2688 CHKiRet(regCfSysLineHdlr((uchar *)"repeatedmsgreduction", 0, eCmdHdlrBinary, NULL, &bReduceRepeatMsgs, NULL));
2689 CHKiRet(regCfSysLineHdlr((uchar *)"actionexeconlywhenpreviousissuspended", 0, eCmdHdlrBinary, NULL, &bActExecWhenPrevSusp, NULL));
2690 CHKiRet(regCfSysLineHdlr((uchar *)"actionresumeinterval", 0, eCmdHdlrInt, setActionResumeInterval, NULL, NULL));
2691 CHKiRet(regCfSysLineHdlr((uchar *)"controlcharacterescapeprefix", 0, eCmdHdlrGetChar, NULL, &cCCEscapeChar, NULL));
2692 CHKiRet(regCfSysLineHdlr((uchar *)"escapecontrolcharactersonreceive", 0, eCmdHdlrBinary, NULL, &bEscapeCCOnRcv, NULL));
2693 CHKiRet(regCfSysLineHdlr((uchar *)"dropmsgswithmaliciousdnsptrrecords", 0, eCmdHdlrBinary, NULL, &bDropMalPTRMsgs, NULL));
2694 CHKiRet(regCfSysLineHdlr((uchar *)"droptrailinglfonreception", 0, eCmdHdlrBinary, NULL, &bDropTrailingLF, NULL));
2695 CHKiRet(regCfSysLineHdlr((uchar *)"template", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_TEMPLATE, NULL));
2696 CHKiRet(regCfSysLineHdlr((uchar *)"outchannel", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_OUTCHANNEL, NULL));
2697 CHKiRet(regCfSysLineHdlr((uchar *)"allowedsender", 0, eCmdHdlrCustomHandler, conf.doNameLine, (void*)DIR_ALLOWEDSENDER, NULL));
2698 CHKiRet(regCfSysLineHdlr((uchar *)"modload", 0, eCmdHdlrCustomHandler, conf.doModLoad, NULL, NULL));
2699 CHKiRet(regCfSysLineHdlr((uchar *)"includeconfig", 0, eCmdHdlrCustomHandler, conf.doIncludeLine, NULL, NULL));
2700 CHKiRet(regCfSysLineHdlr((uchar *)"umask", 0, eCmdHdlrFileCreateMode, setUmask, NULL, NULL));
2701 CHKiRet(regCfSysLineHdlr((uchar *)"debugprinttemplatelist", 0, eCmdHdlrBinary, NULL, &bDebugPrintTemplateList, NULL));
2702 CHKiRet(regCfSysLineHdlr((uchar *)"debugprintmodulelist", 0, eCmdHdlrBinary, NULL, &bDebugPrintModuleList, NULL));
2703 CHKiRet(regCfSysLineHdlr((uchar *)"debugprintcfsyslinehandlerlist", 0, eCmdHdlrBinary,
2704 NULL, &bDebugPrintCfSysLineHandlerList, NULL));
2705 CHKiRet(regCfSysLineHdlr((uchar *)"moddir", 0, eCmdHdlrGetWord, NULL, &pModDir, NULL));
2706 CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL));
2708 /* now add other modules handlers (we should work on that to be able to do it in ClassInit(), but so far
2709 * that is not possible). -- rgerhards, 2008-01-28
2711 CHKiRet(actionAddCfSysLineHdrl());
2718 /* print version and compile-time setting information.
2720 static void printVersion(void)
2722 printf("rsyslogd %s, ", VERSION);
2723 printf("compiled with:\n");
2724 #ifdef FEATURE_REGEXP
2725 printf("\tFEATURE_REGEXP:\t\t\t\tYes\n");
2727 printf("\tFEATURE_REGEXP:\t\t\t\tNo\n");
2730 printf("\tFEATURE_LARGEFILE:\t\t\tYes\n");
2732 printf("\tFEATURE_LARGEFILE:\t\t\tNo\n");
2735 printf("\tFEATURE_NETZIP (message compression):\tYes\n");
2737 printf("\tFEATURE_NETZIP (message compression):\tNo\n");
2739 #if defined(SYSLOG_INET) && defined(USE_GSSAPI)
2740 printf("\tGSSAPI Kerberos 5 support:\t\tYes\n");
2742 printf("\tGSSAPI Kerberos 5 support:\t\tNo\n");
2745 printf("\tFEATURE_DEBUG (debug build, slow code):\tYes\n");
2747 printf("\tFEATURE_DEBUG (debug build, slow code):\tNo\n");
2750 printf("\tRuntime Instrumentation (slow code):\tYes\n");
2752 printf("\tRuntime Instrumentation (slow code):\tNo\n");
2754 printf("\nSee http://www.rsyslog.com for more information.\n");
2758 /* This function is called after initial initalization. It is used to
2759 * move code out of the too-long main() function.
2760 * rgerhards, 2007-10-17
2762 static void mainThread()
2767 #if 0 // code moved back to main()
2768 /* doing some core initializations */
2769 if((iRet = modInitIminternal()) != RS_RET_OK) {
2770 fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n",
2772 exit(1); /* "good" exit, leaving at init for fatal error */
2775 if((iRet = loadBuildInModules()) != RS_RET_OK) {
2776 fprintf(stderr, "fatal error: could not activate built-in modules. Error code %d.\n",
2778 exit(1); /* "good" exit, leaving at init for fatal error */
2782 /* Note: signals MUST be processed by the thread this code is running in. The reason
2783 * is that we need to interrupt the select() system call. -- rgerhards, 2007-10-17
2786 /* initialize the build-in templates */
2787 pTmp = template_SyslogProtocol23Format;
2788 tplAddLine("RSYSLOG_SyslogProtocol23Format", &pTmp);
2789 pTmp = template_FileFormat; /* new format for files with high-precision stamp */
2790 tplAddLine("RSYSLOG_FileFormat", &pTmp);
2791 pTmp = template_TraditionalFileFormat;
2792 tplAddLine("RSYSLOG_TraditionalFileFormat", &pTmp);
2793 pTmp = template_WallFmt;
2794 tplAddLine(" WallFmt", &pTmp);
2795 pTmp = template_ForwardFormat;
2796 tplAddLine("RSYSLOG_ForwardFormat", &pTmp);
2797 pTmp = template_TraditionalForwardFormat;
2798 tplAddLine("RSYSLOG_TraditionalForwardFormat", &pTmp);
2799 pTmp = template_StdUsrMsgFmt;
2800 tplAddLine(" StdUsrMsgFmt", &pTmp);
2801 pTmp = template_StdDBFmt;
2802 tplAddLine(" StdDBFmt", &pTmp);
2803 pTmp = template_StdPgSQLFmt;
2804 tplLastStaticInit(tplAddLine(" StdPgSQLFmt", &pTmp));
2806 dbgprintf("Starting.\n");
2809 dbgprintf("Debugging enabled, SIGUSR1 to turn off debugging.\n");
2812 /* Send a signal to the parent so it can terminate.
2815 kill (ppid, SIGTERM);
2817 /* END OF INTIALIZATION
2818 * ... but keep in mind that we might do a restart and thus init() might
2819 * be called again. If that happens, we must shut down the worker thread,
2820 * do the init() and then restart things.
2821 * rgerhards, 2005-10-24
2829 /* Method to initialize all global classes.
2830 * rgerhards, 2008-01-04
2833 InitGlobalClasses(void)
2836 char *pErrObj; /* tells us which object failed if that happens (useful for troubleshooting!) */
2839 CHKiRet(objClassInit(NULL)); /* *THIS* *MUST* always be the first class initilizer being called! */
2840 CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */
2841 /* the following classes were intialized by objClassInit() */
2843 CHKiRet(objUse(errmsg, CORE_COMPONENT));
2845 CHKiRet(objUse(module, CORE_COMPONENT));
2847 CHKiRet(objUse(var, CORE_COMPONENT));
2849 /* initialize and use classes. We must be very careful with the order of events. Some
2850 * classes use others and if we do not initialize them in the right order, we may end
2851 * up with an invalid call. The most important thing that can happen is that an error
2852 * is detected and needs to be logged, wich in turn requires a broader number of classes
2853 * to be available. The solution is that we take care in the order of calls AND use a
2854 * class immediately after it is initialized. And, of course, we load those classes
2855 * first that we use ourselfs... -- rgerhards, 2008-03-07
2857 pErrObj = "datetime";
2858 CHKiRet(datetimeClassInit(NULL));
2859 CHKiRet(objUse(datetime, CORE_COMPONENT));
2861 CHKiRet(msgClassInit(NULL));
2863 CHKiRet(strmClassInit(NULL));
2865 CHKiRet(wtiClassInit(NULL));
2867 CHKiRet(wtpClassInit(NULL));
2869 CHKiRet(queueClassInit(NULL));
2871 CHKiRet(vmstkClassInit(NULL));
2873 CHKiRet(sysvarClassInit(NULL));
2875 CHKiRet(vmClassInit(NULL));
2876 CHKiRet(objUse(vm, CORE_COMPONENT));
2878 CHKiRet(vmopClassInit(NULL));
2880 CHKiRet(vmprgClassInit(NULL));
2881 pErrObj = "ctok_token";
2882 CHKiRet(ctok_tokenClassInit(NULL));
2884 CHKiRet(ctokClassInit(NULL));
2886 CHKiRet(exprClassInit(NULL));
2887 CHKiRet(objUse(expr, CORE_COMPONENT));
2889 CHKiRet(confClassInit(NULL));
2890 CHKiRet(objUse(conf, CORE_COMPONENT));
2892 /* dummy "classes" */
2894 CHKiRet(actionClassInit());
2895 pErrObj = "template";
2896 CHKiRet(templateInit());
2900 /* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */
2902 CHKiRet(objUse(net, LM_NET_FILENAME));
2905 if(iRet != RS_RET_OK) {
2906 /* we know we are inside the init sequence, so we can safely emit
2907 * messages to stderr. -- rgerhards, 2008-04-02
2909 fprintf(stderr, "Error during class init for object '%s' - failing...\n", pErrObj);
2916 /* Method to exit all global classes. We do not do any error checking here,
2917 * because that wouldn't help us at all. So better try to deinit blindly
2918 * as much as succeeds (which usually means everything will). We just must
2919 * be careful to do the de-init in the opposite order of the init, because
2920 * of the dependencies. However, its not as important this time, because
2921 * we have reference counting.
2922 * rgerhards, 2008-03-10
2925 GlobalClassExit(void)
2929 /* first, release everything we used ourself */
2930 objRelease(net, LM_NET_FILENAME);/* TODO: the dependency on net shall go away! -- rgerhards, 2008-03-07 */
2931 objRelease(conf, CORE_COMPONENT);
2932 objRelease(expr, CORE_COMPONENT);
2933 objRelease(vm, CORE_COMPONENT);
2934 objRelease(var, CORE_COMPONENT);
2935 objRelease(datetime, CORE_COMPONENT);
2937 /* TODO: implement the rest of the deinit */
2940 CHKiRet(datetimeClassInit(NULL));
2941 CHKiRet(msgClassInit(NULL));
2942 CHKiRet(strmClassInit(NULL));
2943 CHKiRet(wtiClassInit(NULL));
2944 CHKiRet(wtpClassInit(NULL));
2945 CHKiRet(queueClassInit(NULL));
2946 CHKiRet(vmstkClassInit(NULL));
2947 CHKiRet(sysvarClassInit(NULL));
2948 CHKiRet(vmClassInit(NULL));
2949 CHKiRet(vmopClassInit(NULL));
2950 CHKiRet(vmprgClassInit(NULL));
2951 CHKiRet(ctok_tokenClassInit(NULL));
2952 CHKiRet(ctokClassInit(NULL));
2953 CHKiRet(exprClassInit(NULL));
2955 /* dummy "classes" */
2956 CHKiRet(actionClassInit());
2957 CHKiRet(templateInit());
2959 /* dummy "classes */
2963 CHKiRet(objGetObjInterface(&obj)); /* this provides the root pointer for all other queries */
2964 /* the following classes were intialized by objClassInit() */
2965 CHKiRet(objUse(errmsg, CORE_COMPONENT));
2966 CHKiRet(objUse(module, CORE_COMPONENT));
2968 objClassExit(); /* *THIS* *MUST/SHOULD?* always be the first class initilizer being called (except debug)! */
2975 /* This is the main entry point into rsyslogd. Over time, we should try to
2976 * modularize it a bit more...
2978 int realMain(int argc, char **argv)
2986 struct hostent *hent;
2988 extern char *optarg;
2989 struct sigaction sigAct;
2990 int bIsFirstOption = 1;
2991 int bEOptionWasGiven = 0;
2992 int bImUxSockLoaded = 0; /* already generated a $ModLoad imuxsock? */
2993 uchar legacyConfLine[80];
2995 gethostname(LocalHostName, sizeof(LocalHostName));
2996 if ( (p = strchr(LocalHostName, '.')) ) {
3004 /* It's not clearly defined whether gethostname()
3005 * should return the simple hostname or the fqdn. A
3006 * good piece of software should be aware of both and
3007 * we want to distribute good software. Joey
3009 * Good software also always checks its return values...
3010 * If syslogd starts up before DNS is up & /etc/hosts
3011 * doesn't have LocalHostName listed, gethostbyname will
3014 /* TODO: gethostbyname() is not thread-safe, but replacing it is
3015 * not urgent as we do not run on multiple threads here. rgerhards, 2007-09-25
3017 hent = gethostbyname(LocalHostName);
3019 snprintf(LocalHostName, sizeof(LocalHostName), "%s", hent->h_name);
3021 if ( (p = strchr(LocalHostName, '.')) )
3029 /* Convert to lower case to recognize the correct domain laterly
3031 for (p = (char *)LocalDomain; *p ; p++)
3032 if (isupper((int) *p))
3033 *p = (char)tolower((int)*p);
3035 CHKiRet_Hdlr(InitGlobalClasses()) {
3036 fprintf(stderr, "rsyslogd initializiation failed - global classes could not be initialized.\n"
3037 "Did you do a \"make install\"?\n"
3038 "Suggested action: run rsyslogd with -d -n options to see what exactly "
3043 /* doing some core initializations */
3044 if((iRet = modInitIminternal()) != RS_RET_OK) {
3045 fprintf(stderr, "fatal error: could not initialize errbuf object (error code %d).\n",
3047 exit(1); /* "good" exit, leaving at init for fatal error */
3050 if((iRet = loadBuildInModules()) != RS_RET_OK) {
3051 fprintf(stderr, "fatal error: could not activate built-in modules. Error code %d.\n",
3053 exit(1); /* "good" exit, leaving at init for fatal error */
3058 if(chdir ("/") != 0)
3059 fprintf(stderr, "Can not do 'cd /' - still trying to run\n");
3061 /* END core initializations */
3063 while ((ch = getopt(argc, argv, "46aAc:def:g:hi:l:m:M:nopqQr::s:t:u:vwx")) != EOF) {
3075 if(iCompatibilityMode < 3) {
3076 if(!bImUxSockLoaded) {
3077 legacyOptsEnq((uchar *) "ModLoad imuxsock");
3078 bImUxSockLoaded = 1;
3080 snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "addunixlistensocket %s", optarg);
3081 legacyOptsEnq(legacyConfLine);
3083 fprintf(stderr, "error -a is no longer supported, use module imuxsock instead");
3086 case 'c': /* compatibility mode */
3087 if(!bIsFirstOption) {
3088 fprintf(stderr, "-c option MUST be specified as the first option - aborting...\n");
3092 iCompatibilityMode = atoi(optarg);
3094 case 'd': /* debug */
3097 case 'e': /* log every message (no repeat message supression) */
3098 fprintf(stderr, "note: -e option is no longer supported, every message is now logged by default\n");
3099 bEOptionWasGiven = 1;
3101 case 'f': /* configuration file */
3102 ConfFile = (uchar*) optarg;
3104 case 'g': /* enable tcp gssapi logging */
3105 #if defined(SYSLOG_INET) && defined(USE_GSSAPI)
3106 if(iCompatibilityMode < 3) {
3107 legacyOptsParseTCP(ch, optarg);
3109 fprintf(stderr, "-g option only supported in compatibility modes 0 to 2 - ignored\n");
3111 fprintf(stderr, "rsyslogd: -g not valid - not compiled with gssapi support");
3115 if(iCompatibilityMode < 3) {
3116 errmsg.LogError(NO_ERRCODE, "WARNING: -h option is no longer supported - ignored");
3118 usage(); /* for v3 and above, it simply is an error */
3121 case 'i': /* pid file name */
3126 fprintf (stderr, "rsyslogd: Only one -l argument allowed, the first one is taken.\n");
3128 LocalHosts = crunch_list(optarg);
3131 case 'm': /* mark interval */
3132 if(iCompatibilityMode < 3) {
3133 MarkInterval = atoi(optarg) * 60;
3136 "-m option only supported in compatibility modes 0 to 2 - ignored\n");
3138 case 'M': /* default module load path */
3139 module.SetModDir((uchar*)optarg);
3141 case 'n': /* don't fork */
3145 if(iCompatibilityMode < 3) {
3146 if(!bImUxSockLoaded) {
3147 legacyOptsEnq((uchar *) "ModLoad imuxsock");
3148 bImUxSockLoaded = 1;
3150 legacyOptsEnq((uchar *) "OmitLocalLogging");
3152 fprintf(stderr, "error -o is no longer supported, use module imuxsock instead");
3156 if(iCompatibilityMode < 3) {
3157 if(!bImUxSockLoaded) {
3158 legacyOptsEnq((uchar *) "ModLoad imuxsock");
3159 bImUxSockLoaded = 1;
3161 snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "SystemLogSocketName %s", optarg);
3162 legacyOptsEnq(legacyConfLine);
3164 fprintf(stderr, "error -p is no longer supported, use module imuxsock instead");
3166 case 'q': /* add hostname if DNS resolving has failed */
3167 *net.pACLAddHostnameOnFail = 1;
3169 case 'Q': /* dont resolve hostnames in ACL to IPs */
3170 *net.pACLDontResolve = 1;
3172 case 'r': /* accept remote messages */
3174 if(iCompatibilityMode < 3) {
3175 legacyOptsEnq((uchar *) "ModLoad imudp");
3176 snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "UDPServerRun %s", optarg);
3177 legacyOptsEnq(legacyConfLine);
3180 "-r option only supported in compatibility modes 0 to 2 - ignored\n");
3182 fprintf(stderr, "rsyslogd: -r not valid - not compiled with network support\n");
3187 fprintf (stderr, "rsyslogd: Only one -s argument allowed, the first one is taken.\n");
3189 StripDomains = crunch_list(optarg);
3192 case 't': /* enable tcp logging */
3194 if(iCompatibilityMode < 3) {
3195 legacyOptsParseTCP(ch, optarg);
3197 fprintf(stderr, "-t option only supported in compatibility modes 0 to 2 - ignored\n");
3199 fprintf(stderr, "rsyslogd: -t not valid - not compiled with network support\n");
3202 case 'u': /* misc user settings */
3203 if(atoi(optarg) == 1)
3204 bParseHOSTNAMEandTAG = 0;
3208 exit(0); /* exit for -v option - so this is a "good one" */
3209 case 'w': /* disable disallowed host warnigs */
3210 option_DisallowWarning = 0;
3212 case 'x': /* disable dns for remote messages */
3219 bIsFirstOption = 0; /* we already saw an option character */
3222 if ((argc -= optind))
3225 /* TODO: this should go away at a reasonable stage of v3 development.
3226 * rgerhards, 2007-12-19
3228 if(iCompatibilityMode < 3) {
3229 errmsg.LogError(NO_ERRCODE, "WARNING: rsyslogd is running in compatibility mode. Automatically "
3230 "generated config directives may interfer with your rsyslog.conf settings. "
3231 "We suggest upgrading your config and adding -c3 as the first "
3232 "rsyslogd option.");
3233 if(MarkInterval > 0) {
3234 legacyOptsEnq((uchar *) "ModLoad immark");
3235 snprintf((char *) legacyConfLine, sizeof(legacyConfLine), "MarkMessagePeriod %d", MarkInterval);
3236 legacyOptsEnq(legacyConfLine);
3238 if(!bImUxSockLoaded) {
3239 legacyOptsEnq((uchar *) "ModLoad imuxsock");
3243 if(bEOptionWasGiven && iCompatibilityMode < 3) {
3244 errmsg.LogError(NO_ERRCODE, "WARNING: \"message repeated n times\" feature MUST be turned on in "
3245 "rsyslog.conf - CURRENTLY EVERY MESSAGE WILL BE LOGGED. Visit "
3246 "http://www.rsyslog.com/rptdmsgreduction to learn "
3247 "more and cast your vote if you want us to keep this feature.");
3253 if ( !(Debug || NoFork) )
3255 dbgprintf("Checking pidfile.\n");
3256 if (!check_pid(PidFile))
3258 memset(&sigAct, 0, sizeof (sigAct));
3259 sigemptyset(&sigAct.sa_mask);
3260 sigAct.sa_handler = doexit;
3261 sigaction(SIGTERM, &sigAct, NULL);
3269 * Not reached unless something major went wrong. 5
3270 * minutes should be a fair amount of time to wait.
3271 * Please note that this procedure is important since
3272 * the father must not exit before syslogd isn't
3273 * initialized or the klogd won't be able to flush its
3276 exit(1); /* "good" exit - after forking, not diasabling anything */
3278 num_fds = getdtablesize();
3279 for (i= 0; i < num_fds; i++)
3285 fputs(" Already running.\n", stderr);
3286 exit(1); /* "good" exit, done if syslogd is already running */
3292 dbgprintf("Compatibility Mode: %d\n", iCompatibilityMode);
3294 /* tuck my process id away */
3295 dbgprintf("Writing pidfile %s.\n", PidFile);
3296 if (!check_pid(PidFile))
3298 if (!write_pid(PidFile))
3300 fputs("Can't write pid.\n", stderr);
3301 exit(1); /* exit during startup - questionable */
3306 fputs("Pidfile (and pid) already exist.\n", stderr);
3307 exit(1); /* exit during startup - questionable */
3309 myPid = getpid(); /* save our pid for further testing (also used for messages) */
3311 memset(&sigAct, 0, sizeof (sigAct));
3312 sigemptyset(&sigAct.sa_mask);
3314 sigAct.sa_handler = sigsegvHdlr;
3315 sigaction(SIGSEGV, &sigAct, NULL);
3316 sigAct.sa_handler = sigsegvHdlr;
3317 sigaction(SIGABRT, &sigAct, NULL);
3318 sigAct.sa_handler = doDie;
3319 sigaction(SIGTERM, &sigAct, NULL);
3320 sigAct.sa_handler = Debug ? doDie : SIG_IGN;
3321 sigaction(SIGINT, &sigAct, NULL);
3322 sigaction(SIGQUIT, &sigAct, NULL);
3323 sigAct.sa_handler = reapchild;
3324 sigaction(SIGCHLD, &sigAct, NULL);
3325 sigAct.sa_handler = Debug ? debug_switch : SIG_IGN;
3326 sigaction(SIGUSR1, &sigAct, NULL);
3327 sigAct.sa_handler = SIG_IGN;
3328 sigaction(SIGPIPE, &sigAct, NULL);
3329 sigaction(SIGXFSZ, &sigAct, NULL); /* do not abort if 2gig file limit is hit */
3333 /* do any de-init's that need to be done AFTER this comment */
3340 if(iRet != RS_RET_OK)
3341 fprintf(stderr, "rsyslogd run failed with error %d\n(see rsyslog.h "
3342 "or http://www.rsyslog.com/errcode to learn what that number means)\n", iRet);
3349 /* This is the main entry point into rsyslogd. This must be a function in its own
3350 * right in order to intialize the debug system in a portable way (otherwise we would
3351 * need to have a statement before variable definitions.
3352 * rgerhards, 20080-01-28
3354 int main(int argc, char **argv)
3357 return realMain(argc, argv);