aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-01-04 21:22:11 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-01-04 21:22:11 +0000
commita0e2a0a19272268fc042f159e74f1573a10202cd (patch)
treed274d7a270bdb5347bbb462c65473f2997f6fb40
parentb8934971516d69086cf693a1a51acf649930ee64 (diff)
downloadbusybox-a0e2a0a19272268fc042f159e74f1573a10202cd.tar.gz
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
-rw-r--r--include/usage.h18
-rw-r--r--sysklogd/logger.c54
-rw-r--r--sysklogd/syslogd.c63
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 <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
@@ -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 */
}