aboutsummaryrefslogtreecommitdiff
path: root/sysklogd/syslogd.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysklogd/syslogd.c')
-rw-r--r--sysklogd/syslogd.c364
1 files changed, 299 insertions, 65 deletions
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 24cab3b6c..b6f409f41 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -13,6 +13,35 @@
13 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 13 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
14 */ 14 */
15 15
16//usage:#define syslogd_trivial_usage
17//usage: "[OPTIONS]"
18//usage:#define syslogd_full_usage "\n\n"
19//usage: "System logging utility.\n"
20//usage: "This version of syslogd ignores /etc/syslog.conf\n"
21//usage: "\nOptions:"
22//usage: "\n -n Run in foreground"
23//usage: "\n -O FILE Log to given file (default:/var/log/messages)"
24//usage: "\n -l N Set local log level"
25//usage: "\n -S Smaller logging output"
26//usage: IF_FEATURE_ROTATE_LOGFILE(
27//usage: "\n -s SIZE Max size (KB) before rotate (default:200KB, 0=off)"
28//usage: "\n -b N N rotated logs to keep (default:1, max=99, 0=purge)")
29//usage: IF_FEATURE_REMOTE_LOG(
30//usage: "\n -R HOST[:PORT] Log to IP or hostname on PORT (default PORT=514/UDP)"
31//usage: "\n -L Log locally and via network (default is network only if -R)")
32//usage: IF_FEATURE_SYSLOGD_DUP(
33//usage: "\n -D Drop duplicates")
34//usage: IF_FEATURE_IPC_SYSLOG(
35//usage: "\n -C[size(KiB)] Log to shared mem buffer (read it using logread)")
36//usage: IF_FEATURE_SYSLOGD_CFG(
37//usage: "\n -f FILE Use FILE as config (default is /etc/syslog.conf)")
38/* NB: -Csize shouldn't have space (because size is optional) */
39/* //usage: "\n -m MIN Minutes between MARK lines (default:20, 0=off)" */
40//usage:
41//usage:#define syslogd_example_usage
42//usage: "$ syslogd -R masterlog:514\n"
43//usage: "$ syslogd -R 192.168.1.1:601\n"
44
16/* 45/*
17 * Done in syslogd_and_logger.c: 46 * Done in syslogd_and_logger.c:
18#include "libbb.h" 47#include "libbb.h"
@@ -66,10 +95,26 @@ typedef struct {
66} remoteHost_t; 95} remoteHost_t;
67#endif 96#endif
68 97
98typedef struct logFile_t {
99 const char *path;
100 int fd;
101#if ENABLE_FEATURE_ROTATE_LOGFILE
102 unsigned size;
103 uint8_t isRegular;
104#endif
105} logFile_t;
106
107#if ENABLE_FEATURE_SYSLOGD_CFG
108typedef struct logRule_t {
109 uint8_t enabled_facility_priomap[LOG_NFACILITIES];
110 struct logFile_t *file;
111 struct logRule_t *next;
112} logRule_t;
113#endif
114
69/* Allows us to have smaller initializer. Ugly. */ 115/* Allows us to have smaller initializer. Ugly. */
70#define GLOBALS \ 116#define GLOBALS \
71 const char *logFilePath; \ 117 logFile_t logFile; \
72 int logFD; \
73 /* interval between marks in seconds */ \ 118 /* interval between marks in seconds */ \
74 /*int markInterval;*/ \ 119 /*int markInterval;*/ \
75 /* level of messages to be logged */ \ 120 /* level of messages to be logged */ \
@@ -79,8 +124,6 @@ IF_FEATURE_ROTATE_LOGFILE( \
79 unsigned logFileSize; \ 124 unsigned logFileSize; \
80 /* number of rotated message files */ \ 125 /* number of rotated message files */ \
81 unsigned logFileRotate; \ 126 unsigned logFileRotate; \
82 unsigned curFileSize; \
83 smallint isRegular; \
84) \ 127) \
85IF_FEATURE_IPC_SYSLOG( \ 128IF_FEATURE_IPC_SYSLOG( \
86 int shmid; /* ipc shared memory id */ \ 129 int shmid; /* ipc shared memory id */ \
@@ -88,6 +131,9 @@ IF_FEATURE_IPC_SYSLOG( \
88 int shm_size; \ 131 int shm_size; \
89 struct sembuf SMwup[1]; \ 132 struct sembuf SMwup[1]; \
90 struct sembuf SMwdn[3]; \ 133 struct sembuf SMwdn[3]; \
134) \
135IF_FEATURE_SYSLOGD_CFG( \
136 logRule_t *log_rules; \
91) 137)
92 138
93struct init_globals { 139struct init_globals {
@@ -119,8 +165,10 @@ struct globals {
119}; 165};
120 166
121static const struct init_globals init_data = { 167static const struct init_globals init_data = {
122 .logFilePath = "/var/log/messages", 168 .logFile = {
123 .logFD = -1, 169 .path = "/var/log/messages",
170 .fd = -1,
171 },
124#ifdef SYSLOGD_MARK 172#ifdef SYSLOGD_MARK
125 .markInterval = 20 * 60, 173 .markInterval = 20 * 60,
126#endif 174#endif
@@ -132,7 +180,7 @@ static const struct init_globals init_data = {
132#if ENABLE_FEATURE_IPC_SYSLOG 180#if ENABLE_FEATURE_IPC_SYSLOG
133 .shmid = -1, 181 .shmid = -1,
134 .s_semid = -1, 182 .s_semid = -1,
135 .shm_size = ((CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE)*1024), // default shm size 183 .shm_size = ((CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE)*1024), /* default shm size */
136 .SMwup = { {1, -1, IPC_NOWAIT} }, 184 .SMwup = { {1, -1, IPC_NOWAIT} },
137 .SMwdn = { {0, 0}, {1, 0}, {1, +1} }, 185 .SMwdn = { {0, 0}, {1, 0}, {1, +1} },
138#endif 186#endif
@@ -157,6 +205,7 @@ enum {
157 IF_FEATURE_REMOTE_LOG( OPTBIT_locallog ,) // -L 205 IF_FEATURE_REMOTE_LOG( OPTBIT_locallog ,) // -L
158 IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C 206 IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C
159 IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D 207 IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D
208 IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f
160 209
161 OPT_mark = 1 << OPTBIT_mark , 210 OPT_mark = 1 << OPTBIT_mark ,
162 OPT_nofork = 1 << OPTBIT_nofork , 211 OPT_nofork = 1 << OPTBIT_nofork ,
@@ -169,6 +218,7 @@ enum {
169 OPT_locallog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_locallog )) + 0, 218 OPT_locallog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_locallog )) + 0,
170 OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0, 219 OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0,
171 OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0, 220 OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0,
221 OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0,
172}; 222};
173#define OPTION_STR "m:nO:l:S" \ 223#define OPTION_STR "m:nO:l:S" \
174 IF_FEATURE_ROTATE_LOGFILE("s:" ) \ 224 IF_FEATURE_ROTATE_LOGFILE("s:" ) \
@@ -176,17 +226,195 @@ enum {
176 IF_FEATURE_REMOTE_LOG( "R:" ) \ 226 IF_FEATURE_REMOTE_LOG( "R:" ) \
177 IF_FEATURE_REMOTE_LOG( "L" ) \ 227 IF_FEATURE_REMOTE_LOG( "L" ) \
178 IF_FEATURE_IPC_SYSLOG( "C::") \ 228 IF_FEATURE_IPC_SYSLOG( "C::") \
179 IF_FEATURE_SYSLOGD_DUP( "D" ) 229 IF_FEATURE_SYSLOGD_DUP( "D" ) \
230 IF_FEATURE_SYSLOGD_CFG( "f:" )
180#define OPTION_DECL *opt_m, *opt_l \ 231#define OPTION_DECL *opt_m, *opt_l \
181 IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \ 232 IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \
182 IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \ 233 IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \
183 IF_FEATURE_IPC_SYSLOG( ,*opt_C = NULL) 234 IF_FEATURE_IPC_SYSLOG( ,*opt_C = NULL) \
184#define OPTION_PARAM &opt_m, &G.logFilePath, &opt_l \ 235 IF_FEATURE_SYSLOGD_CFG( ,*opt_f = NULL)
236#define OPTION_PARAM &opt_m, &(G.logFile.path), &opt_l \
185 IF_FEATURE_ROTATE_LOGFILE(,&opt_s) \ 237 IF_FEATURE_ROTATE_LOGFILE(,&opt_s) \
186 IF_FEATURE_ROTATE_LOGFILE(,&opt_b) \ 238 IF_FEATURE_ROTATE_LOGFILE(,&opt_b) \
187 IF_FEATURE_REMOTE_LOG( ,&remoteAddrList) \ 239 IF_FEATURE_REMOTE_LOG( ,&remoteAddrList) \
188 IF_FEATURE_IPC_SYSLOG( ,&opt_C) 240 IF_FEATURE_IPC_SYSLOG( ,&opt_C) \
241 IF_FEATURE_SYSLOGD_CFG( ,&opt_f)
242
243
244#if ENABLE_FEATURE_SYSLOGD_CFG
245static const CODE* find_by_name(char *name, const CODE* c_set)
246{
247 for (; c_set->c_name; c_set++) {
248 if (strcmp(name, c_set->c_name) == 0)
249 return c_set;
250 }
251 return NULL;
252}
253#endif
254static const CODE* find_by_val(int val, const CODE* c_set)
255{
256 for (; c_set->c_name; c_set++) {
257 if (c_set->c_val == val)
258 return c_set;
259 }
260 return NULL;
261}
262
263#if ENABLE_FEATURE_SYSLOGD_CFG
264static void parse_syslogdcfg(const char *file)
265{
266 char *t;
267 logRule_t **pp_rule;
268 /* tok[0] set of selectors */
269 /* tok[1] file name */
270 /* tok[2] has to be NULL */
271 char *tok[3];
272 parser_t *parser;
273
274 parser = config_open2(file ? file : "/etc/syslog.conf",
275 file ? xfopen_for_read : fopen_or_warn_stdin);
276 if (!parser)
277 /* didn't find default /etc/syslog.conf */
278 /* proceed as if we built busybox without config support */
279 return;
280
281 /* use ptr to ptr to avoid checking whether head was initialized */
282 pp_rule = &G.log_rules;
283 /* iterate through lines of config, skipping comments */
284 while (config_read(parser, tok, 3, 2, "# \t", PARSE_NORMAL | PARSE_MIN_DIE)) {
285 char *cur_selector;
286 logRule_t *cur_rule;
287
288 /* unexpected trailing token? */
289 if (tok[2])
290 goto cfgerr;
291
292 cur_rule = *pp_rule = xzalloc(sizeof(*cur_rule));
293
294 cur_selector = tok[0];
295 /* iterate through selectors: "kern.info;kern.!err;..." */
296 do {
297 const CODE *code;
298 char *next_selector;
299 uint8_t negated_prio; /* "kern.!err" */
300 uint8_t single_prio; /* "kern.=err" */
301 uint32_t facmap; /* bitmap of enabled facilities */
302 uint8_t primap; /* bitmap of enabled priorities */
303 unsigned i;
304
305 next_selector = strchr(cur_selector, ';');
306 if (next_selector)
307 *next_selector++ = '\0';
308
309 t = strchr(cur_selector, '.');
310 if (!t)
311 goto cfgerr;
312 *t++ = '\0'; /* separate facility from priority */
313
314 negated_prio = 0;
315 single_prio = 0;
316 if (*t == '!') {
317 negated_prio = 1;
318 ++t;
319 }
320 if (*t == '=') {
321 single_prio = 1;
322 ++t;
323 }
324
325 /* parse priority */
326 if (*t == '*')
327 primap = 0xff; /* all 8 log levels enabled */
328 else {
329 uint8_t priority;
330 code = find_by_name(t, prioritynames);
331 if (!code)
332 goto cfgerr;
333 primap = 0;
334 priority = code->c_val;
335 if (priority == INTERNAL_NOPRI) {
336 /* ensure we take "enabled_facility_priomap[fac] &= 0" branch below */
337 negated_prio = 1;
338 } else {
339 priority = 1 << priority;
340 do {
341 primap |= priority;
342 if (single_prio)
343 break;
344 priority >>= 1;
345 } while (priority);
346 if (negated_prio)
347 primap = ~primap;
348 }
349 }
350
351 /* parse facility */
352 if (*cur_selector == '*')
353 facmap = (1<<LOG_NFACILITIES) - 1;
354 else {
355 char *next_facility;
356 facmap = 0;
357 t = cur_selector;
358 /* iterate through facilities: "kern,daemon.<priospec>" */
359 do {
360 next_facility = strchr(t, ',');
361 if (next_facility)
362 *next_facility++ = '\0';
363 code = find_by_name(t, facilitynames);
364 if (!code)
365 goto cfgerr;
366 /* "mark" is not a real facility, skip it */
367 if (code->c_val != INTERNAL_MARK)
368 facmap |= 1<<(LOG_FAC(code->c_val));
369 t = next_facility;
370 } while (t);
371 }
372
373 /* merge result with previous selectors */
374 for (i = 0; i < LOG_NFACILITIES; ++i) {
375 if (!(facmap & (1<<i)))
376 continue;
377 if (negated_prio)
378 cur_rule->enabled_facility_priomap[i] &= primap;
379 else
380 cur_rule->enabled_facility_priomap[i] |= primap;
381 }
382
383 cur_selector = next_selector;
384 } while (cur_selector);
385
386 /* check whether current file name was mentioned in previous rules or
387 * as global logfile (G.logFile).
388 */
389 if (strcmp(G.logFile.path, tok[1]) == 0) {
390 cur_rule->file = &G.logFile;
391 goto found;
392 }
393 /* temporarily use cur_rule as iterator, but *pp_rule still points
394 * to currently processing rule entry.
395 * NOTE: *pp_rule points to the current (and last in the list) rule.
396 */
397 for (cur_rule = G.log_rules; cur_rule != *pp_rule; cur_rule = cur_rule->next) {
398 if (strcmp(cur_rule->file->path, tok[1]) == 0) {
399 /* found - reuse the same file structure */
400 (*pp_rule)->file = cur_rule->file;
401 cur_rule = *pp_rule;
402 goto found;
403 }
404 }
405 cur_rule->file = xzalloc(sizeof(*cur_rule->file));
406 cur_rule->file->fd = -1;
407 cur_rule->file->path = xstrdup(tok[1]);
408 found:
409 pp_rule = &cur_rule->next;
410 }
411 config_close(parser);
412 return;
189 413
414 cfgerr:
415 bb_error_msg_and_die("error in '%s' at line %d", file, parser->lineno);
416}
417#endif
190 418
191/* circular buffer variables/structures */ 419/* circular buffer variables/structures */
192#if ENABLE_FEATURE_IPC_SYSLOG 420#if ENABLE_FEATURE_IPC_SYSLOG
@@ -231,7 +459,7 @@ static void ipcsyslog_init(void)
231 G.shbuf->size = G.shm_size - offsetof(struct shbuf_ds, data) - 1; 459 G.shbuf->size = G.shm_size - offsetof(struct shbuf_ds, data) - 1;
232 /*G.shbuf->tail = 0;*/ 460 /*G.shbuf->tail = 0;*/
233 461
234 // we'll trust the OS to set initial semval to 0 (let's hope) 462 /* 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); 463 G.s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023);
236 if (G.s_semid == -1) { 464 if (G.s_semid == -1) {
237 if (errno == EEXIST) { 465 if (errno == EEXIST) {
@@ -244,9 +472,10 @@ static void ipcsyslog_init(void)
244} 472}
245 473
246/* Write message to shared mem buffer */ 474/* Write message to shared mem buffer */
247static void log_to_shmem(const char *msg, int len) 475static void log_to_shmem(const char *msg)
248{ 476{
249 int old_tail, new_tail; 477 int old_tail, new_tail;
478 int len;
250 479
251 if (semop(G.s_semid, G.SMwdn, 3) == -1) { 480 if (semop(G.s_semid, G.SMwdn, 3) == -1) {
252 bb_perror_msg_and_die("SMwdn"); 481 bb_perror_msg_and_die("SMwdn");
@@ -258,7 +487,7 @@ static void log_to_shmem(const char *msg, int len)
258 * tail's max value is (shbuf->size - 1) 487 * tail's max value is (shbuf->size - 1)
259 * Last byte of buffer is never used and remains NUL. 488 * Last byte of buffer is never used and remains NUL.
260 */ 489 */
261 len++; /* length with NUL included */ 490 len = strlen(msg) + 1; /* length with NUL included */
262 again: 491 again:
263 old_tail = G.shbuf->tail; 492 old_tail = G.shbuf->tail;
264 new_tail = old_tail + len; 493 new_tail = old_tail + len;
@@ -288,22 +517,15 @@ void ipcsyslog_init(void);
288void log_to_shmem(const char *msg); 517void log_to_shmem(const char *msg);
289#endif /* FEATURE_IPC_SYSLOG */ 518#endif /* FEATURE_IPC_SYSLOG */
290 519
291
292/* Print a message to the log file. */ 520/* Print a message to the log file. */
293static void log_locally(time_t now, char *msg) 521static void log_locally(time_t now, char *msg, logFile_t *log_file)
294{ 522{
295#ifdef SYSLOGD_WRLOCK 523#ifdef SYSLOGD_WRLOCK
296 struct flock fl; 524 struct flock fl;
297#endif 525#endif
298 int len = strlen(msg); 526 int len = strlen(msg);
299 527
300#if ENABLE_FEATURE_IPC_SYSLOG 528 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 529 /* Reopen log file every second. This allows admin
308 * to delete the file and not worry about restarting us. 530 * to delete the file and not worry about restarting us.
309 * This costs almost nothing since it happens 531 * This costs almost nothing since it happens
@@ -313,15 +535,15 @@ static void log_locally(time_t now, char *msg)
313 now = time(NULL); 535 now = time(NULL);
314 if (G.last_log_time != now) { 536 if (G.last_log_time != now) {
315 G.last_log_time = now; 537 G.last_log_time = now;
316 close(G.logFD); 538 close(log_file->fd);
317 goto reopen; 539 goto reopen;
318 } 540 }
319 } else { 541 } else {
320 reopen: 542 reopen:
321 G.logFD = open(G.logFilePath, O_WRONLY | O_CREAT 543 log_file->fd = open(log_file->path, O_WRONLY | O_CREAT
322 | O_NOCTTY | O_APPEND | O_NONBLOCK, 544 | O_NOCTTY | O_APPEND | O_NONBLOCK,
323 0666); 545 0666);
324 if (G.logFD < 0) { 546 if (log_file->fd < 0) {
325 /* cannot open logfile? - print to /dev/console then */ 547 /* cannot open logfile? - print to /dev/console then */
326 int fd = device_open(DEV_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK); 548 int fd = device_open(DEV_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK);
327 if (fd < 0) 549 if (fd < 0)
@@ -334,9 +556,9 @@ static void log_locally(time_t now, char *msg)
334#if ENABLE_FEATURE_ROTATE_LOGFILE 556#if ENABLE_FEATURE_ROTATE_LOGFILE
335 { 557 {
336 struct stat statf; 558 struct stat statf;
337 G.isRegular = (fstat(G.logFD, &statf) == 0 && S_ISREG(statf.st_mode)); 559 log_file->isRegular = (fstat(log_file->fd, &statf) == 0 && S_ISREG(statf.st_mode));
338 /* bug (mostly harmless): can wrap around if file > 4gb */ 560 /* bug (mostly harmless): can wrap around if file > 4gb */
339 G.curFileSize = statf.st_size; 561 log_file->size = statf.st_size;
340 } 562 }
341#endif 563#endif
342 } 564 }
@@ -346,41 +568,41 @@ static void log_locally(time_t now, char *msg)
346 fl.l_start = 0; 568 fl.l_start = 0;
347 fl.l_len = 1; 569 fl.l_len = 1;
348 fl.l_type = F_WRLCK; 570 fl.l_type = F_WRLCK;
349 fcntl(G.logFD, F_SETLKW, &fl); 571 fcntl(log_file->fd, F_SETLKW, &fl);
350#endif 572#endif
351 573
352#if ENABLE_FEATURE_ROTATE_LOGFILE 574#if ENABLE_FEATURE_ROTATE_LOGFILE
353 if (G.logFileSize && G.isRegular && G.curFileSize > G.logFileSize) { 575 if (G.logFileSize && log_file->isRegular && log_file->size > G.logFileSize) {
354 if (G.logFileRotate) { /* always 0..99 */ 576 if (G.logFileRotate) { /* always 0..99 */
355 int i = strlen(G.logFilePath) + 3 + 1; 577 int i = strlen(log_file->path) + 3 + 1;
356 char oldFile[i]; 578 char oldFile[i];
357 char newFile[i]; 579 char newFile[i];
358 i = G.logFileRotate - 1; 580 i = G.logFileRotate - 1;
359 /* rename: f.8 -> f.9; f.7 -> f.8; ... */ 581 /* rename: f.8 -> f.9; f.7 -> f.8; ... */
360 while (1) { 582 while (1) {
361 sprintf(newFile, "%s.%d", G.logFilePath, i); 583 sprintf(newFile, "%s.%d", log_file->path, i);
362 if (i == 0) break; 584 if (i == 0) break;
363 sprintf(oldFile, "%s.%d", G.logFilePath, --i); 585 sprintf(oldFile, "%s.%d", log_file->path, --i);
364 /* ignore errors - file might be missing */ 586 /* ignore errors - file might be missing */
365 rename(oldFile, newFile); 587 rename(oldFile, newFile);
366 } 588 }
367 /* newFile == "f.0" now */ 589 /* newFile == "f.0" now */
368 rename(G.logFilePath, newFile); 590 rename(log_file->path, newFile);
369#ifdef SYSLOGD_WRLOCK 591#ifdef SYSLOGD_WRLOCK
370 fl.l_type = F_UNLCK; 592 fl.l_type = F_UNLCK;
371 fcntl(G.logFD, F_SETLKW, &fl); 593 fcntl(log_file->fd, F_SETLKW, &fl);
372#endif 594#endif
373 close(G.logFD); 595 close(log_file->fd);
374 goto reopen; 596 goto reopen;
375 } 597 }
376 ftruncate(G.logFD, 0); 598 ftruncate(log_file->fd, 0);
377 } 599 }
378 G.curFileSize += 600 log_file->size +=
379#endif 601#endif
380 full_write(G.logFD, msg, len); 602 full_write(log_file->fd, msg, len);
381#ifdef SYSLOGD_WRLOCK 603#ifdef SYSLOGD_WRLOCK
382 fl.l_type = F_UNLCK; 604 fl.l_type = F_UNLCK;
383 fcntl(G.logFD, F_SETLKW, &fl); 605 fcntl(log_file->fd, F_SETLKW, &fl);
384#endif 606#endif
385} 607}
386 608
@@ -388,29 +610,15 @@ static void parse_fac_prio_20(int pri, char *res20)
388{ 610{
389 const CODE *c_pri, *c_fac; 611 const CODE *c_pri, *c_fac;
390 612
391 if (pri != 0) { 613 c_fac = find_by_val(LOG_FAC(pri) << 3, facilitynames);
392 c_fac = facilitynames; 614 if (c_fac) {
393 while (c_fac->c_name) { 615 c_pri = find_by_val(LOG_PRI(pri), prioritynames);
394 if (c_fac->c_val != (LOG_FAC(pri) << 3)) { 616 if (c_pri) {
395 c_fac++; 617 snprintf(res20, 20, "%s.%s", c_fac->c_name, c_pri->c_name);
396 continue; 618 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 } 619 }
412 snprintf(res20, 20, "<%d>", pri);
413 } 620 }
621 snprintf(res20, 20, "<%d>", pri);
414} 622}
415 623
416/* len parameter is used only for "is there a timestamp?" check. 624/* len parameter is used only for "is there a timestamp?" check.
@@ -444,7 +652,32 @@ static void timestamp_and_log(int pri, char *msg, int len)
444 } 652 }
445 653
446 /* Log message locally (to file or shared mem) */ 654 /* Log message locally (to file or shared mem) */
447 log_locally(now, G.printbuf); 655#if ENABLE_FEATURE_SYSLOGD_CFG
656 {
657 bool match = 0;
658 logRule_t *rule;
659 uint8_t facility = LOG_FAC(pri);
660 uint8_t prio_bit = 1 << LOG_PRI(pri);
661
662 for (rule = G.log_rules; rule; rule = rule->next) {
663 if (rule->enabled_facility_priomap[facility] & prio_bit) {
664 log_locally(now, G.printbuf, rule->file);
665 match = 1;
666 }
667 }
668 if (match)
669 return;
670 }
671#endif
672 if (LOG_PRI(pri) < G.logLevel) {
673#if ENABLE_FEATURE_IPC_SYSLOG
674 if ((option_mask32 & OPT_circularlog) && G.shbuf) {
675 log_to_shmem(msg);
676 return;
677 }
678#endif
679 log_locally(now, G.printbuf, &G.logFile);
680 }
448} 681}
449 682
450static void timestamp_and_log_internal(const char *msg) 683static void timestamp_and_log_internal(const char *msg)
@@ -489,8 +722,7 @@ static void split_escape_and_log(char *tmpbuf, int len)
489 *q = '\0'; 722 *q = '\0';
490 723
491 /* Now log it */ 724 /* Now log it */
492 if (LOG_PRI(pri) < G.logLevel) 725 timestamp_and_log(pri, G.parsebuf, q - G.parsebuf);
493 timestamp_and_log(pri, G.parsebuf, q - G.parsebuf);
494 } 726 }
495} 727}
496 728
@@ -719,10 +951,12 @@ int syslogd_main(int argc UNUSED_PARAM, char **argv)
719 if (opt_C) // -Cn 951 if (opt_C) // -Cn
720 G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024; 952 G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024;
721#endif 953#endif
722
723 /* If they have not specified remote logging, then log locally */ 954 /* If they have not specified remote logging, then log locally */
724 if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R 955 if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R
725 option_mask32 |= OPT_locallog; 956 option_mask32 |= OPT_locallog;
957#if ENABLE_FEATURE_SYSLOGD_CFG
958 parse_syslogdcfg(opt_f);
959#endif
726 960
727 /* Store away localhost's name before the fork */ 961 /* Store away localhost's name before the fork */
728 G.hostname = safe_gethostname(); 962 G.hostname = safe_gethostname();