From a0e2a0a19272268fc042f159e74f1573a10202cd Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Thu, 4 Jan 2007 21:22:11 +0000 Subject: [PATCH] syslogd: start using bb_common_bufsiz1 instead of stack/malloc logger: optimize, also use bb_common_bufsiz1 (~40 bytes) tested to eat arbitrarily-sized input at high speed - ok --- include/usage.h | 18 ++++++------- sysklogd/logger.c | 54 ++++++++++++++------------------------- sysklogd/syslogd.c | 63 +++++++++++++++++++++++++--------------------- 3 files changed, 63 insertions(+), 72 deletions(-) diff --git a/include/usage.h b/include/usage.h index 6202c4afd..ae03d5431 100644 --- a/include/usage.h +++ b/include/usage.h @@ -3009,19 +3009,19 @@ "System logging utility.\n" \ "Note that this version of syslogd ignores /etc/syslog.conf." \ "\n\nOptions:" \ - "\n -m MIN Minutes between MARK lines (default=20, 0=off)" \ - "\n -n Run as a foreground process" \ - "\n -O FILE Use an alternate log file (default=/var/log/messages)" \ - "\n -l n Sets the local log level of messages to n" \ - "\n -S Make logging output smaller" \ + "\n -m MIN Minutes between MARK lines (default=20, 0=off)" \ + "\n -n Run as a foreground process" \ + "\n -O FILE Use an alternate log file (default=/var/log/messages)" \ + "\n -l n Sets the local log level of messages to n" \ + "\n -S Make logging output smaller" \ USE_FEATURE_ROTATE_LOGFILE( \ - "\n -s SIZE Max size (KB) before rotate (default=200KB, 0=off)" \ - "\n -b NUM Number of rotated logs to keep (default=1, max=99, 0=purge)") \ + "\n -s SIZE Max size (KB) before rotate (default=200KB, 0=off)" \ + "\n -b NUM Number of rotated logs to keep (default=1, max=99, 0=purge)") \ USE_FEATURE_REMOTE_LOG( \ "\n -R HOST[:PORT] Log to IP or hostname on PORT (default PORT=514/UDP)" \ - "\n -L Log locally and via network logging (default is network only)") \ + "\n -L Log locally and via network logging (default is network only)") \ USE_FEATURE_IPC_SYSLOG( \ - "\n -C[size(KiB)] Log to a circular buffer (read the buffer using logread)") + "\n -C[size(KiB)] Log to a shared mem buffer (read the buffer using logread)") /* NB: -Csize shouldn't have space (because size is optional) */ #define syslogd_example_usage \ "$ syslogd -R masterlog:514\n" \ diff --git a/sysklogd/logger.c b/sysklogd/logger.c index 8901bd79f..3a4f51575 100644 --- a/sysklogd/logger.c +++ b/sysklogd/logger.c @@ -8,13 +8,6 @@ */ #include "busybox.h" -#include -#include -#include -#include -#include -#include -#include #if !defined CONFIG_SYSLOGD @@ -93,49 +86,40 @@ int logger_main(int argc, char **argv) char *opt_p, *opt_t; int pri = LOG_USER | LOG_NOTICE; int option = 0; - int c, i; - char buf[1024], name[128]; + char name[80]; /* Fill out the name string early (may be overwritten later) */ bb_getpwuid(name, geteuid(), sizeof(name)); /* Parse any options */ opt = getopt32(argc, argv, "p:st:", &opt_p, &opt_t); + argc -= optind; + argv += optind; if (opt & 0x1) pri = pencode(opt_p); // -p if (opt & 0x2) option |= LOG_PERROR; // -s if (opt & 0x4) safe_strncpy(name, opt_t, sizeof(name)); // -t openlog(name, option, 0); - if (optind == argc) { - do { - /* read from stdin */ - i = 0; - while ((c = getc(stdin)) != EOF && c != '\n' && - i < (sizeof(buf)-1)) { - buf[i++] = c; - } - if (i > 0) { - buf[i++] = '\0'; - syslog(pri, "%s", buf); + if (!argc) { + while (fgets(bb_common_bufsiz1, BUFSIZ, stdin)) { + if (bb_common_bufsiz1[0] + && NOT_LONE_CHAR(bb_common_bufsiz1, '\n') + ) { + /* Neither "" nor "\n" */ + syslog(pri, "%s", bb_common_bufsiz1); } - } while (c != EOF); + } } else { char *message = NULL; - int len = argc - optind; /* for the space between the args - and '\0' */ - opt = len; - argv += optind; - for (i = 0; i < opt; i++) { - len += strlen(*argv); + int len = 1; /* for NUL */ + int pos = 0; + do { + len += strlen(*argv) + 1; message = xrealloc(message, len); - if(!i) - message[0] = '\0'; - else - strcat(message, " "); - strcat(message, *argv); - argv++; - } - syslog(pri, "%s", message); + sprintf(message + pos, " %s", *argv), + pos = len; + } while (*++argv); + syslog(pri, "%s", message + 1); /* skip leading " " */ } closelog(); diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 7edce7a0a..fbb85338a 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -56,13 +56,23 @@ static int remoteFD = -1; static struct sockaddr_in remoteAddr; #endif - -/* NB: we may need 2x this amount on stack... */ -enum { MAX_READ = 1024 }; - - -/* options */ -/* Correct regardless of combination of CONFIG_xxx */ +/* We are using bb_common_bufsiz1 for buffering: */ +enum { MAX_READ = (BUFSIZ/6) & ~0xf }; +/* We recv into this... (size: MAX_READ ~== BUFSIZ/6) */ +#define RECVBUF bb_common_bufsiz1 +/* ...then copy here, escaping control chars */ +/* (can grow x2 + 1 max ~== BUFSIZ/3) */ +#define PARSEBUF (bb_common_bufsiz1 + MAX_READ) +/* ...then sprintf into this, adding timestamp (15 chars), + * host (64), fac.prio (20) to the message */ +/* (growth by: 15 + 64 + 20 + delims = ~110) */ +#define PRINTBUF (bb_common_bufsiz1 + 3*MAX_READ + 0x10) +/* totals: BUFSIZ/6 + BUFSIZ/3 + BUFSIZ/3 = BUFSIZ - BUFSIZ/6 + * -- we have BUFSIZ/6 extra at the ent of PRINTBUF + * which covers needed ~110 extra bytes (and much more) */ + + +/* Options */ enum { OPTBIT_mark = 0, // -m OPTBIT_nofork, // -n @@ -175,11 +185,12 @@ static void ipcsyslog_init(void) } } -/* write message to buffer */ +/* Write message to shared mem buffer */ static void log_to_shmem(const char *msg, int len) { - static /*const*/ struct sembuf SMwup[1] = { {1, -1, IPC_NOWAIT} }; - static /*const*/ struct sembuf SMwdn[3] = { {0, 0}, {1, 0}, {1, +1} }; + /* Why libc insists on these being rw? */ + static struct sembuf SMwup[1] = { {1, -1, IPC_NOWAIT} }; + static struct sembuf SMwdn[3] = { {0, 0}, {1, 0}, {1, +1} }; int old_tail, new_tail; char *c; @@ -362,9 +373,9 @@ static void parse_fac_prio_20(int pri, char *res20) } } -/* len parameter is used only for "is there a timestamp?" check +/* len parameter is used only for "is there a timestamp?" check. * NB: some callers cheat and supply 0 when they know - * that there is no timestamp, short-cutting the test */ + * that there is no timestamp, short-cutting the test. */ static void timestamp_and_log(int pri, char *msg, int len) { time_t now; @@ -385,31 +396,29 @@ static void timestamp_and_log(int pri, char *msg, int len) if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) { if (LOG_PRI(pri) < logLevel) { if (option_mask32 & OPT_small) - msg = xasprintf("%s %s\n", timestamp, msg); + sprintf(PRINTBUF, "%s %s\n", timestamp, msg); else { char res[20]; parse_fac_prio_20(pri, res); - msg = xasprintf("%s %s %s %s\n", timestamp, localHostName, res, msg); + sprintf(PRINTBUF, "%s %s %s %s\n", timestamp, localHostName, res, msg); } - log_locally(msg); - free(msg); + log_locally(PRINTBUF); } } } static void split_escape_and_log(char *tmpbuf, int len) { - char line[len * 2 + 1]; /* gcc' cheap alloca */ char *p = tmpbuf; tmpbuf += len; while (p < tmpbuf) { char c; - char *q = line; + char *q = PARSEBUF; int pri = (LOG_USER | LOG_NOTICE); if (*p == '<') { - /* Parse the magic priority number. */ + /* Parse the magic priority number */ pri = bb_strtou(p + 1, &p, 10); if (*p == '>') p++; if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) { @@ -427,8 +436,8 @@ static void split_escape_and_log(char *tmpbuf, int len) *q++ = c; } *q = '\0'; - /* now log it */ - timestamp_and_log(pri, line, q - line); + /* Now log it */ + timestamp_and_log(pri, PARSEBUF, q - PARSEBUF); } } @@ -509,11 +518,10 @@ static void do_syslogd(void) if (FD_ISSET(sock_fd, &fds)) { int i; -#define tmpbuf bb_common_bufsiz1 - i = recv(sock_fd, tmpbuf, MAX_READ, 0); + i = recv(sock_fd, RECVBUF, MAX_READ - 1, 0); if (i <= 0) bb_perror_msg_and_die("UNIX socket error"); - /* TODO: maybe supress duplicates? */ + /* TODO: maybe suppress duplicates? */ #if ENABLE_FEATURE_REMOTE_LOG /* We are not modifying log messages in any way before send */ /* Remote site cannot trust _us_ anyway and need to do validation again */ @@ -523,15 +531,14 @@ static void do_syslogd(void) } if (-1 != remoteFD) { /* send message to remote logger, ignore possible error */ - sendto(remoteFD, tmpbuf, i, MSG_DONTWAIT, + sendto(remoteFD, RECVBUF, i, MSG_DONTWAIT, (struct sockaddr *) &remoteAddr, sizeof(remoteAddr)); } } #endif - tmpbuf[i] = '\0'; - split_escape_and_log(tmpbuf, i); -#undef tmpbuf + RECVBUF[i] = '\0'; + split_escape_and_log(RECVBUF, i); } /* FD_ISSET() */ } /* for */ } -- 2.25.1