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
This commit is contained in:
Denis Vlasenko 2007-01-04 21:22:11 +00:00
parent b893497151
commit a0e2a0a192
3 changed files with 61 additions and 70 deletions

View File

@ -3021,7 +3021,7 @@
"\n -R HOST[:PORT] Log to IP or hostname on PORT (default PORT=514/UDP)" \ "\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( \ 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) */ /* NB: -Csize shouldn't have space (because size is optional) */
#define syslogd_example_usage \ #define syslogd_example_usage \
"$ syslogd -R masterlog:514\n" \ "$ syslogd -R masterlog:514\n" \

View File

@ -8,13 +8,6 @@
*/ */
#include "busybox.h" #include "busybox.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#if !defined CONFIG_SYSLOGD #if !defined CONFIG_SYSLOGD
@ -93,49 +86,40 @@ int logger_main(int argc, char **argv)
char *opt_p, *opt_t; char *opt_p, *opt_t;
int pri = LOG_USER | LOG_NOTICE; int pri = LOG_USER | LOG_NOTICE;
int option = 0; int option = 0;
int c, i; char name[80];
char buf[1024], name[128];
/* Fill out the name string early (may be overwritten later) */ /* Fill out the name string early (may be overwritten later) */
bb_getpwuid(name, geteuid(), sizeof(name)); bb_getpwuid(name, geteuid(), sizeof(name));
/* Parse any options */ /* Parse any options */
opt = getopt32(argc, argv, "p:st:", &opt_p, &opt_t); opt = getopt32(argc, argv, "p:st:", &opt_p, &opt_t);
argc -= optind;
argv += optind;
if (opt & 0x1) pri = pencode(opt_p); // -p if (opt & 0x1) pri = pencode(opt_p); // -p
if (opt & 0x2) option |= LOG_PERROR; // -s if (opt & 0x2) option |= LOG_PERROR; // -s
if (opt & 0x4) safe_strncpy(name, opt_t, sizeof(name)); // -t if (opt & 0x4) safe_strncpy(name, opt_t, sizeof(name)); // -t
openlog(name, option, 0); openlog(name, option, 0);
if (optind == argc) { if (!argc) {
do { while (fgets(bb_common_bufsiz1, BUFSIZ, stdin)) {
/* read from stdin */ if (bb_common_bufsiz1[0]
i = 0; && NOT_LONE_CHAR(bb_common_bufsiz1, '\n')
while ((c = getc(stdin)) != EOF && c != '\n' && ) {
i < (sizeof(buf)-1)) { /* Neither "" nor "\n" */
buf[i++] = c; syslog(pri, "%s", bb_common_bufsiz1);
} }
if (i > 0) {
buf[i++] = '\0';
syslog(pri, "%s", buf);
} }
} while (c != EOF);
} else { } else {
char *message = NULL; char *message = NULL;
int len = argc - optind; /* for the space between the args int len = 1; /* for NUL */
and '\0' */ int pos = 0;
opt = len; do {
argv += optind; len += strlen(*argv) + 1;
for (i = 0; i < opt; i++) {
len += strlen(*argv);
message = xrealloc(message, len); message = xrealloc(message, len);
if(!i) sprintf(message + pos, " %s", *argv),
message[0] = '\0'; pos = len;
else } while (*++argv);
strcat(message, " "); syslog(pri, "%s", message + 1); /* skip leading " " */
strcat(message, *argv);
argv++;
}
syslog(pri, "%s", message);
} }
closelog(); closelog();

View File

