From ceab8700dfa0a4f987c9872e12e57cfba6ddb95c Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Thu, 4 Jan 2007 17:57:54 +0000 Subject: [PATCH] syslogd: almost rewritten. Had several obvious bugs... --- sysklogd/syslogd.c | 590 ++++++++++++++++++++------------------------- 1 file changed, 263 insertions(+), 327 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 453cbda35..9e4bc63c2 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -15,7 +15,6 @@ #include "busybox.h" #include -#include #include /* SYSLOG_NAMES defined to pull some extra junk from syslog.h */ @@ -24,36 +23,39 @@ #include /* Path to the unix socket */ -static char lfile[MAXPATHLEN]; +static char dev_log_name[MAXPATHLEN]; /* Path for the file where all log messages are written */ static const char *logFilePath = "/var/log/messages"; -#ifdef CONFIG_FEATURE_ROTATE_LOGFILE +#if ENABLE_FEATURE_ROTATE_LOGFILE /* max size of message file before being rotated */ static int logFileSize = 200 * 1024; - /* number of rotated message files */ static int logFileRotate = 1; #endif /* interval between marks in seconds */ -static int MarkInterval = 20 * 60; +static int markInterval = 20 * 60; /* level of messages to be locally logged */ static int logLevel = 8; /* localhost's name */ -static char LocalHostName[64]; +static char localHostName[64]; -#ifdef CONFIG_FEATURE_REMOTE_LOG +#if ENABLE_FEATURE_REMOTE_LOG #include /* udp socket for logging to remote host */ -static int remotefd = -1; -static struct sockaddr_in remoteaddr; - +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 */ enum { @@ -96,10 +98,10 @@ enum { USE_FEATURE_REMOTE_LOG( ,&opt_R) \ USE_FEATURE_IPC_SYSLOG( ,&opt_C) -#define MAXLINE 1024 /* maximum line length */ /* circular buffer variables/structures */ -#ifdef CONFIG_FEATURE_IPC_SYSLOG +#if ENABLE_FEATURE_IPC_SYSLOG + #if CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE < 4 #error Sorry, you must set the syslogd buffer size to at least 4KB. @@ -115,14 +117,11 @@ enum { // Semaphore operation structures static struct shbuf_ds { - int size; // size of data written - int head; // start of message list - int tail; // end of message list + int32_t size; // size of data written + int32_t head; // start of message list + int32_t tail; // end of message list char data[1]; // data/messages -} *shbuf = NULL; // shared memory pointer - -static struct sembuf SMwup[1] = { {1, -1, IPC_NOWAIT} }; // set SMwup -static struct sembuf SMwdn[3] = { {0, 0}, {1, 0}, {1, +1} }; // set SMwdn +} *shbuf; // shared memory pointer static int shmid = -1; // ipc shared memory id static int s_semid = -1; // ipc semaphore id @@ -130,11 +129,9 @@ static int shm_size = ((CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE)*1024); // default static void ipcsyslog_cleanup(void) { - puts("Exiting syslogd!"); if (shmid != -1) { shmdt(shbuf); } - if (shmid != -1) { shmctl(shmid, IPC_RMID, NULL); } @@ -145,359 +142,299 @@ static void ipcsyslog_cleanup(void) static void ipcsyslog_init(void) { - if (shbuf == NULL) { - shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023); - if (shmid == -1) { - bb_perror_msg_and_die("shmget"); - } + shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023); + if (shmid == -1) { + bb_perror_msg_and_die("shmget"); + } - shbuf = shmat(shmid, NULL, 0); - if (!shbuf) { - bb_perror_msg_and_die("shmat"); - } + shbuf = shmat(shmid, NULL, 0); + if (!shbuf) { + bb_perror_msg_and_die("shmat"); + } - shbuf->size = shm_size - sizeof(*shbuf); - shbuf->head = shbuf->tail = 0; + shbuf->size = shm_size - offsetof(struct shbuf_ds, data); + shbuf->head = shbuf->tail = 0; - // we'll trust the OS to set initial semval to 0 (let's hope) - s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023); - if (s_semid == -1) { - if (errno == EEXIST) { - s_semid = semget(KEY_ID, 2, 0); - if (s_semid == -1) { - bb_perror_msg_and_die("semget"); - } - } else { - bb_perror_msg_and_die("semget"); - } + // we'll trust the OS to set initial semval to 0 (let's hope) + s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023); + if (s_semid == -1) { + if (errno == EEXIST) { + s_semid = semget(KEY_ID, 2, 0); + if (s_semid != -1) + return; } - } else { - printf("Buffer already allocated just grab the semaphore?"); + bb_perror_msg_and_die("semget"); } } /* write message to buffer */ -static void circ_message(const char *msg) +static void log_to_shmem(const char *msg, int len) { - int l = strlen(msg) + 1; /* count the whole message w/ '\0' included */ - const char * const fail_msg = "Can't find the terminator token%s?\n"; + static /*const*/ struct sembuf SMwup[1] = { {1, -1, IPC_NOWAIT} }; + static /*const*/ struct sembuf SMwdn[3] = { {0, 0}, {1, 0}, {1, +1} }; + + int old_tail, new_tail; + char *c; if (semop(s_semid, SMwdn, 3) == -1) { bb_perror_msg_and_die("SMwdn"); } - /* - * Circular Buffer Algorithm: + /* Circular Buffer Algorithm: * -------------------------- - * - * Start-off w/ empty buffer of specific size SHM_SIZ - * Start filling it up w/ messages. I use '\0' as separator to break up messages. - * This is also very handy since we can do printf on message. - * - * Once the buffer is full we need to get rid of the first message in buffer and - * insert the new message. (Note: if the message being added is >1 message then - * we will need to "remove" >1 old message from the buffer). The way this is done - * is the following: - * When we reach the end of the buffer we set a mark and start from the beginning. - * Now what about the beginning and end of the buffer? Well we have the "head" - * index/pointer which is the starting point for the messages and we have "tail" - * index/pointer which is the ending point for the messages. When we "display" the - * messages we start from the beginning and continue until we reach "tail". If we - * reach end of buffer, then we just start from the beginning (offset 0). "head" and - * "tail" are actually offsets from the beginning of the buffer. - * - * Note: This algorithm uses Linux IPC mechanism w/ shared memory and semaphores to provide - * a threadsafe way of handling shared memory operations. + * tail == position where to store next syslog message. + * head == position of next message to retrieve ("print"). + * if head == tail, there is no "unprinted" messages left. + * head is typically advanced by separate "reader" program, + * but if there isn't one, we have to do it ourself. + * messages are NUL-separated. */ - if ((shbuf->tail + l) < shbuf->size) { - /* before we append the message we need to check the HEAD so that we won't - overwrite any of the message that we still need and adjust HEAD to point - to the next message! */ - if (shbuf->tail < shbuf->head) { - if ((shbuf->tail + l) >= shbuf->head) { - /* we need to move the HEAD to point to the next message - * Theoretically we have enough room to add the whole message to the - * buffer, because of the first outer IF statement, so we don't have - * to worry about overflows here! - */ - /* we need to know how many bytes we are overwriting to make enough room */ - int k = shbuf->tail + l - shbuf->head; - char *c = - memchr(shbuf->data + shbuf->head + k, '\0', - shbuf->size - (shbuf->head + k)); - if (c != NULL) { /* do a sanity check just in case! */ - /* we need to convert pointer to offset + skip the '\0' - since we need to point to the beginning of the next message */ - shbuf->head = c - shbuf->data + 1; - /* Note: HEAD is only used to "retrieve" messages, it's not used - when writing messages into our buffer */ - } else { /* show an error message to know we messed up? */ - printf(fail_msg,""); - shbuf->head = 0; - } + len++; /* length with NUL included */ + again: + old_tail = shbuf->tail; + new_tail = old_tail + len; + if (new_tail < shbuf->size) { + /* No need to move head if shbuf->head <= old_tail, + * else... */ + if (old_tail < shbuf->head && shbuf->head <= new_tail) { + /* ...need to move head forward */ + c = memchr(shbuf->data + new_tail, '\0', + shbuf->size - new_tail); + if (!c) /* no NUL ahead of us, wrap around */ + c = memchr(shbuf->data, '\0', old_tail); + if (!c) { /* still nothing? point to this msg... */ + shbuf->head = old_tail; + } else { + /* convert pointer to offset + skip NUL */ + shbuf->head = c - shbuf->data + 1; } } - - /* in other cases no overflows have been done yet, so we don't care! */ - /* we should be ok to append the message now */ - strncpy(shbuf->data + shbuf->tail, msg, l); /* append our message */ - shbuf->tail += l; /* count full message w/ '\0' terminating char */ + /* store message, set new tail */ + memcpy(shbuf->data + old_tail, msg, len); + shbuf->tail = new_tail; } else { - /* we need to break up the message and "circle" it around */ - char *c; - int k = shbuf->tail + l - shbuf->size; /* count # of bytes we don't fit */ - - /* We need to move HEAD! This is always the case since we are going - * to "circle" the message. */ - c = memchr(shbuf->data + k, '\0', shbuf->size - k); - - if (c != NULL) { /* if we don't have '\0'??? weird!!! */ - /* move head pointer */ - shbuf->head = c - shbuf->data + 1; - - /* now write the first part of the message */ - strncpy(shbuf->data + shbuf->tail, msg, l - k - 1); - - /* ALWAYS terminate end of buffer w/ '\0' */ - shbuf->data[shbuf->size - 1] = '\0'; - - /* now write out the rest of the string to the beginning of the buffer */ - strcpy(shbuf->data, &msg[l - k - 1]); - - /* we need to place the TAIL at the end of the message */ - shbuf->tail = k + 1; - } else { - printf(fail_msg, " from the beginning"); - shbuf->head = shbuf->tail = 0; /* reset buffer, since it's probably corrupted */ + /* we need to break up the message and wrap it around */ + /* k == available buffer space ahead of old tail */ + int k = shbuf->size - old_tail - 1; + if (shbuf->head > old_tail) { + /* we are going to overwrite head, need to + * move it out of the way */ + c = memchr(shbuf->data, '\0', old_tail); + if (!c) { /* nothing? point to this msg... */ + shbuf->head = old_tail; + } else { /* convert pointer to offset + skip NUL */ + shbuf->head = c - shbuf->data + 1; + } } - + /* copy what fits to the end of buffer, and repeat */ + memcpy(shbuf->data + old_tail, msg, k); + msg += k; + len -= k; + shbuf->tail = 0; + goto again; } if (semop(s_semid, SMwup, 1) == -1) { bb_perror_msg_and_die("SMwup"); } - } #else void ipcsyslog_cleanup(void); void ipcsyslog_init(void); -void circ_message(const char *msg); -#endif /* CONFIG_FEATURE_IPC_SYSLOG */ +void log_to_shmem(const char *msg); + + +#endif /* FEATURE_IPC_SYSLOG */ + -/* Note: There is also a function called "message()" in init.c */ /* Print a message to the log file. */ -static void message(char *fmt, ...) __attribute__ ((format(printf, 1, 2))); -static void message(char *fmt, ...) +static void log_locally(char *msg) { - int fd = -1; - struct flock fl; - va_list arguments; + int fd, len = strlen(msg); - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 1; - -#ifdef CONFIG_FEATURE_IPC_SYSLOG +#if ENABLE_FEATURE_IPC_SYSLOG if ((option_mask32 & OPT_circularlog) && shbuf) { - char b[1024]; - - va_start(arguments, fmt); - vsnprintf(b, sizeof(b) - 1, fmt, arguments); - va_end(arguments); - circ_message(b); - - } else + log_to_shmem(msg, len); + return; + } #endif + + again: fd = device_open(logFilePath, O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND | O_NONBLOCK); if (fd >= 0) { + struct flock fl; + + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 1; fl.l_type = F_WRLCK; fcntl(fd, F_SETLKW, &fl); -#ifdef CONFIG_FEATURE_ROTATE_LOGFILE - if (ENABLE_FEATURE_ROTATE_LOGFILE && logFileSize > 0 ) { +#if ENABLE_FEATURE_ROTATE_LOGFILE + if (logFileSize) { struct stat statf; int r = fstat(fd, &statf); if (!r && (statf.st_mode & S_IFREG) - && (lseek(fd,0,SEEK_END) > logFileSize)) { - if (logFileRotate > 0) { - int i = strlen(logFilePath) + 4; + && (lseek(fd, 0, SEEK_END) > logFileSize) + ) { + if (logFileRotate) { /* always 0..99 */ + int i = strlen(logFilePath) + 3 + 1; char oldFile[i]; char newFile[i]; - for (i=logFileRotate-1; i>0; i--) { - sprintf(oldFile, "%s.%d", logFilePath, i-1); + i = logFileRotate - 1; + /* rename: f.8 -> f.9; f.7 -> f.8; ... */ + while (1) { sprintf(newFile, "%s.%d", logFilePath, i); + if (i == 0) break; + sprintf(oldFile, "%s.%d", logFilePath, --i); rename(oldFile, newFile); } - sprintf(newFile, "%s.%d", logFilePath, 0); + /* newFile == "f.0" now */ + rename(logFilePath, newFile); fl.l_type = F_UNLCK; fcntl(fd, F_SETLKW, &fl); close(fd); - rename(logFilePath, newFile); - fd = device_open(logFilePath, - O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND | - O_NONBLOCK); - fl.l_type = F_WRLCK; - fcntl(fd, F_SETLKW, &fl); - } else { - ftruncate(fd, 0); + goto again; } + ftruncate(fd, 0); } } #endif - va_start(arguments, fmt); - vdprintf(fd, fmt, arguments); - va_end(arguments); + full_write(fd, msg, len); fl.l_type = F_UNLCK; fcntl(fd, F_SETLKW, &fl); close(fd); } else { - /* Always send console messages to /dev/console so people will see them. */ + /* cannot open logfile? - print to /dev/console then */ fd = device_open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK); - if (fd >= 0) { - va_start(arguments, fmt); - vdprintf(fd, fmt, arguments); - va_end(arguments); + if (fd < 0) + fd = 2; /* then stderr, dammit */ + full_write(fd, msg, len); + if (fd != 2) close(fd); - } else { - fprintf(stderr, "Bummer, can't print: "); - va_start(arguments, fmt); - vfprintf(stderr, fmt, arguments); - fflush(stderr); - va_end(arguments); - } } } -static void logMessage(int pri, char *msg) +static void parse_fac_prio_20(int pri, char *res20) { - time_t now; - char *timestamp; - char res[20]; CODE *c_pri, *c_fac; if (pri != 0) { c_fac = facilitynames; - while (c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3)) - c_fac++; - c_pri = prioritynames; - while (c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri))) - c_pri++; - if (c_fac->c_name == NULL || c_pri->c_name == NULL) { - snprintf(res, sizeof(res), "<%d>", pri); - } else { - snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name); + while (c_fac->c_name) { + if (c_fac->c_val != (LOG_FAC(pri) << 3)) { + c_fac++; continue; + } + /* facility is found, look for prio */ + c_pri = prioritynames; + while (c_pri->c_name) { + if (c_pri->c_val != LOG_PRI(pri)) { + c_pri++; continue; + } + snprintf(res20, 20, "%s.%s", + c_fac->c_name, c_pri->c_name); + return; + } + /* prio not found, bail out */ + break; } + snprintf(res20, 20, "<%d>", pri); } +} - if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' || - msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') { +/* 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 */ +static void timestamp_and_log(int pri, char *msg, int len) +{ + time_t now; + char *timestamp; + + if (len < 16 || msg[3] != ' ' || msg[6] != ' ' + || msg[9] != ':' || msg[12] != ':' || msg[15] != ' ' + ) { time(&now); timestamp = ctime(&now) + 4; - timestamp[15] = '\0'; } else { timestamp = msg; - timestamp[15] = '\0'; msg += 16; } + timestamp[15] = '\0'; - /* todo: supress duplicates */ - -#ifdef CONFIG_FEATURE_REMOTE_LOG - if (option_mask32 & OPT_remotelog) { - char line[MAXLINE + 1]; - /* trying connect the socket */ - if (-1 == remotefd) { - remotefd = socket(AF_INET, SOCK_DGRAM, 0); - } - /* if we have a valid socket, send the message */ - if (-1 != remotefd) { - snprintf(line, sizeof(line), "<%d>%s", pri, msg); - /* send message to remote logger, ignore possible error */ - sendto(remotefd, line, strlen(line), 0, - (struct sockaddr *) &remoteaddr, sizeof(remoteaddr)); + /* Log message locally (to file or shared mem) */ + 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); + else { + char res[20]; + parse_fac_prio_20(pri, res); + msg = xasprintf("%s %s %s %s\n", timestamp, localHostName, res, msg); + } + log_locally(msg); + free(msg); } } +} - if (option_mask32 & OPT_locallog) -#endif - { - /* now spew out the message to wherever it is supposed to go */ - if (pri == 0 || LOG_PRI(pri) < logLevel) { - if (option_mask32 & OPT_small) - message("%s %s\n", timestamp, msg); - else - message("%s %s %s %s\n", timestamp, LocalHostName, res, msg); +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; + int pri = (LOG_USER | LOG_NOTICE); + + if (*p == '<') { + /* Parse the magic priority number. */ + pri = bb_strtou(p + 1, &p, 10); + if (*p == '>') p++; + if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) { + pri = (LOG_USER | LOG_NOTICE); + } } + + while ((c = *p++)) { + if (c == '\n') + c = ' '; + if (!(c & ~0x1f)) { + *q++ = '^'; + c += '@'; /* ^@, ^A, ^B... */ + } + *q++ = c; + } + *q = '\0'; + /* now log it */ + timestamp_and_log(pri, line, q - line); } } static void quit_signal(int sig) { - logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting."); - unlink(lfile); + timestamp_and_log(LOG_SYSLOG | LOG_INFO, "System log daemon exiting", 0); + puts("System log daemon exiting"); + unlink(dev_log_name); if (ENABLE_FEATURE_IPC_SYSLOG) ipcsyslog_cleanup(); - exit(1); } -static void domark(int sig) +static void do_mark(int sig) { - if (MarkInterval > 0) { - logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --"); - alarm(MarkInterval); + if (markInterval) { + timestamp_and_log(LOG_SYSLOG | LOG_INFO, "-- MARK --", 0); + alarm(markInterval); } } -/* This must be a #define, since when CONFIG_DEBUG and BUFFERS_GO_IN_BSS are - * enabled, we otherwise get a "storage size isn't constant error. */ -static int serveConnection(char *tmpbuf, int n_read) -{ - char *p = tmpbuf; - - while (p < tmpbuf + n_read) { - - int pri = (LOG_USER | LOG_NOTICE); - int num_lt = 0; - char line[MAXLINE + 1]; - unsigned char c; - char *q = line; - - while ((c = *p) && q < &line[sizeof(line) - 1]) { - if (c == '<' && num_lt == 0) { - /* Parse the magic priority number. */ - num_lt++; - pri = 0; - while (isdigit(*++p)) { - pri = 10 * pri + (*p - '0'); - } - if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) { - pri = (LOG_USER | LOG_NOTICE); - } - } else if (c == '\n') { - *q++ = ' '; - } else if (iscntrl(c) && (c < 0177)) { - *q++ = '^'; - *q++ = c ^ 0100; - } else { - *q++ = c; - } - p++; - } - *q = '\0'; - p++; - /* Now log it */ - logMessage(pri, line); - } - return n_read; -} - -static void doSyslogd(void) ATTRIBUTE_NORETURN; -static void doSyslogd(void) +static void do_syslogd(void) ATTRIBUTE_NORETURN; +static void do_syslogd(void) { struct sockaddr_un sunx; socklen_t addrLength; - int sock_fd; fd_set fds; @@ -510,31 +447,31 @@ static void doSyslogd(void) #ifdef SIGCLD signal(SIGCLD, SIG_IGN); #endif - signal(SIGALRM, domark); - alarm(MarkInterval); + signal(SIGALRM, do_mark); + alarm(markInterval); - /* Create the syslog file so realpath() can work. */ - if (realpath(_PATH_LOG, lfile) != NULL) { - unlink(lfile); + /* Unlink old /dev/log (or object it points to) */ + if (realpath(_PATH_LOG, dev_log_name) != NULL) { + unlink(dev_log_name); } memset(&sunx, 0, sizeof(sunx)); sunx.sun_family = AF_UNIX; - strncpy(sunx.sun_path, lfile, sizeof(sunx.sun_path)); + strncpy(sunx.sun_path, dev_log_name, sizeof(sunx.sun_path)); sock_fd = xsocket(AF_UNIX, SOCK_DGRAM, 0); addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path); if (bind(sock_fd, (struct sockaddr *) &sunx, addrLength) < 0) { - bb_perror_msg_and_die("cannot connect to socket %s", lfile); + bb_perror_msg_and_die("cannot connect to socket %s", dev_log_name); } - if (chmod(lfile, 0666) < 0) { - bb_perror_msg_and_die("cannot set permission on %s", lfile); + if (chmod(dev_log_name, 0666) < 0) { + bb_perror_msg_and_die("cannot set permission on %s", dev_log_name); } if (ENABLE_FEATURE_IPC_SYSLOG && (option_mask32 & OPT_circularlog)) { ipcsyslog_init(); } - logMessage(LOG_SYSLOG | LOG_INFO, "syslogd started: " "BusyBox v" BB_VER ); + timestamp_and_log(LOG_SYSLOG | LOG_INFO, "syslogd started: BusyBox v" BB_VER, 0); for (;;) { FD_ZERO(&fds); @@ -550,24 +487,33 @@ static void doSyslogd(void) if (FD_ISSET(sock_fd, &fds)) { int i; -#if MAXLINE > BUFSIZ -# define TMP_BUF_SZ BUFSIZ -#else -# define TMP_BUF_SZ MAXLINE -#endif #define tmpbuf bb_common_bufsiz1 - - if ((i = recv(sock_fd, tmpbuf, TMP_BUF_SZ, 0)) > 0) { - tmpbuf[i] = '\0'; - serveConnection(tmpbuf, i); - } else { + i = recv(sock_fd, tmpbuf, MAX_READ, 0); + if (i <= 0) bb_perror_msg_and_die("UNIX socket error"); + /* TODO: maybe supress 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 */ + if (option_mask32 & OPT_remotelog) { + if (-1 == remoteFD) { + remoteFD = socket(AF_INET, SOCK_DGRAM, 0); + } + if (-1 != remoteFD) { + /* send message to remote logger, ignore possible error */ + sendto(remoteFD, tmpbuf, i, MSG_DONTWAIT, + (struct sockaddr *) &remoteAddr, + sizeof(remoteAddr)); + } } - } /* FD_ISSET() */ - } /* for main loop */ +#endif + tmpbuf[i] = '\0'; + split_escape_and_log(tmpbuf, i); +#undef tmpbuf + } /* FD_ISSET() */ + } /* for */ } - int syslogd_main(int argc, char **argv) { char OPTION_DECL; @@ -575,46 +521,37 @@ int syslogd_main(int argc, char **argv) /* do normal option parsing */ getopt32(argc, argv, OPTION_STR, OPTION_PARAM); - if (option_mask32 & OPT_mark) MarkInterval = xatoul_range(opt_m, 0, INT_MAX/60) * 60; // -m + if (option_mask32 & OPT_mark) // -m + markInterval = xatou_range(opt_m, 0, INT_MAX/60) * 60; //if (option_mask32 & OPT_nofork) // -n //if (option_mask32 & OPT_outfile) // -O - if (option_mask32 & OPT_loglevel) { // -l - logLevel = xatoi_u(opt_l); - /* Valid levels are between 1 and 8 */ - if (logLevel < 1 || logLevel > 8) - bb_show_usage(); - } + if (option_mask32 & OPT_loglevel) // -l + logLevel = xatou_range(opt_l, 1, 8); //if (option_mask32 & OPT_small) // -S #if ENABLE_FEATURE_ROTATE_LOGFILE - if (option_mask32 & OPT_filesize) logFileSize = xatoul_range(opt_s, 0, INT_MAX/1024) * 1024; // -s - if (option_mask32 & OPT_rotatecnt) { // -b - logFileRotate = xatoi_u(opt_b); - if (logFileRotate > 99) logFileRotate = 99; - } + if (option_mask32 & OPT_filesize) // -s + logFileSize = xatou_range(opt_s, 0, INT_MAX/1024) * 1024; + if (option_mask32 & OPT_rotatecnt) // -b + logFileRotate = xatou_range(opt_b, 0, 99); #endif #if ENABLE_FEATURE_REMOTE_LOG if (option_mask32 & OPT_remotelog) { // -R int port = 514; - char *host = xstrdup(opt_R); - p = strchr(host, ':'); + p = strchr(opt_R, ':'); if (p) { - port = xatou16(p + 1); - *p = '\0'; + *p++ = '\0'; + port = xatou16(p); } - remoteaddr.sin_family = AF_INET; + remoteAddr.sin_family = AF_INET; /* FIXME: looks ip4-specific. need to do better */ - remoteaddr.sin_addr = *(struct in_addr *) *(xgethostbyname(host)->h_addr_list); - remoteaddr.sin_port = htons(port); - free(host); + remoteAddr.sin_addr = *(struct in_addr *) *(xgethostbyname(opt_R)->h_addr_list); + remoteAddr.sin_port = htons(port); } //if (option_mask32 & OPT_locallog) // -L #endif #if ENABLE_FEATURE_IPC_SYSLOG - if (option_mask32 & OPT_circularlog) { // -C - if (opt_C) { - shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024; - } - } + if ((option_mask32 & OPT_circularlog) && opt_C) // -C + shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024; #endif /* If they have not specified remote logging, then log locally */ @@ -622,14 +559,12 @@ int syslogd_main(int argc, char **argv) option_mask32 |= OPT_locallog; /* Store away localhost's name before the fork */ - gethostname(LocalHostName, sizeof(LocalHostName)); - p = strchr(LocalHostName, '.'); + gethostname(localHostName, sizeof(localHostName)); + p = strchr(localHostName, '.'); if (p) { *p = '\0'; } - umask(0); - if (!(option_mask32 & OPT_nofork)) { #ifdef BB_NOMMU vfork_daemon_rexec(0, 1, argc, argv, "-n"); @@ -637,7 +572,8 @@ int syslogd_main(int argc, char **argv) xdaemon(0, 1); #endif } - doSyslogd(); + umask(0); + do_syslogd(); return EXIT_SUCCESS; }