diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-13 09:19:14 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-13 09:19:14 +0000 |
commit | 75cddd8eb514082c8f9945ae1976f97c4b0413b4 (patch) | |
tree | d83dfad188c25d4765ec3ba1156c697e2442cdb3 | |
parent | 0a4624aece9e46b0580dd2d5867b41f6d06ef160 (diff) | |
download | busybox-w32-75cddd8eb514082c8f9945ae1976f97c4b0413b4.tar.gz busybox-w32-75cddd8eb514082c8f9945ae1976f97c4b0413b4.tar.bz2 busybox-w32-75cddd8eb514082c8f9945ae1976f97c4b0413b4.zip |
syslogd: send '\n'-terminated messages over the network.
fully closes bug 1574. +8 bytes.
-rw-r--r-- | sysklogd/syslogd.c | 36 |
1 files changed, 21 insertions, 15 deletions
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index f3ebf9392..457f38103 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c | |||
@@ -370,13 +370,15 @@ static void parse_fac_prio_20(int pri, char *res20) | |||
370 | c_fac = facilitynames; | 370 | c_fac = facilitynames; |
371 | while (c_fac->c_name) { | 371 | while (c_fac->c_name) { |
372 | if (c_fac->c_val != (LOG_FAC(pri) << 3)) { | 372 | if (c_fac->c_val != (LOG_FAC(pri) << 3)) { |
373 | c_fac++; continue; | 373 | c_fac++; |
374 | continue; | ||
374 | } | 375 | } |
375 | /* facility is found, look for prio */ | 376 | /* facility is found, look for prio */ |
376 | c_pri = prioritynames; | 377 | c_pri = prioritynames; |
377 | while (c_pri->c_name) { | 378 | while (c_pri->c_name) { |
378 | if (c_pri->c_val != LOG_PRI(pri)) { | 379 | if (c_pri->c_val != LOG_PRI(pri)) { |
379 | c_pri++; continue; | 380 | c_pri++; |
381 | continue; | ||
380 | } | 382 | } |
381 | snprintf(res20, 20, "%s.%s", | 383 | snprintf(res20, 20, "%s.%s", |
382 | c_fac->c_name, c_pri->c_name); | 384 | c_fac->c_name, c_pri->c_name); |
@@ -428,6 +430,9 @@ static void timestamp_and_log_internal(const char *msg) | |||
428 | timestamp_and_log(LOG_SYSLOG | LOG_INFO, (char*)msg, 0); | 430 | timestamp_and_log(LOG_SYSLOG | LOG_INFO, (char*)msg, 0); |
429 | } | 431 | } |
430 | 432 | ||
433 | /* tmpbuf[len] is a NUL byte (set by caller), but there can be other, | ||
434 | * embedded NULs. Split messages on each of these NULs, parse prio, | ||
435 | * escape control chars and log each locally. */ | ||
431 | static void split_escape_and_log(char *tmpbuf, int len) | 436 | static void split_escape_and_log(char *tmpbuf, int len) |
432 | { | 437 | { |
433 | char *p = tmpbuf; | 438 | char *p = tmpbuf; |
@@ -556,30 +561,24 @@ static void do_syslogd(void) | |||
556 | size_t sz; | 561 | size_t sz; |
557 | read_again: | 562 | read_again: |
558 | sz = safe_read(sock_fd, G.recvbuf, MAX_READ - 1); | 563 | sz = safe_read(sock_fd, G.recvbuf, MAX_READ - 1); |
559 | if (sz < 0) { | 564 | if (sz < 0) |
560 | bb_perror_msg_and_die("read from /dev/log"); | 565 | bb_perror_msg_and_die("read from /dev/log"); |
561 | } | ||
562 | 566 | ||
563 | /* Drop trailing NULs (typically there is one NUL) */ | 567 | /* Drop trailing '\n' and NULs (typically there is one NUL) */ |
564 | while (1) { | 568 | while (1) { |
565 | if (sz == 0) | 569 | if (sz == 0) |
566 | goto read_again; | 570 | goto read_again; |
567 | /* man 3 syslog says: "A trailing newline is added when needed". | 571 | /* man 3 syslog says: "A trailing newline is added when needed". |
568 | * However, neither glibc nor uclibc do this: | 572 | * However, neither glibc nor uclibc do this: |
569 | * syslog(prio, "test") sends "test\0" to /dev/log, | 573 | * syslog(prio, "test") sends "test\0" to /dev/log, |
570 | * syslog(prio, "test\n") sends "test\n\0", | 574 | * syslog(prio, "test\n") sends "test\n\0". |
571 | * IOW: newline is passed verbatim! | 575 | * IOW: newline is passed verbatim! |
572 | * I take it to mean that it's syslogd's job | 576 | * I take it to mean that it's syslogd's job |
573 | * to make those look identical in the log files */ | 577 | * to make those look identical in the log files. */ |
574 | if (G.recvbuf[sz-1] && G.recvbuf[sz-1] != '\n') | 578 | if (G.recvbuf[sz-1] != '\0' && G.recvbuf[sz-1] != '\n') |
575 | break; | 579 | break; |
576 | sz--; | 580 | sz--; |
577 | } | 581 | } |
578 | /* Maybe we need to add '\n' here, not later? | ||
579 | * It looks like stock syslogd does send '\n' over network, | ||
580 | * but we do not (see sendto below) */ | ||
581 | G.recvbuf[sz] = '\0'; /* make sure it *is* NUL terminated */ | ||
582 | |||
583 | /* TODO: maybe suppress duplicates? */ | 582 | /* TODO: maybe suppress duplicates? */ |
584 | #if ENABLE_FEATURE_REMOTE_LOG | 583 | #if ENABLE_FEATURE_REMOTE_LOG |
585 | /* We are not modifying log messages in any way before send */ | 584 | /* We are not modifying log messages in any way before send */ |
@@ -590,14 +589,21 @@ static void do_syslogd(void) | |||
590 | if (-1 == G.remoteFD) | 589 | if (-1 == G.remoteFD) |
591 | goto no_luck; | 590 | goto no_luck; |
592 | } | 591 | } |
592 | /* Stock syslogd sends it '\n'-terminated | ||
593 | * over network, mimic that */ | ||
594 | G.recvbuf[sz] = '\n'; | ||
593 | /* send message to remote logger, ignore possible error */ | 595 | /* send message to remote logger, ignore possible error */ |
594 | sendto(G.remoteFD, G.recvbuf, sz, MSG_DONTWAIT, | 596 | /* TODO: on some errors, close and set G.remoteFD to -1 |
597 | * so that DNS resolution and connect is retried? */ | ||
598 | sendto(G.remoteFD, G.recvbuf, sz+1, MSG_DONTWAIT, | ||
595 | &G.remoteAddr->u.sa, G.remoteAddr->len); | 599 | &G.remoteAddr->u.sa, G.remoteAddr->len); |
596 | no_luck: ; | 600 | no_luck: ; |
597 | } | 601 | } |
598 | #endif | 602 | #endif |
599 | if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) | 603 | if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) { |
604 | G.recvbuf[sz] = '\0'; /* ensure it *is* NUL terminated */ | ||
600 | split_escape_and_log(G.recvbuf, sz); | 605 | split_escape_and_log(G.recvbuf, sz); |
606 | } | ||
601 | } /* for (;;) */ | 607 | } /* for (;;) */ |
602 | } | 608 | } |
603 | 609 | ||