+ if (pri != 0) {
+ for (c_fac = facilitynames;
+ c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++);
+ for (c_pri = prioritynames;
+ 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);
+ }
+
+ if (strlen(msg) < 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;
+ }
+
+ /* todo: supress duplicates */
+
+#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;
+
+ memset(&res, 0, sizeof(res));
+ snprintf(res, sizeof(res), "<%d>", pri);
+ v->iov_base = res ;
+ v->iov_len = strlen(res);
+ v++;
+
+ v->iov_base = msg;
+ v->iov_len = strlen(msg);
+
+ if ( -1 == writev(remotefd,iov, IOV_COUNT)){
+ error_msg_and_die("syslogd: cannot write to remote file handle on"
+ "%s:%d",RemoteHost,RemotePort);
+ }
+ }
+ if (local_logging == TRUE)
+#endif
+ /* now spew out the message to wherever it is supposed to go */
+ message("%s %s %s %s\n", timestamp, LocalHostName, res, msg);
+
+
+}
+
+static void quit_signal(int sig)
+{
+ logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting.");
+ unlink(lfile);
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
+ ipcsyslog_cleanup();
+#endif
+
+ exit(TRUE);
+}
+
+static void domark(int sig)
+{
+ if (MarkInterval > 0) {
+ logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --");
+ alarm(MarkInterval);
+ }
+}
+
+/* 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)
+{
+ RESERVE_CONFIG_BUFFER(tmpbuf, BUFSIZE + 1);
+ int n_read;
+ char *p = tmpbuf;
+
+ n_read = read (conn, tmpbuf, BUFSIZE );
+
+ while (p < tmpbuf + n_read) {
+
+ int pri = (LOG_USER | LOG_NOTICE);
+ char line[ BUFSIZE + 1 ];
+ unsigned char c;
+
+ char *q = line;
+
+ tmpbuf[ n_read - 1 ] = '\0';
+
+ while (p && (c = *p) && q < &line[ sizeof (line) - 1 ]) {
+ if (c == '<') {
+ /* Parse the magic priority number. */
+ 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);
+ }
+ RELEASE_CONFIG_BUFFER (tmpbuf);
+ return n_read;
+}
+
+
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+static void init_RemoteLog (void){
+
+ struct sockaddr_in remoteaddr;
+ struct hostent *hostinfo;
+ int len = sizeof(remoteaddr);
+
+ memset(&remoteaddr, 0, len);
+
+ remotefd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (remotefd < 0) {
+ error_msg_and_die("syslogd: cannot create socket");
+ }
+
+ hostinfo = xgethostbyname(RemoteHost);
+
+ remoteaddr.sin_family = AF_INET;
+ 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
+ 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);
+ }
+
+}
+#endif
+
+static void doSyslogd (void) __attribute__ ((noreturn));
+static void doSyslogd (void)
+{
+ struct sockaddr_un sunx;
+ socklen_t addrLength;
+
+
+ int sock_fd;
+ fd_set fds;
+
+ /* Set up signal handlers. */
+ signal (SIGINT, quit_signal);
+ signal (SIGTERM, quit_signal);
+ signal (SIGQUIT, quit_signal);
+ signal (SIGHUP, SIG_IGN);
+ signal (SIGCHLD, SIG_IGN);
+#ifdef SIGCLD
+ signal (SIGCLD, SIG_IGN);
+#endif
+ signal (SIGALRM, domark);
+ alarm (MarkInterval);
+
+ /* Create the syslog file so realpath() can work. */
+ if (realpath (_PATH_LOG, lfile) != NULL)
+ unlink (lfile);
+
+ 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)
+ 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)))
+ 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 CONFIG_FEATURE_IPC_SYSLOG
+ if (circular_logging == TRUE ){
+ ipcsyslog_init();
+ }
+#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));
+
+ if ((n_ready = select (FD_SETSIZE, &readfds, NULL, NULL, NULL)) < 0) {
+ if (errno == EINTR) continue; /* alarm may have happened. */
+ 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 */
+ } /* for main loop */
+}
+
+extern int syslogd_main(int argc, char **argv)
+{
+ int opt;
+ int doFork = TRUE;
+
+ char *p;
+
+ /* do normal option parsing */
+ while ((opt = getopt(argc, argv, "m:nO:R:LC")) > 0) {
+ switch (opt) {
+ case 'm':
+ MarkInterval = atoi(optarg) * 60;
+ break;
+ case 'n':
+ doFork = FALSE;
+ break;
+ case 'O':
+ logFilePath = strdup(optarg);
+ break;
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+ case 'R':
+ RemoteHost = strdup(optarg);
+ if ( (p = strchr(RemoteHost, ':'))){
+ RemotePort = atoi(p+1);
+ *p = '\0';
+ }
+ doRemoteLog = TRUE;
+ break;
+ case 'L':
+ local_logging = TRUE;
+ break;
+#endif
+#ifdef CONFIG_FEATURE_IPC_SYSLOG
+ case 'C':
+ circular_logging = TRUE;
+ break;
+#endif
+ default:
+ show_usage();
+ }
+ }
+
+#ifdef CONFIG_FEATURE_REMOTE_LOG
+ /* If they have not specified remote logging, then log locally */
+ if (doRemoteLog == FALSE)
+ local_logging = TRUE;
+#endif
+
+
+ /* Store away localhost's name before the fork */
+ gethostname(LocalHostName, sizeof(LocalHostName));
+ if ((p = strchr(LocalHostName, '.'))) {
+ *p++ = '\0';
+ }
+
+ umask(0);
+
+ if (doFork == TRUE) {
+ if (daemon(0, 1) < 0)
+ perror_msg_and_die("daemon");
+ }
+ doSyslogd();
+
+ return EXIT_SUCCESS;
+}