Only compile the files in this dir if the IP applet is enabled
[oweals/busybox.git] / sysklogd / syslogd.c
index 89f5348ec94ffbd197fac8ee275873ffe33d4463..e13ebfc342e42cb26816a89c0a9bbbfa32f06a9e 100644 (file)
@@ -2,8 +2,8 @@
 /*
  * Mini syslogd implementation for busybox
  *
- * Copyright (C) 1999,2000,2001 by Lineo, inc.
- * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
+ * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
+ * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org>
  *
  * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org>
  *
@@ -55,7 +55,7 @@
 #define __LOG_FILE "/var/log/messages"
 
 /* Path to the unix socket */
-static char lfile[BUFSIZ] = "";
+static char lfile[MAXPATHLEN];
 
 static char *logFilePath = __LOG_FILE;
 
@@ -63,9 +63,9 @@ static char *logFilePath = __LOG_FILE;
 static int MarkInterval = 20 * 60;
 
 /* localhost's name */
-static char LocalHostName[32];
+static char LocalHostName[64];
 
-#ifdef BB_FEATURE_REMOTE_LOG
+#ifdef CONFIG_FEATURE_REMOTE_LOG
 #include <netinet/in.h>
 /* udp socket for logging to remote host */
 static int remotefd = -1;
@@ -78,8 +78,17 @@ static int doRemoteLog = FALSE;
 static int local_logging = FALSE;
 #endif
 
+
+#define MAXLINE         1024            /* maximum line length */
+
+
 /* circular buffer variables/structures */
-#ifdef BB_FEATURE_IPC_SYSLOG
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
+#if __GNU_LIBRARY__ < 5
+#error Sorry.  Looks like you are using libc5.
+#error libc5 shm support isnt good enough.
+#error Please disable CONFIG_FEATURE_IPC_SYSLOG
+#endif
 
 #include <sys/ipc.h>
 #include <sys/sem.h>
@@ -90,19 +99,19 @@ static const long KEY_ID = 0x414e4547; /*"GENA"*/
 
 // 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
-       char data[1];           // data/messages
-} *buf = NULL;                 // shared memory pointer
+       int size;               // size of data written
+       int head;               // start of message list
+       int tail;               // end of message list
+       char data[1];           // data/messages
+} *buf = 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
 
