aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sysklogd/Config.src7
-rw-r--r--sysklogd/syslogd.c333
2 files changed, 275 insertions, 65 deletions
diff --git a/sysklogd/Config.src b/sysklogd/Config.src
index d62dc5f5c..b3e13d7c0 100644
--- a/sysklogd/Config.src
+++ b/sysklogd/Config.src
@@ -52,6 +52,13 @@ config FEATURE_SYSLOGD_DUP
52 Option -D instructs syslogd to drop consecutive messages 52 Option -D instructs syslogd to drop consecutive messages
53 which are totally the same. 53 which are totally the same.
54 54
55config FEATURE_SYSLOGD_CFG
56 bool "Support syslog.conf"
57 default y
58 depends on SYSLOGD
59 help
60 Supports restricted syslogd config.
61
55config FEATURE_SYSLOGD_READ_BUFFER_SIZE 62config FEATURE_SYSLOGD_READ_BUFFER_SIZE
56 int "Read buffer size in bytes" 63 int "Read buffer size in bytes"
57 default 256 64 default 256
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 24cab3b6c..f179dc5ac 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -66,10 +66,26 @@ typedef struct {
66} remoteHost_t; 66} remoteHost_t;
67#endif 67#endif
68 68
69typedef struct logFile_t {
70 const char *path;
71 int fd;
72#if ENABLE_FEATURE_ROTATE_LOGFILE
73 unsigned size;
74 uint8_t isRegular;
75#endif
76} logFile_t;
77
78#if ENABLE_FEATURE_SYSLOGD_CFG
79typedef struct logRule_t {
80 uint8_t enabled_facility_priomap[LOG_NFACILITIES];
81 struct logFile_t *file;
82 struct logRule_t *next;
83} logRule_t;
84#endif
85
69/* Allows us to have smaller initializer. Ugly. */ 86/* Allows us to have smaller initializer. Ugly. */
70#define GLOBALS \ 87#define GLOBALS \
71 const char *logFilePath; \ 88 logFile_t logFile; \
72 int logFD; \
73 /* interval between marks in seconds */ \ 89 /* interval between marks in seconds */ \
74 /*int markInterval;*/ \ 90 /*int markInterval;*/ \
75 /* level of messages to be logged */ \ 91 /* level of messages to be logged */ \
@@ -79,8 +95,6 @@ IF_FEATURE_ROTATE_LOGFILE( \
79 unsigned logFileSize; \ 95 unsigned logFileSize; \
80 /* number of rotated message files */ \ 96 /* number of rotated message files */ \
81 unsigned logFileRotate; \ 97 unsigned logFileRotate; \
82 unsigned curFileSize; \
83 smallint isRegular; \
84) \ 98) \
85IF_FEATURE_IPC_SYSLOG( \ 99IF_FEATURE_IPC_SYSLOG( \
86 int shmid; /* ipc shared memory id */ \ 100 int shmid; /* ipc shared memory id */ \
@@ -88,6 +102,9 @@ IF_FEATURE_IPC_SYSLOG( \
88 int shm_size; \ 102 int shm_size; \
89 struct sembuf SMwup[1]; \ 103 struct sembuf SMwup[1]; \
90 struct sembuf SMwdn[3]; \ 104 struct sembuf SMwdn[3]; \
105) \
106IF_FEATURE_SYSLOGD_CFG( \
107 logRule_t *log_rules; \
91) 108)
92 109
93struct init_globals { 110struct init_globals {
@@ -119,8 +136,10 @@ struct globals {
119}; 136};
120 137
121static const struct init_globals init_data = { 138static const struct init_globals init_data = {
122 .logFilePath = "/var/log/messages", 139 .logFile = {
123 .logFD = -1, 140 .path = "/var/log/messages",
141 .fd = -1,
142 },
124#ifdef SYSLOGD_MARK 143#ifdef SYSLOGD_MARK
125 .markInterval = 20 * 60, 144 .markInterval = 20 * 60,
126#endif 145#endif
@@ -132,7 +151,7 @@ static const struct init_globals init_data = {
132#if ENABLE_FEATURE_IPC_SYSLOG 151#if ENABLE_FEATURE_IPC_SYSLOG
133 .shmid = -1, 152 .shmid = -1,
134 .s_semid = -1, 153 .s_semid = -1,
135 .shm_size = ((CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE)*1024), // default shm size 154 .shm_size = ((CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE)*1024), /* default shm size */
136 .SMwup = { {1, -1, IPC_NOWAIT} }, 155 .SMwup = { {1, -1, IPC_NOWAIT} },
137 .SMwdn = { {0, 0}, {1, 0}, {1, +1} }, 156 .SMwdn = { {0, 0}, {1, 0}, {1, +1} },
138#endif 157#endif
@@ -157,6 +176,7 @@ enum {
157 IF_FEATURE_REMOTE_LOG( OPTBIT_locallog ,) // -L 176 IF_FEATURE_REMOTE_LOG( OPTBIT_locallog ,) // -L
158 IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C 177 IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C
159 IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D 178 IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D
179 IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f
160 180
161 OPT_mark = 1 << OPTBIT_mark , 181 OPT_mark = 1 << OPTBIT_mark ,
162 OPT_nofork = 1 << OPTBIT_nofork , 182 OPT_nofork = 1 << OPTBIT_nofork ,
@@ -169,6 +189,7 @@ enum {
169 OPT_locallog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_locallog )) + 0, 189 OPT_locallog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_locallog )) + 0,
170 OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0, 190 OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0,
171 OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0, 191 OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0,
192 OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0,
172}; 193};
173#define OPTION_STR "m:nO:l:S" \ 194#define OPTION_STR "m:nO:l:S" \
174 IF_FEATURE_ROTATE_LOGFILE("s:" ) \ 195 IF_FEATURE_ROTATE_LOGFILE("s:" ) \
@@ -176,18 +197,194 @@ enum {
176 IF_FEATURE_REMOTE_LOG( "R:" ) \ 197 IF_FEATURE_REMOTE_LOG( "R:" ) \
177 IF_FEATURE_REMOTE_LOG( "L" ) \ 198 IF_FEATURE_REMOTE_LOG( "L" ) \
178 IF_FEATURE_IPC_SYSLOG( "C::") \ 199 IF_FEATURE_IPC_SYSLOG( "C::") \
179 IF_FEATURE_SYSLOGD_DUP( "D" ) 200 IF_FEATURE_SYSLOGD_DUP( "D" ) \
201 IF_FEATURE_SYSLOGD_CFG( "f:" )
180#define OPTION_DECL *opt_m, *opt_l \ 202#define OPTION_DECL *opt_m, *opt_l \
181 IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \ 203 IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \
182 IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \ 204 IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \
183 IF_FEATURE_IPC_SYSLOG( ,*opt_C = NULL) 205 IF_FEATURE_IPC_SYSLOG( ,*opt_C = NULL) \
184#define OPTION_PARAM &opt_m, &G.logFilePath, &opt_l \ 206 IF_FEATURE_SYSLOGD_CFG( ,*opt_f = NULL)
207#define OPTION_PARAM &opt_m, &(G.logFile.path), &opt_l \
185 IF_FEATURE_ROTATE_LOGFILE(,&opt_s) \ 208 IF_FEATURE_ROTATE_LOGFILE(,&opt_s) \
186 IF_FEATURE_ROTATE_LOGFILE(,&opt_b) \ 209 IF_FEATURE_ROTATE_LOGFILE(,&opt_b) \
187 IF_FEATURE_REMOTE_LOG( ,&remoteAddrList) \ 210 IF_FEATURE_REMOTE_LOG( ,&remoteAddrList) \
188 IF_FEATURE_IPC_SYSLOG( ,&opt_C) 211 IF_FEATURE_IPC_SYSLOG( ,&opt_C) \
212 IF_FEATURE_SYSLOGD_CFG( ,&opt_f)
189 213
190 214
215#if ENABLE_FEATURE_SYSLOGD_CFG
216static const CODE* find_by_name(char *name, const CODE* c_set)
217{
218 for (; c_set->c_name; c_set++) {
219 if (strcmp(name, c_set->c_name) == 0)
220 return c_set;
221 }
222 return NULL;
223}
224#endif
225static const CODE* find_by_val(int val, const CODE* c_set)
226{
227 for (; c_set->c_name; c_set++) {
228 if (c_set->c_val == val)
229 return c_set;
230 }
231 return NULL;
232}
233
234#if ENABLE_FEATURE_SYSLOGD_CFG
235static void parse_syslogdcfg(const char *file)
236{
237 char *t;
238 logRule_t **pp_rule;
239 /* tok[0] set of selectors */
240 /* tok[1] file name */
241 /* tok[2] has to be NULL */
242 char *tok[3];
243 parser_t *parser;
244
245 parser = config_open2(file ? file : "/etc/syslog.conf",
246 file ? xfopen_for_read : fopen_or_warn_stdin);
247 if (!parser)
248 /* didn't find default /etc/syslog.conf */
249 /* proceed as if we built busybox without config support */
250 return;
251
252 /* use ptr to ptr to avoid checking whether head was initialized */
253 pp_rule = &G.log_rules;
254 /* iterate through lines of config, skipping comments */
255 while (config_read(parser, tok, 3, 2, "# \t", PARSE_NORMAL | PARSE_MIN_DIE)) {
256 char *cur_selector;
257 logRule_t *cur_rule;
258
259 /* unexpected trailing token? */
260 if (tok[2]) {
261 t = tok[2];
262 goto cfgerr;
263 }
264
265 cur_rule = *pp_rule = xzalloc(sizeof(*cur_rule));
266
267 cur_selector = tok[0];
268 /* iterate through selectors: "kern.info;kern.!err;..." */
269 do {
270 const CODE *code;
271 char *next_selector;
272 uint8_t negated_prio; /* "kern.!err" */
273 uint8_t single_prio; /* "kern.=err" */
274 uint32_t facmap; /* bitmap of enabled facilities */
275 uint8_t primap; /* bitmap of enabled priorities */
276 unsigned i;
277
278 next_selector = strchr(cur_selector, ';');
279 if (next_selector)
280 *next_selector++ = '\0';
281
282 t = strchr(cur_selector, '.');
283 if (!t) {
284 t = cur_selector;
285 goto cfgerr;
286 }
287 *t++ = '\0'; /* separate facility from priority */
288
289 negated_prio = 0;
290 single_prio = 0;
291 if (*t == '!') {
292 negated_prio = 1;
293 ++t;
294 }
295 if (*t == '=') {
296 single_prio = 1;
297 ++t;
298 }
299
300 /* parse priority */
301 if (*t == '*')
302 primap = 0xff; /* all 8 log levels enabled */
303 else {
304 uint8_t priority;
305 code = find_by_name(t, prioritynames);
306 if (!code)
307 goto cfgerr;
308 primap = 0;
309 priority = code->c_val;
310 if (priority == INTERNAL_NOPRI) {
311 /* ensure we take "enabled_facility_priomap[fac] &= 0" branch below */
312 negated_prio = 1;
313 } else {
314 priority = 1 << priority;
315 do {
316 primap |= priority;
317 if (single_prio)
318 break;
319 priority >>= 1;
320 } while (priority);
321 if (negated_prio)
322 primap = ~primap;
323 }
324 }
325
326 /* parse facility */
327 if (*cur_selector == '*')
328 facmap = (1<<LOG_NFACILITIES) - 1;
329 else {
330 char *next_facility;
331 facmap = 0;
332 t = cur_selector;
333 /* iterate through facilities: "kern,daemon.<priospec>" */
334 do {
335 next_facility = strchr(t, ',');
336 if (next_facility)
337 *next_facility++ = '\0';
338 code = find_by_name(t, facilitynames);
339 if (!code)
340 goto cfgerr;
341 /* "mark" is not a real facility, skip it */
342 if (code->c_val != INTERNAL_MARK)
343 facmap |= 1<<(LOG_FAC(code->c_val));
344 t = next_facility;
345 } while (t);
346 }
347
348 /* merge result with previous selectors */
349 for (i = 0; i < LOG_NFACILITIES; ++i) {
350 if (!(facmap & (1<<i)))
351 continue;
352 if (negated_prio)
353 cur_rule->enabled_facility_priomap[i] &= primap;
354 else
355 cur_rule->enabled_facility_priomap[i] |= primap;
356 }
357
358 cur_selector = next_selector;
359 } while (cur_selector);
360
361 /* check whether current file name was mentioned in previous rules.
362 * temporarily use cur_rule as iterator, but *pp_rule still points to
363 * currently processing rule entry.
364 * NOTE: *pp_rule points to the current (and last in the list) rule.
365 */
366 for (cur_rule = G.log_rules; cur_rule != *pp_rule; cur_rule = cur_rule->next) {
367 if (strcmp(cur_rule->file->path, tok[1]) == 0) {
368 /* found - reuse the same file structure */
369 (*pp_rule)->file = cur_rule->file;
370 cur_rule = *pp_rule;
371 goto found;
372 }
373 }
374 cur_rule->file = xzalloc(sizeof(*cur_rule->file));
375 cur_rule->file->fd = -1;
376 cur_rule->file->path = xstrdup(tok[1]);
377 found:
378 pp_rule = &cur_rule->next;
379 }
380 config_close(parser);
381 return;
382
383 cfgerr:
384 bb_error_msg_and_die("bad line %d: wrong token '%s'", parser->lineno, t);
385}
386#endif
387
191/* circular buffer variables/structures */ 388/* circular buffer variables/structures */
192#if ENABLE_FEATURE_IPC_SYSLOG 389#if ENABLE_FEATURE_IPC_SYSLOG
193 390
@@ -231,7 +428,7 @@ static void ipcsyslog_init(void)
231 G.shbuf->size = G.shm_size - offsetof(struct shbuf_ds, data) - 1; 428 G.shbuf->size = G.shm_size - offsetof(struct shbuf_ds, data) - 1;
232 /*G.shbuf->tail = 0;*/ 429 /*G.shbuf->tail = 0;*/
233 430
234 // we'll trust the OS to set initial semval to 0 (let's hope) 431 /* we'll trust the OS to set initial semval to 0 (let's hope) */
235 G.s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023); 432 G.s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023);
236 if (G.s_semid == -1) { 433 if (G.s_semid == -1) {
237 if (errno == EEXIST) { 434 if (errno == EEXIST) {
@@ -244,9 +441,10 @@ static void ipcsyslog_init(void)
244} 441}
245 442
246/* Write message to shared mem buffer */ 443/* Write message to shared mem buffer */
247static void log_to_shmem(const char *msg, int len) 444static void log_to_shmem(const char *msg)
248{ 445{
249 int old_tail, new_tail; 446 int old_tail, new_tail;
447 int len;
250 448
251 if (semop(G.s_semid, G.SMwdn, 3) == -1) { 449 if (semop(G.s_semid, G.SMwdn, 3) == -1) {
252 bb_perror_msg_and_die("SMwdn"); 450 bb_perror_msg_and_die("SMwdn");
@@ -258,7 +456,7 @@ static void log_to_shmem(const char *msg, int len)
258 * tail's max value is (shbuf->size - 1) 456 * tail's max value is (shbuf->size - 1)
259 * Last byte of buffer is never used and remains NUL. 457 * Last byte of buffer is never used and remains NUL.
260 */ 458 */
261 len++; /* length with NUL included */ 459 len = strlen(msg) + 1; /* length with NUL included */
262 again: 460 again:
263 old_tail = G.shbuf->tail; 461 old_tail = G.shbuf->tail;
264 new_tail = old_tail + len; 462 new_tail = old_tail + len;
@@ -288,22 +486,15 @@ void ipcsyslog_init(void);
288void log_to_shmem(const char *msg); 486void log_to_shmem(const char *msg);
289#endif /* FEATURE_IPC_SYSLOG */ 487#endif /* FEATURE_IPC_SYSLOG */
290 488
291
292/* Print a message to the log file. */ 489/* Print a message to the log file. */
293static void log_locally(time_t now, char *msg) 490static void log_locally(time_t now, char *msg, logFile_t *log_file)
294{ 491{
295#ifdef SYSLOGD_WRLOCK 492#ifdef SYSLOGD_WRLOCK
296 struct flock fl; 493 struct flock fl;
297#endif 494#endif
298 int len = strlen(msg); 495 int len = strlen(msg);
299 496
300#if ENABLE_FEATURE_IPC_SYSLOG 497 if (log_file->fd >= 0) {
301 if ((option_mask32 & OPT_circularlog) && G.shbuf) {
302 log_to_shmem(msg, len);
303 return;
304 }
305#endif
306 if (G.logFD >= 0) {
307 /* Reopen log file every second. This allows admin 498 /* Reopen log file every second. This allows admin
308 * to delete the file and not worry about restarting us. 499 * to delete the file and not worry about restarting us.
309 * This costs almost nothing since it happens 500 * This costs almost nothing since it happens
@@ -313,15 +504,15 @@ static void log_locally(time_t now, char *msg)
313 now = time(NULL); 504 now = time(NULL);
314 if (G.last_log_time != now) { 505 if (G.last_log_time != now) {
315 G.last_log_time = now; 506 G.last_log_time = now;
316 close(G.logFD); 507 close(log_file->fd);
317 goto reopen; 508 goto reopen;
318 } 509 }
319 } else { 510 } else {
320 reopen: 511 reopen:
321 G.logFD = open(G.logFilePath, O_WRONLY | O_CREAT 512 log_file->fd = open(log_file->path, O_WRONLY | O_CREAT
322 | O_NOCTTY | O_APPEND | O_NONBLOCK, 513 | O_NOCTTY | O_APPEND | O_NONBLOCK,
323 0666); 514 0666);
324 if (G.logFD < 0) { 515 if (log_file->fd < 0) {
325 /* cannot open logfile? - print to /dev/console then */ 516 /* cannot open logfile? - print to /dev/console then */
326 int fd = device_open(DEV_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK); 517 int fd = device_open(DEV_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK);
327 if (fd < 0) 518 if (fd < 0)
@@ -334,9 +525,9 @@ static void log_locally(time_t now, char *msg)
334#if ENABLE_FEATURE_ROTATE_LOGFILE 525#if ENABLE_FEATURE_ROTATE_LOGFILE
335 { 526 {
336 struct stat statf; 527 struct stat statf;
337 G.isRegular = (fstat(G.logFD, &statf) == 0 && S_ISREG(statf.st_mode)); 528 log_file->isRegular = (fstat(log_file->fd, &statf) == 0 && S_ISREG(statf.st_mode));
338 /* bug (mostly harmless): can wrap around if file > 4gb */ 529 /* bug (mostly harmless): can wrap around if file > 4gb */
339 G.curFileSize = statf.st_size; 530 log_file->size = statf.st_size;
340 } 531 }
341#endif 532#endif
342 } 533 }
@@ -346,41 +537,41 @@ static void log_locally(time_t now, char *msg)
346 fl.l_start = 0; 537 fl.l_start = 0;
347 fl.l_len = 1; 538 fl.l_len = 1;
348 fl.l_type = F_WRLCK; 539 fl.l_type = F_WRLCK;
349 fcntl(G.logFD, F_SETLKW, &fl); 540 fcntl(log_file->fd, F_SETLKW, &fl);
350#endif 541#endif
351 542
352#if ENABLE_FEATURE_ROTATE_LOGFILE 543#if ENABLE_FEATURE_ROTATE_LOGFILE
353 if (G.logFileSize && G.isRegular && G.curFileSize > G.logFileSize) { 544 if (G.logFileSize && log_file->isRegular && log_file->size > G.logFileSize) {
354 if (G.logFileRotate) { /* always 0..99 */ 545 if (G.logFileRotate) { /* always 0..99 */
355 int i = strlen(G.logFilePath) + 3 + 1; 546 int i = strlen(log_file->path) + 3 + 1;
356 char oldFile[i]; 547 char oldFile[i];
357 char newFile[i]; 548 char newFile[i];
358 i = G.logFileRotate - 1; 549 i = G.logFileRotate - 1;
359 /* rename: f.8 -> f.9; f.7 -> f.8; ... */ 550 /* rename: f.8 -> f.9; f.7 -> f.8; ... */
360 while (1) { 551 while (1) {
361 sprintf(newFile, "%s.%d", G.logFilePath, i); 552 sprintf(newFile, "%s.%d", log_file->path, i);
362 if (i == 0) break; 553 if (i == 0) break;
363 sprintf(oldFile, "%s.%d", G.logFilePath, --i); 554 sprintf(oldFile, "%s.%d", log_file->path, --i);
364 /* ignore errors - file might be missing */ 555 /* ignore errors - file might be missing */
365 rename(oldFile, newFile); 556 rename(oldFile, newFile);
366 } 557 }
367 /* newFile == "f.0" now */ 558 /* newFile == "f.0" now */
368 rename(G.logFilePath, newFile); 559 rename(log_file->path, newFile);
369#ifdef SYSLOGD_WRLOCK 560#ifdef SYSLOGD_WRLOCK
370 fl.l_type = F_UNLCK; 561 fl.l_type = F_UNLCK;
371 fcntl(G.logFD, F_SETLKW, &fl); 562 fcntl(log_file->fd, F_SETLKW, &fl);
372#endif 563#endif
373 close(G.logFD); 564 close(log_file->fd);
374 goto reopen; 565 goto reopen;
375 } 566 }
376 ftruncate(G.logFD, 0); 567 ftruncate(log_file->fd, 0);
377 } 568 }
378 G.curFileSize += 569 log_file->size +=
379#endif 570#endif
380 full_write(G.logFD, msg, len); 571 full_write(log_file->fd, msg, len);
381#ifdef SYSLOGD_WRLOCK 572#ifdef SYSLOGD_WRLOCK
382 fl.l_type = F_UNLCK; 573 fl.l_type = F_UNLCK;
383 fcntl(G.logFD, F_SETLKW, &fl); 574 fcntl(log_file->fd, F_SETLKW, &fl);
384#endif 575#endif
385} 576}
386 577
@@ -388,29 +579,15 @@ static void parse_fac_prio_20(int pri, char *res20)
388{ 579{
389 const CODE *c_pri, *c_fac; 580 const CODE *c_pri, *c_fac;
390 581
391 if (pri != 0) { 582 c_fac = find_by_val(LOG_FAC(pri) << 3, facilitynames);
392 c_fac = facilitynames; 583 if (c_fac) {
393 while (c_fac->c_name) { 584 c_pri = find_by_val(LOG_PRI(pri), prioritynames);
394 if (c_fac->c_val != (LOG_FAC(pri) << 3)) { 585 if (c_pri) {
395 c_fac++; 586 snprintf(res20, 20, "%s.%s", c_fac->c_name, c_pri->c_name);
396 continue; 587 return;
397 }
398 /* facility is found, look for prio */
399 c_pri = prioritynames;
400 while (c_pri->c_name) {
401 if (c_pri->c_val != LOG_PRI(pri)) {
402 c_pri++;
403 continue;
404 }
405 snprintf(res20, 20, "%s.%s",
406 c_fac->c_name, c_pri->c_name);
407 return;
408 }
409 /* prio not found, bail out */
410 break;
411 } 588 }
412 snprintf(res20, 20, "<%d>", pri);
413 } 589 }
590 snprintf(res20, 20, "<%d>", pri);
414} 591}
415 592
416/* len parameter is used only for "is there a timestamp?" check. 593/* len parameter is used only for "is there a timestamp?" check.
@@ -444,7 +621,32 @@ static void timestamp_and_log(int pri, char *msg, int len)
444 } 621 }
445 622
446 /* Log message locally (to file or shared mem) */ 623 /* Log message locally (to file or shared mem) */
447 log_locally(now, G.printbuf); 624#if ENABLE_FEATURE_SYSLOGD_CFG
625 {
626 bool match = 0;
627 logRule_t *rule;
628 uint8_t facility = LOG_FAC(pri);
629 uint8_t prio_bit = 1 << LOG_PRI(pri);
630
631 for (rule = G.log_rules; rule; rule = rule->next) {
632 if (rule->enabled_facility_priomap[facility] & prio_bit) {
633 log_locally(now, G.printbuf, rule->file);
634 match = 1;
635 }
636 }
637 if (match)
638 return;
639 }
640#endif
641 if (LOG_PRI(pri) < G.logLevel) {
642#if ENABLE_FEATURE_IPC_SYSLOG
643 if ((option_mask32 & OPT_circularlog) && G.shbuf) {
644 log_to_shmem(msg);
645 return;
646 }
647#endif
648 log_locally(now, G.printbuf, &G.logFile);
649 }
448} 650}
449 651
450static void timestamp_and_log_internal(const char *msg) 652static void timestamp_and_log_internal(const char *msg)
@@ -489,8 +691,7 @@ static void split_escape_and_log(char *tmpbuf, int len)
489 *q = '\0'; 691 *q = '\0';
490 692
491 /* Now log it */ 693 /* Now log it */
492 if (LOG_PRI(pri) < G.logLevel) 694 timestamp_and_log(pri, G.parsebuf, q - G.parsebuf);
493 timestamp_and_log(pri, G.parsebuf, q - G.parsebuf);
494 } 695 }
495} 696}
496 697
@@ -719,10 +920,12 @@ int syslogd_main(int argc UNUSED_PARAM, char **argv)
719 if (opt_C) // -Cn 920 if (opt_C) // -Cn
720 G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024; 921 G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024;
721#endif 922#endif
722
723 /* If they have not specified remote logging, then log locally */ 923 /* If they have not specified remote logging, then log locally */
724 if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R 924 if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R
725 option_mask32 |= OPT_locallog; 925 option_mask32 |= OPT_locallog;
926#if ENABLE_FEATURE_SYSLOGD_CFG
927 parse_syslogdcfg(opt_f);
928#endif
726 929
727 /* Store away localhost's name before the fork */ 930 /* Store away localhost's name before the fork */
728 G.hostname = safe_gethostname(); 931 G.hostname = safe_gethostname();