@ -56,13 +56,23 @@ static int remoteFD = -1;
static struct sockaddr_in remoteAddr; static struct sockaddr_in remoteAddr;
#endif #endif
/* We are using bb_common_bufsiz1 for buffering: */
/* NB: we may need 2x this amount on stack... */ enum { MAX_READ = (BUFSIZ/6) & ~0xf };
enum { MAX_READ = 1024 }; /* 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 */ /* Options */
/* Correct regardless of combination of CONFIG_xxx */
enum { enum {
OPTBIT_mark = 0, // -m OPTBIT_mark = 0, // -m
OPTBIT_nofork, // -n 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 void log_to_shmem(const char *msg, int len)
{ {
static /*const*/ struct sembuf SMwup[1] = { {1, -1, IPC_NOWAIT} }; /* Why libc insists on these being rw? */
static /*const*/ struct sembuf SMwdn[3] = { {0, 0}, {1, 0}, {1, +1} }; 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; int old_tail, new_tail;
char *c; 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 * 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) static void timestamp_and_log(int pri, char *msg, int len)
{ {
time_t now; 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 (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) {
if (LOG_PRI(pri) < logLevel) { if (LOG_PRI(pri) < logLevel) {
if (option_mask32 & OPT_small) if (option_mask32 & OPT_small)
msg = xasprintf("%s %s\n", timestamp, msg); sprintf(PRINTBUF, "%s %s\n", timestamp, msg);
else { else {
char res[20]; char res[20];
parse_fac_prio_20(pri, res); 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); log_locally(PRINTBUF);
free(msg);
} }
} }
} }
static void split_escape_and_log(char *tmpbuf, int len) static void split_escape_and_log(char *tmpbuf, int len)
{ {
char line[len * 2 + 1]; /* gcc' cheap alloca */
char *p = tmpbuf; char *p = tmpbuf;
tmpbuf += len; tmpbuf += len;
while (p < tmpbuf) { while (p < tmpbuf) {
char c; char c;
char *q = line; char *q = PARSEBUF;
int pri = (LOG_USER | LOG_NOTICE); int pri = (LOG_USER | LOG_NOTICE);
if (*p == '<') { if (*p == '<') {
/* Parse the magic priority number. */ /* Parse the magic priority number */
pri = bb_strtou(p + 1, &p, 10); pri = bb_strtou(p + 1, &p, 10);
if (*p == '>') p++; if (*p == '>') p++;
if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) { if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) {
@ -427,8 +436,8 @@ static void split_escape_and_log(char *tmpbuf, int len)
*q++ = c; *q++ = c;
} }
*q = '\0'; *q = '\0';
/* now log it */ /* Now log it */
timestamp_and_log(pri, line, q - line); timestamp_and_log(pri, PARSEBUF, q - PARSEBUF);
} }
} }
@ -509,11 +518,10 @@ static void do_syslogd(void)
if (FD_ISSET(sock_fd, &fds)) { if (FD_ISSET(sock_fd, &fds)) {
int i; int i;
#define tmpbuf bb_common_bufsiz1 i = recv(sock_fd, RECVBUF, MAX_READ - 1, 0);
i = recv(sock_fd, tmpbuf, MAX_READ, 0);
if (i <= 0) if (i <= 0)
bb_perror_msg_and_die("UNIX socket error"); bb_perror_msg_and_die("UNIX socket error");
/* TODO: maybe supress duplicates? */ /* TODO: maybe suppress duplicates? */
#if ENABLE_FEATURE_REMOTE_LOG #if ENABLE_FEATURE_REMOTE_LOG
/* We are not modifying log messages in any way before send */ /* We are not modifying log messages in any way before send */
/* Remote site cannot trust _us_ anyway and need to do validation again */ /* Remote site cannot trust _us_ anyway and need to do validation again */
@ -523,15 +531,14 @@ static void do_syslogd(void)
} }
if (-1 != remoteFD) { if (-1 != remoteFD) {
/* send message to remote logger, ignore possible error */ /* send message to remote logger, ignore possible error */
sendto(remoteFD, tmpbuf, i, MSG_DONTWAIT, sendto(remoteFD, RECVBUF, i, MSG_DONTWAIT,
(struct sockaddr *) &remoteAddr, (struct sockaddr *) &remoteAddr,
sizeof(remoteAddr)); sizeof(remoteAddr));
} }
} }
#endif #endif
tmpbuf[i] = '\0'; RECVBUF[i] = '\0';
split_escape_and_log(tmpbuf, i); split_escape_and_log(RECVBUF, i);
#undef tmpbuf
} /* FD_ISSET() */ } /* FD_ISSET() */
} /* for */ } /* for */
} }