-static int     shmid = -1;     // ipc shared memory id
-static int     s_semid = -1;   // ipc semaphore id
-int    data_size = 16000; // data size
-int    shm_size = 16000 + sizeof(*buf); // our buffer size
+static int      shmid = -1;     // ipc shared memory id
+static int      s_semid = -1;   // ipc semaphore id
+int     data_size = 16000; // data size
+int     shm_size = 16000 + sizeof(*buf); // our buffer size
 static int circular_logging = FALSE;
 
 /*
@@ -138,11 +147,11 @@ void ipcsyslog_cleanup(void){
 void ipcsyslog_init(void){
        if (buf == NULL){
            if ((shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023)) == -1)
-                       perror_msg_and_die("shmget");
+                       perror_msg_and_die("shmget");
 
 
            if ((buf = shmat(shmid, NULL, 0)) == NULL)
-                       perror_msg_and_die("shmat");
+                       perror_msg_and_die("shmat");
 
 
            buf->size=data_size;
@@ -150,11 +159,11 @@ void ipcsyslog_init(void){
 
            // we'll trust the OS to set initial semval to 0 (let's hope)
            if ((s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023)) == -1){
-               if (errno == EEXIST){
+               if (errno == EEXIST){
                   if ((s_semid = semget(KEY_ID, 2, 0)) == -1)
                    perror_msg_and_die("semget");
                }else
-                       perror_msg_and_die("semget");
+                       perror_msg_and_die("semget");
            }
        }else{
                printf("Buffer already allocated just grab the semaphore?");
@@ -179,16 +188,16 @@ void circ_message(const char *msg){
         * 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.
+        *      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 threasafe way of handling shared memory operations.
+        *       a threasafe way of handling shared memory operations.
         */
        if ( (buf->tail + l) < buf->size ){
                /* before we append the message we need to check the HEAD so that we won't
@@ -202,19 +211,19 @@ void circ_message(const char *msg){
                           * to worry about overflows here!
                           */
                           int k= buf->tail + l - buf->head; /* we need to know how many bytes
-                                                               we are overwriting to make
+                                                               we are overwriting to make
                                                                enough room */
                           char *c=memchr(buf->data+buf->head + k,'\0',buf->size - (buf->head + k));
                           if (c != NULL) {/* do a sanity check just in case! */
-                               buf->head = c - buf->data + 1; /* we need to convert pointer to
+                               buf->head = c - buf->data + 1; /* we need to convert pointer to
                                                                  offset + skip the '\0' since
                                                                  we need to point to the beginning
                                                                  of the next message */
                                /* 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("Weird! Can't find the terminator token??? \n");
-                               buf->head=0;
+                               printf("Weird! Can't find the terminator token??? \n");
+                               buf->head=0;
                           }
                        }
                } /* in other cases no overflows have been done yet, so we don't care! */
@@ -226,22 +235,22 @@ void circ_message(const char *msg){
                /* we need to break up the message and "circle" it around */
                char *c;
                int k=buf->tail + l - buf->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(buf->data + k ,'\0', buf->size - k);
-               
+
                if (c != NULL) /* if we don't have '\0'??? weird!!! */{
                        /* move head pointer*/
-                       buf->head=c-buf->data+1; 
-                       
-                       /* now write the first part of the message */                   
+                       buf->head=c-buf->data+1;
+
+                       /* now write the first part of the message */
                        strncpy(buf->data + buf->tail, msg, l - k - 1);
-                       
+
                        /* ALWAYS terminate end of buffer w/ '\0' */
-                       buf->data[buf->size-1]='\0'; 
-                       
+                       buf->data[buf->size-1]='\0';
+
                        /* now write out the rest of the string to the beginning of the buffer */
                        strcpy(buf->data, &msg[l-k-1]);
 
@@ -251,11 +260,12 @@ void circ_message(const char *msg){
                        printf("Weird! Can't find the terminator token from the beginning??? \n");
                        buf->head = buf->tail = 0; /* reset buffer, since it's probably corrupted */
                }
-               
+
        }
        sem_up(s_semid);
 }
-#endif
+#endif  /* CONFIG_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)));
@@ -269,11 +279,11 @@ static void message (char *fmt, ...)
        fl.l_start  = 0;
        fl.l_len    = 1;
 
-#ifdef BB_FEATURE_IPC_SYSLOG
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
        if ((circular_logging == TRUE) && (buf != NULL)){
                        char b[1024];
                        va_start (arguments, fmt);
-                       vsprintf (b, fmt, arguments);
+                       vsnprintf (b, sizeof(b)-1, fmt, arguments);
                        va_end (arguments);
                        circ_message(b);
 
@@ -339,24 +349,25 @@ static void logMessage (int pri, char *msg)
 
        /* todo: supress duplicates */
 
-#ifdef BB_FEATURE_REMOTE_LOG
+#ifdef CONFIG_FEATURE_REMOTE_LOG
        /* send message to remote logger */
        if ( -1 != remotefd){
 static const int IOV_COUNT = 2;
                struct iovec iov[IOV_COUNT];
                struct iovec *v = iov;
 
-               bzero(&res, sizeof(res));
+               memset(&res, 0, sizeof(res));
                snprintf(res, sizeof(res), "<%d>", pri);
                v->iov_base = res ;
-               v->iov_len = strlen(res);          
+               v->iov_len = strlen(res);
                v++;
 
                v->iov_base = msg;
-               v->iov_len = strlen(msg);          
-
+               v->iov_len = strlen(msg);
+writev_retry:
                if ( -1 == writev(remotefd,iov, IOV_COUNT)){
-                       error_msg_and_die("syslogd: cannot write to remote file handle on" 
+                       if (errno == EINTR) goto writev_retry;
+                       error_msg_and_die("cannot write to remote file handle on"
                                        "%s:%d",RemoteHost,RemotePort);
                }
        }
@@ -372,7 +383,7 @@ static void quit_signal(int sig)
 {
        logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting.");
        unlink(lfile);
-#ifdef BB_FEATURE_IPC_SYSLOG
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
        ipcsyslog_cleanup();
 #endif
 
@@ -389,25 +400,19 @@ static void domark(int sig)
 
 /* This must be a #define, since when DODEBUG and BUFFERS_GO_IN_BSS are
  * enabled, we otherwise get a "storage size isn't constant error. */
-#define BUFSIZE 1023
-static int serveConnection (int conn)
+static int serveConnection (char* tmpbuf, int n_read)
 {
-       RESERVE_BB_BUFFER(tmpbuf, BUFSIZE + 1);
-       int    n_read;
-
-       n_read = read (conn, tmpbuf, BUFSIZE );
+       char *p = tmpbuf;
 
-       if (n_read > 0) {
+       while (p < tmpbuf + n_read) {
 
                int           pri = (LOG_USER | LOG_NOTICE);
-               char          line[ BUFSIZE + 1 ];
+               char          line[ MAXLINE + 1 ];
                unsigned char c;
 
-               char *p = tmpbuf, *q = line;
-
-               tmpbuf[ n_read - 1 ] = '\0';
+               char *q = line;
 
-               while (p && (c = *p) && q < &line[ sizeof (line) - 1 ]) {
+               while ( (c = *p) && q < &line[ sizeof (line) - 1 ]) {
                        if (c == '<') {
                        /* Parse the magic priority number. */
                                pri = 0;
@@ -428,6 +433,7 @@ static int serveConnection (int conn)
                        p++;
                }
                *q = '\0';
+               p++;
                /* Now log it */
                logMessage (pri, line);
        }
@@ -435,19 +441,20 @@ static int serveConnection (int conn)
 }
 
 
-#ifdef BB_FEATURE_REMOTE_LOG
-static void init_RemoteLog (void){
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+static void init_RemoteLog (void)
+{
 
   struct sockaddr_in remoteaddr;
   struct hostent *hostinfo;
   int len = sizeof(remoteaddr);
 
-  bzero(&remoteaddr, len);
+  memset(&remoteaddr, 0, len);
 
   remotefd = socket(AF_INET, SOCK_DGRAM, 0);
 
   if (remotefd < 0) {
-    error_msg_and_die("syslogd: cannot create socket");
+    error_msg_and_die("cannot create socket");
   }
 
   hostinfo = xgethostbyname(RemoteHost);
@@ -456,12 +463,12 @@ static void init_RemoteLog (void){
   remoteaddr.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
   remoteaddr.sin_port = htons(RemotePort);
 
-  /* 
-     Since we are using UDP sockets, connect just sets the default host and port 
+  /*
+     Since we are using UDP sockets, connect just sets the default host and port
      for future operations
   */
   if ( 0 != (connect(remotefd, (struct sockaddr *) &remoteaddr, len))){
-    error_msg_and_die("syslogd: cannot connect to remote host %s:%d", RemoteHost, RemotePort);
+    error_msg_and_die("cannot connect to remote host %s:%d", RemoteHost, RemotePort);
   }
 
 }
@@ -473,7 +480,6 @@ static void doSyslogd (void)
        struct sockaddr_un sunx;
        socklen_t addrLength;
 
-
        int sock_fd;
        fd_set fds;
 
@@ -496,77 +502,65 @@ static void doSyslogd (void)
        memset (&sunx, 0, sizeof (sunx));
        sunx.sun_family = AF_UNIX;
        strncpy (sunx.sun_path, lfile, sizeof (sunx.sun_path));
-       if ((sock_fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
+       if ((sock_fd = socket (AF_UNIX, SOCK_DGRAM, 0)) < 0)
                perror_msg_and_die ("Couldn't get file descriptor for socket " _PATH_LOG);
 
        addrLength = sizeof (sunx.sun_family) + strlen (sunx.sun_path);
-       if ((bind (sock_fd, (struct sockaddr *) &sunx, addrLength)) || (listen (sock_fd, 5)))
+       if (bind(sock_fd, (struct sockaddr *) &sunx, addrLength) < 0)
                perror_msg_and_die ("Could not connect to socket " _PATH_LOG);
 
        if (chmod (lfile, 0666) < 0)
                perror_msg_and_die ("Could not set permission on " _PATH_LOG);
 
-       FD_ZERO (&fds);
-       FD_SET (sock_fd, &fds);
 
-#ifdef BB_FEATURE_IPC_SYSLOG
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
        if (circular_logging == TRUE ){
           ipcsyslog_init();
        }
 #endif
 
-        #ifdef BB_FEATURE_REMOTE_LOG
-        if (doRemoteLog == TRUE){
-          init_RemoteLog();
-        }
-        #endif
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+       if (doRemoteLog == TRUE){
+         init_RemoteLog();
+       }
+#endif
 
        logMessage (LOG_SYSLOG | LOG_INFO, "syslogd started: " BB_BANNER);
 
        for (;;) {
 
-               fd_set readfds;
-               int    n_ready;
-               int    fd;
-
-               memcpy (&readfds, &fds, sizeof (fds));
+               FD_ZERO (&fds);
+               FD_SET (sock_fd, &fds);
 
-               if ((n_ready = select (FD_SETSIZE, &readfds, NULL, NULL, NULL)) < 0) {
-                       if (errno == EINTR) continue; /* alarm may have happened. */
+               if (select (sock_fd+1, &fds, NULL, NULL, NULL) < 0) {
+                       if (errno == EINTR) {
+                               /* alarm may have happened. */
+                               continue;
+                       }
                        perror_msg_and_die ("select error");
                }
 
-               for (fd = 0; (n_ready > 0) && (fd < FD_SETSIZE); fd++) {
-                       if (FD_ISSET (fd, &readfds)) {
-
-                               --n_ready;
-
-                               if (fd == sock_fd) {
-                                       int   conn;
-
-                                       //printf("New Connection request.\n");
-                                       if ((conn = accept (sock_fd, (struct sockaddr *) &sunx, &addrLength)) < 0) {
-                                               perror_msg_and_die ("accept error");
-                                       }
-
-                                       FD_SET(conn, &fds);
-                                       //printf("conn: %i, set_size: %i\n",conn,FD_SETSIZE);
-                               } else {
-                                       //printf("Serving connection: %i\n",fd);
-                                         if ( serveConnection(fd) <= 0 ) {
-                                           close (fd);
-                                           FD_CLR(fd, &fds);
-            }
-                               } /* fd == sock_fd */
-                       }/* FD_ISSET() */
-               }/* for */
+               if (FD_ISSET (sock_fd, &fds)) {
+                      int   i;
+                      RESERVE_CONFIG_BUFFER(tmpbuf, BUFSIZ + 1);
+
+                      memset(tmpbuf, '\0', BUFSIZ+1);
+                      if ( (i = recv(sock_fd, tmpbuf, BUFSIZ, 0)) > 0) {
+                              serveConnection(tmpbuf, i);
+                      } else {
+                              perror_msg_and_die ("UNIX socket error");
+                      }
+                      RELEASE_CONFIG_BUFFER (tmpbuf);
+               }/* FD_ISSET() */
        } /* for main loop */
 }
 
 extern int syslogd_main(int argc, char **argv)
 {
        int opt;
+#if ! defined(__uClinux__)
        int doFork = TRUE;
+#endif
 
        char *p;
 
@@ -576,15 +570,17 @@ extern int syslogd_main(int argc, char **argv)
                        case 'm':
                                MarkInterval = atoi(optarg) * 60;
                                break;
+#if ! defined(__uClinux__)
                        case 'n':
                                doFork = FALSE;
                                break;
+#endif
                        case 'O':
-                               logFilePath = strdup(optarg);
+                               logFilePath = xstrdup(optarg);
                                break;
-#ifdef BB_FEATURE_REMOTE_LOG
+#ifdef CONFIG_FEATURE_REMOTE_LOG
                        case 'R':
-                               RemoteHost = strdup(optarg);
+                               RemoteHost = xstrdup(optarg);
                                if ( (p = strchr(RemoteHost, ':'))){
                                        RemotePort = atoi(p+1);
                                        *p = '\0';
@@ -595,7 +591,7 @@ extern int syslogd_main(int argc, char **argv)
                                local_logging = TRUE;
                                break;
 #endif
-#ifdef BB_FEATURE_IPC_SYSLOG
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
                        case 'C':
                                circular_logging = TRUE;
                                break;
@@ -605,7 +601,7 @@ extern int syslogd_main(int argc, char **argv)
                }
        }
 
-#ifdef BB_FEATURE_REMOTE_LOG
+#ifdef CONFIG_FEATURE_REMOTE_LOG
        /* If they have not specified remote logging, then log locally */
        if (doRemoteLog == FALSE)
                local_logging = TRUE;
@@ -620,10 +616,12 @@ extern int syslogd_main(int argc, char **argv)
 
        umask(0);
 
+#if ! defined(__uClinux__)
        if (doFork == TRUE) {
                if (daemon(0, 1) < 0)
                        perror_msg_and_die("daemon");
        }
+#endif
        doSyslogd();
 
        return EXIT_SUCCESS;