www.usr.com/support/gpl/USR9113_release1.0.tar.gz
[bcm963xx.git] / userapps / opensource / busybox / sysklogd / syslogd.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini syslogd implementation for busybox
4  *
5  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6  *
7  * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org>
8  *
9  * "circular buffer" Copyright (C) 2001 by Gennady Feldman <gfeldman@gena01.com>
10  *
11  * Maintainer: Gennady Feldman <gfeldman@gena01.com> as of Mar 12, 2001
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21  * General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26  *
27  */
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <getopt.h>
35 #include <netdb.h>
36 #include <paths.h>
37 #include <signal.h>
38 #include <stdarg.h>
39 #include <stdbool.h>
40 #include <time.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <sys/socket.h>
44 #include <sys/types.h>
45 #include <sys/un.h>
46 #include <sys/param.h>
47
48 #include "busybox.h"
49
50 /* SYSLOG_NAMES defined to pull some extra junk from syslog.h */
51 #define SYSLOG_NAMES
52 #include <sys/syslog.h>
53 #include <sys/uio.h>
54
55 /*BRCM begin*/
56 int localLogLevel=-1;
57 int remoteLogLevel=-1;
58 /*BRCM end*/
59
60 /* Path for the file where all log messages are written */
61 #define __LOG_FILE "/var/log/messages"
62
63 /* Path to the unix socket */
64 static char lfile[MAXPATHLEN];
65
66 static const char *logFilePath = __LOG_FILE;
67
68 #ifdef CONFIG_FEATURE_ROTATE_LOGFILE
69 /* max size of message file before being rotated */
70 static int logFileSize = 200 * 1024;
71
72 /* number of rotated message files */
73 static int logFileRotate = 1;
74 #endif
75
76 /* interval between marks in seconds */
77 /*BRCM begin*/
78 /*static int MarkInterval = 20 * 60; */
79 static int MarkInterval = 60 * 60;
80 /*BRCM end*/
81
82 /* localhost's name */
83 static char LocalHostName[64];
84
85 #ifdef CONFIG_FEATURE_REMOTE_LOG
86 #include <netinet/in.h>
87 /* udp socket for logging to remote host */
88 static int remotefd = -1;
89 static struct sockaddr_in remoteaddr;
90
91 /* where do we log? */
92 static char *RemoteHost;
93
94 /* what port to log to? */
95 static int RemotePort = 514;
96
97 /* To remote log or not to remote log, that is the question. */
98 static int doRemoteLog = FALSE;
99 static int local_logging = FALSE;
100 #endif
101
102 /* Make loging output smaller. */
103 static bool small = false;
104
105 #define MAXLINE         1024    /* maximum line length */
106
107
108 /* circular buffer variables/structures */
109 #ifdef CONFIG_FEATURE_IPC_SYSLOG
110
111 #if CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE < 4
112 #error Sorry, you must set the syslogd buffer size to at least 4KB.
113 #error Please check CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE
114 #endif
115
116 #include <sys/ipc.h>
117 #include <sys/sem.h>
118 #include <sys/shm.h>
119
120 /* our shared key */
121 static const long KEY_ID = 0x414e4547;  /*"GENA" */
122
123 // Semaphore operation structures
124 static struct shbuf_ds {
125         int size;                       // size of data written
126         int head;                       // start of message list
127         int tail;                       // end of message list
128         char data[1];           // data/messages
129 } *buf = NULL;                  // shared memory pointer
130
131 static struct sembuf SMwup[1] = { {1, -1, IPC_NOWAIT} };        // set SMwup
132 static struct sembuf SMwdn[3] = { {0, 0}, {1, 0}, {1, +1} };    // set SMwdn
133
134 static int shmid = -1;  // ipc shared memory id
135 static int s_semid = -1;        // ipc semaphore id
136 static int shm_size = ((CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE)*1024);   // default shm size
137 static int circular_logging = FALSE;
138
139 static void init_RemoteLog(void);
140
141 /*
142  * sem_up - up()'s a semaphore.
143  */
144 static inline void sem_up(int semid)
145 {
146         if (semop(semid, SMwup, 1) == -1) {
147                 bb_perror_msg_and_die("semop[SMwup]");
148         }
149 }
150
151 /*
152  * sem_down - down()'s a semaphore
153  */
154 static inline void sem_down(int semid)
155 {
156         if (semop(semid, SMwdn, 3) == -1) {
157                 bb_perror_msg_and_die("semop[SMwdn]");
158         }
159 }
160
161
162 void ipcsyslog_cleanup(void)
163 {
164         printf("Exiting Syslogd!\n");
165         if (shmid != -1) {
166                 shmdt(buf);
167         }
168
169         if (shmid != -1) {
170                 shmctl(shmid, IPC_RMID, NULL);
171         }
172         if (s_semid != -1) {
173                 semctl(s_semid, 0, IPC_RMID, 0);
174         }
175 }
176
177 void ipcsyslog_init(void)
178 {
179         if (buf == NULL) {
180                 if ((shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023)) == -1) {
181                         bb_perror_msg_and_die("shmget");
182                 }
183
184                 if ((buf = shmat(shmid, NULL, 0)) == NULL) {
185                         bb_perror_msg_and_die("shmat");
186                 }
187
188                 buf->size = shm_size - sizeof(*buf);
189                 buf->head = buf->tail = 0;
190
191                 // we'll trust the OS to set initial semval to 0 (let's hope)
192                 if ((s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023)) == -1) {
193                         if (errno == EEXIST) {
194                                 if ((s_semid = semget(KEY_ID, 2, 0)) == -1) {
195                                         bb_perror_msg_and_die("semget");
196                                 }
197                         } else {
198                                 bb_perror_msg_and_die("semget");
199                         }
200                 }
201         } else {
202                 printf("Buffer already allocated just grab the semaphore?");
203         }
204 }
205
206 /* write message to buffer */
207 void circ_message(const char *msg)
208 {
209         int l = strlen(msg) + 1;        /* count the whole message w/ '\0' included */
210
211         sem_down(s_semid);
212
213         /*
214          * Circular Buffer Algorithm:
215          * --------------------------
216          *
217          * Start-off w/ empty buffer of specific size SHM_SIZ
218          * Start filling it up w/ messages. I use '\0' as separator to break up messages.
219          * This is also very handy since we can do printf on message.
220          *
221          * Once the buffer is full we need to get rid of the first message in buffer and
222          * insert the new message. (Note: if the message being added is >1 message then
223          * we will need to "remove" >1 old message from the buffer). The way this is done
224          * is the following:
225          *      When we reach the end of the buffer we set a mark and start from the beginning.
226          *      Now what about the beginning and end of the buffer? Well we have the "head"
227          *      index/pointer which is the starting point for the messages and we have "tail"
228          *      index/pointer which is the ending point for the messages. When we "display" the
229          *      messages we start from the beginning and continue until we reach "tail". If we
230          *      reach end of buffer, then we just start from the beginning (offset 0). "head" and
231          *      "tail" are actually offsets from the beginning of the buffer.
232          *
233          * Note: This algorithm uses Linux IPC mechanism w/ shared memory and semaphores to provide
234          *       a threasafe way of handling shared memory operations.
235          */
236         if ((buf->tail + l) < buf->size) {
237                 /* before we append the message we need to check the HEAD so that we won't
238                    overwrite any of the message that we still need and adjust HEAD to point
239                    to the next message! */
240                 if (buf->tail < buf->head) {
241                         if ((buf->tail + l) >= buf->head) {
242                                 /* we need to move the HEAD to point to the next message
243                                  * Theoretically we have enough room to add the whole message to the
244                                  * buffer, because of the first outer IF statement, so we don't have
245                                  * to worry about overflows here!
246                                  */
247                                 int k = buf->tail + l - buf->head;      /* we need to know how many bytes
248                                                                                                            we are overwriting to make
249                                                                                                            enough room */
250                                 char *c =
251                                         memchr(buf->data + buf->head + k, '\0',
252                                                    buf->size - (buf->head + k));
253                                 if (c != NULL) {        /* do a sanity check just in case! */
254                                         buf->head = c - buf->data + 1;  /* we need to convert pointer to
255                                                                                                            offset + skip the '\0' since
256                                                                                                            we need to point to the beginning
257                                                                                                            of the next message */
258                                         /* Note: HEAD is only used to "retrieve" messages, it's not used
259                                            when writing messages into our buffer */
260                                 } else {        /* show an error message to know we messed up? */
261                                         printf("Weird! Can't find the terminator token??? \n");
262                                         buf->head = 0;
263                                 }
264                         }
265                 }
266
267                 /* in other cases no overflows have been done yet, so we don't care! */
268                 /* we should be ok to append the message now */
269                 strncpy(buf->data + buf->tail, msg, l); /* append our message */
270                 buf->tail += l; /* count full message w/ '\0' terminating char */
271         } else {
272                 /* we need to break up the message and "circle" it around */
273                 char *c;
274                 int k = buf->tail + l - buf->size;      /* count # of bytes we don't fit */
275
276                 /* We need to move HEAD! This is always the case since we are going
277                  * to "circle" the message.
278                  */
279                 c = memchr(buf->data + k, '\0', buf->size - k);
280
281                 if (c != NULL) {        /* if we don't have '\0'??? weird!!! */
282                         /* move head pointer */
283                         buf->head = c - buf->data + 1;
284
285                         /* now write the first part of the message */
286                         strncpy(buf->data + buf->tail, msg, l - k - 1);
287
288                         /* ALWAYS terminate end of buffer w/ '\0' */
289                         buf->data[buf->size - 1] = '\0';
290
291                         /* now write out the rest of the string to the beginning of the buffer */
292                         strcpy(buf->data, &msg[l - k - 1]);
293
294                         /* we need to place the TAIL at the end of the message */
295                         buf->tail = k + 1;
296                 } else {
297                         printf
298                                 ("Weird! Can't find the terminator token from the beginning??? \n");
299                         buf->head = buf->tail = 0;      /* reset buffer, since it's probably corrupted */
300                 }
301
302         }
303         sem_up(s_semid);
304 }
305 #endif                                                  /* CONFIG_FEATURE_IPC_SYSLOG */
306
307 /* Note: There is also a function called "message()" in init.c */
308 /* Print a message to the log file. */
309 static void message(char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
310 static void message(char *fmt, ...)
311 {
312         int fd;
313         struct flock fl;
314         va_list arguments;
315
316         fl.l_whence = SEEK_SET;
317         fl.l_start = 0;
318         fl.l_len = 1;
319
320 #ifdef CONFIG_FEATURE_IPC_SYSLOG
321         if ((circular_logging == TRUE) && (buf != NULL)) {
322                 char b[1024];
323
324                 va_start(arguments, fmt);
325                 vsnprintf(b, sizeof(b) - 1, fmt, arguments);
326                 va_end(arguments);
327                 circ_message(b);
328
329         } else
330 #endif
331         if ((fd =
332                          device_open(logFilePath,
333                                                          O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
334                                                          O_NONBLOCK)) >= 0) {
335                 fl.l_type = F_WRLCK;
336                 fcntl(fd, F_SETLKW, &fl);
337 #ifdef CONFIG_FEATURE_ROTATE_LOGFILE
338                 if ( logFileSize > 0 ) {
339                         struct stat statf;
340                         int r = fstat(fd, &statf);
341                         if( !r && (statf.st_mode & S_IFREG)
342                                 && (lseek(fd,0,SEEK_END) > logFileSize) ) {
343                                 if(logFileRotate > 0) {
344                                         int i;
345                                         char oldFile[(strlen(logFilePath)+3)], newFile[(strlen(logFilePath)+3)];
346                                         for(i=logFileRotate-1;i>0;i--) {
347                                                 sprintf(oldFile, "%s.%d", logFilePath, i-1);
348                                                 sprintf(newFile, "%s.%d", logFilePath, i);
349                                                 rename(oldFile, newFile);
350                                         }
351                                         sprintf(newFile, "%s.%d", logFilePath, 0);
352                                         fl.l_type = F_UNLCK;
353                                         fcntl (fd, F_SETLKW, &fl);
354                                         close(fd);
355                                         rename(logFilePath, newFile);
356                                         fd = device_open (logFilePath,
357                                                    O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
358                                                    O_NONBLOCK);
359                                         fl.l_type = F_WRLCK;
360                                         fcntl (fd, F_SETLKW, &fl);
361                                 } else {
362                                         ftruncate( fd, 0 );
363                                 }
364                         }
365                 }
366 #endif
367                 va_start(arguments, fmt);
368                 vdprintf(fd, fmt, arguments);
369                 va_end(arguments);
370                 fl.l_type = F_UNLCK;
371                 fcntl(fd, F_SETLKW, &fl);
372                 close(fd);
373         } else {
374                 /* Always send console messages to /dev/console so people will see them. */
375                 if ((fd =
376                          device_open(_PATH_CONSOLE,
377                                                  O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) {
378                         va_start(arguments, fmt);
379                         vdprintf(fd, fmt, arguments);
380                         va_end(arguments);
381                         close(fd);
382                 } else {
383                         fprintf(stderr, "Bummer, can't print: ");
384                         va_start(arguments, fmt);
385                         vfprintf(stderr, fmt, arguments);
386                         fflush(stderr);
387                         va_end(arguments);
388                 }
389         }
390 }
391
392 static void logMessage(int pri, char *msg)
393 {
394         time_t now;
395         char *timestamp;
396         static char res[20] = "";
397 #ifdef CONFIG_FEATURE_REMOTE_LOG        
398         static char line[MAXLINE + 1];
399 #endif
400         CODE *c_pri, *c_fac;
401 /*BRCM begin*/
402         int localLog=1;
403         int remoteLog=1;
404         int len;
405 /*BRCM end*/
406
407         if (pri != 0) {
408                 for (c_fac = facilitynames;
409                          c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++);
410                 for (c_pri = prioritynames;
411                          c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++);
412                 if (c_fac->c_name == NULL || c_pri->c_name == NULL) {
413                         snprintf(res, sizeof(res), "<%d>", pri);
414                 } else {
415                         snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name);
416                 }
417         }
418
419 /*BRCM begin*/
420         if ((pri != 0) && (c_pri->c_name != NULL)) {
421                 if (c_pri->c_val > localLogLevel) 
422                         localLog = 0;
423                 if (c_pri->c_val > remoteLogLevel)
424                         remoteLog = 0;
425         }
426         if (!localLog && !remoteLog)
427                 return;
428 /*BRCM end*/
429
430         if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' ||
431                 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') {
432                 time(&now);
433                 timestamp = ctime(&now) + 4;
434                 timestamp[15] = '\0';
435         } else {
436                 timestamp = msg;
437                 timestamp[15] = '\0';
438                 msg += 16;
439         }
440
441         /* todo: supress duplicates */
442
443 #ifdef CONFIG_FEATURE_REMOTE_LOG
444         if (doRemoteLog == TRUE) {
445                 /* trying connect the socket */
446                 if (-1 == remotefd) {
447                         init_RemoteLog();
448                 }
449
450                 /* if we have a valid socket, send the message */
451                 if (-1 != remotefd) {
452                         now = 1;
453                         snprintf(line, sizeof(line), "<%d> %s", pri, msg);
454
455                 retry:
456                         /* send message to remote logger */
457                         if(( -1 == sendto(remotefd, line, strlen(line), 0,
458                                                         (struct sockaddr *) &remoteaddr,
459                                                         sizeof(remoteaddr))) && (errno == EINTR)) {
460                                 /* sleep now seconds and retry (with now * 2) */
461                                 sleep(now);
462                                 now *= 2;
463                                 goto retry;
464                         }
465                 }
466         }
467
468 /*BRCM begin*/
469 //      if (local_logging == TRUE)
470         /* bug fix ; circular_logging should do too; it only checked
471                  *            -L local logging.   */
472         if (((local_logging == TRUE) || (circular_logging)) && localLog) {
473 #endif
474         //              /* now spew out the message to wherever it is supposed to go */
475         //              message("%s %s %s %s\n", timestamp, LocalHostName, res, msg);
476         /* brcm, add len of string to do log display with latestest event displayed first */
477         /* now spew out the message to wherever it is supposed to go; 4 spaces+ \0 + \n + len(3bytes) */
478                 len = (strlen(timestamp)+strlen(LocalHostName)+strlen(res)+strlen(msg)+9);
479                 message("%s %s %s %s %3i\n", timestamp, LocalHostName, res, msg, len);
480 #ifdef CONFIG_FEATURE_REMOTE_LOG
481         }
482 #endif
483 /*BRCM end*/
484 }
485
486 static void quit_signal(int sig)
487 {
488 /*BRCM begin */
489         char pidfilename[30];
490         /* change to priority emerg to be consistent with klogd */
491         logMessage(LOG_SYSLOG | LOG_EMERG, "System log daemon exiting.");
492         // logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting.");
493
494         unlink(lfile);
495         sprintf (pidfilename, "%s%s.pid", _PATH_VARRUN, "syslogd");
496         unlink (pidfilename);
497 /*BRCM end*/
498
499         unlink(lfile);
500 #ifdef CONFIG_FEATURE_IPC_SYSLOG
501         ipcsyslog_cleanup();
502 #endif
503
504         exit(TRUE);
505 }
506
507 static void domark(int sig)
508 {
509         if (MarkInterval > 0) {
510                 logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --");
511                 alarm(MarkInterval);
512         }
513 }
514
515 /* This must be a #define, since when CONFIG_DEBUG and BUFFERS_GO_IN_BSS are
516  * enabled, we otherwise get a "storage size isn't constant error. */
517 static int serveConnection(char *tmpbuf, int n_read)
518 {
519         char *p = tmpbuf;
520
521         while (p < tmpbuf + n_read) {
522
523                 int pri = (LOG_USER | LOG_NOTICE);
524                 int num_lt = 0;
525                 char line[MAXLINE + 1];
526                 unsigned char c;
527                 char *q = line;
528
529                 while ((c = *p) && q < &line[sizeof(line) - 1]) {
530                         if (c == '<' && num_lt == 0) {
531                                 /* Parse the magic priority number. */
532                                 num_lt++;
533                                 pri = 0;
534                                 while (isdigit(*(++p))) {
535                                         pri = 10 * pri + (*p - '0');
536                                 }
537                                 if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) {
538                                         pri = (LOG_USER | LOG_NOTICE);
539                                 }
540                         } else if (c == '\n') {
541                                 *q++ = ' ';
542                         } else if (iscntrl(c) && (c < 0177)) {
543                                 *q++ = '^';
544                                 *q++ = c ^ 0100;
545                         } else {
546                                 *q++ = c;
547                         }
548                         p++;
549                 }
550                 *q = '\0';
551                 p++;
552                 /* Now log it */
553                 logMessage(pri, line);
554         }
555         return n_read;
556 }
557
558
559 #ifdef CONFIG_FEATURE_REMOTE_LOG
560 static void init_RemoteLog(void)
561 {
562         memset(&remoteaddr, 0, sizeof(remoteaddr));
563         remotefd = socket(AF_INET, SOCK_DGRAM, 0);
564
565         if (remotefd < 0) {
566           /* BRCM begin */
567           if ((local_logging == FALSE) && (circular_logging == FALSE))
568                 bb_error_msg_and_die("cannot create socket");
569           else
570                 bb_perror_msg("cannot create socket");
571           /* BRCM end */
572         }
573
574         remoteaddr.sin_family = AF_INET;
575         remoteaddr.sin_addr = *(struct in_addr *) *(xgethostbyname(RemoteHost))->h_addr_list;
576         remoteaddr.sin_port = htons(RemotePort);
577 }
578 #endif
579
580 static void doSyslogd(void) __attribute__ ((noreturn));
581 static void doSyslogd(void)
582 {
583         struct sockaddr_un sunx;
584         socklen_t addrLength;
585 /*BRCM begin*/
586         FILE *pidfile;
587         char pidfilename[30];
588 /* All the access to /dev/log will be redirected to /var/log/log
589  *  * which is TMPFS, memory file system.
590  **/
591 #define BRCM_PATH_LOG "/var/log/log"
592 /*BRCM end*/
593
594         int sock_fd;
595         fd_set fds;
596
597         /* Set up signal handlers. */
598         signal(SIGINT, quit_signal);
599         signal(SIGTERM, quit_signal);
600         signal(SIGQUIT, quit_signal);
601         signal(SIGHUP, SIG_IGN);
602         signal(SIGCHLD, SIG_IGN);
603 #ifdef SIGCLD
604         signal(SIGCLD, SIG_IGN);
605 #endif
606         signal(SIGALRM, domark);
607         alarm(MarkInterval);
608
609         /* Create the syslog file so realpath() can work. */
610 /*BRCM begin*/
611         /*
612         if (realpath (_PATH_LOG, lfile) != NULL) {
613         */
614         if (realpath (BRCM_PATH_LOG, lfile) != NULL) {
615 /*BRCM end*/
616                 unlink (lfile);
617         }
618
619         memset(&sunx, 0, sizeof(sunx));
620         sunx.sun_family = AF_UNIX;
621         strncpy(sunx.sun_path, lfile, sizeof(sunx.sun_path));
622         if ((sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
623 /*BRCM begin*/
624 /*              bb_perror_msg_and_die("Couldn't get file descriptor for socket "
625                                                    _PATH_LOG);
626 */
627                 bb_error_msg_and_die ("Couldn't get file descriptor for socket " BRCM_PATH_LOG);
628 /*BRCM end*/
629         }
630
631         addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path);
632         if (bind(sock_fd, (struct sockaddr *) &sunx, addrLength) < 0) {
633 /*BRCM begin*/
634 /*              bb_perror_msg_and_die("Could not connect to socket " _PATH_LOG);
635  */
636                 bb_error_msg_and_die ("Could not connect to socket " BRCM_PATH_LOG);
637 /*BRCM end*/
638         }
639
640         if (chmod(lfile, 0666) < 0) {
641 /*BRCM begin*/
642 /*              bb_perror_msg_and_die("Could not set permission on " _PATH_LOG);
643  */
644                 bb_error_msg_and_die ("Could not set permission on " BRCM_PATH_LOG);
645 /*BRCM end*/
646         }
647 #ifdef CONFIG_FEATURE_IPC_SYSLOG
648         if (circular_logging == TRUE) {
649                 ipcsyslog_init();
650         }
651 #endif
652
653 #ifdef CONFIG_FEATURE_REMOTE_LOG
654         if (doRemoteLog == TRUE) {
655                 init_RemoteLog();
656         }
657 #endif
658
659 /*BRCM begin*/
660         if (localLogLevel < LOG_EMERG)
661                 localLogLevel = LOG_DEBUG;
662         if (remoteLogLevel < LOG_EMERG)
663                 remoteLogLevel = LOG_ERR;
664
665         /* change to priority emerg to be consistent with klogd */
666         /* logMessage(LOG_SYSLOG | LOG_INFO, "syslogd started: " BB_BANNER); */
667         logMessage (LOG_SYSLOG | LOG_EMERG, "BCM96345  started: " BB_BANNER);
668
669         sprintf (pidfilename, "%s%s.pid", _PATH_VARRUN, "syslogd");
670         if ((pidfile = fopen (pidfilename, "w")) != NULL) {
671                 fprintf (pidfile, "%d\n", getpid ());
672                 (void) fclose (pidfile);
673         }
674         else {
675                 logMessage ((LOG_SYSLOG | LOG_ERR),("Failed to create pid file %s", pidfilename));
676         }
677 /*BRCM end*/
678
679         for (;;) {
680
681                 FD_ZERO(&fds);
682                 FD_SET(sock_fd, &fds);
683
684                 if (select(sock_fd + 1, &fds, NULL, NULL, NULL) < 0) {
685                         if (errno == EINTR) {
686                                 /* alarm may have happened. */
687                                 continue;
688                         }
689                         bb_perror_msg_and_die("select error");
690                 }
691
692                 if (FD_ISSET(sock_fd, &fds)) {
693                         int i;
694
695                         RESERVE_CONFIG_BUFFER(tmpbuf, MAXLINE + 1);
696
697                         memset(tmpbuf, '\0', MAXLINE + 1);
698                         if ((i = recv(sock_fd, tmpbuf, MAXLINE, 0)) > 0) {
699                                 serveConnection(tmpbuf, i);
700                         } else {
701                                 bb_perror_msg_and_die("UNIX socket error");
702                         }
703                         RELEASE_CONFIG_BUFFER(tmpbuf);
704                 }                               /* FD_ISSET() */
705         }                                       /* for main loop */
706 }
707
708 extern int syslogd_main(int argc, char **argv)
709 {
710         int opt;
711
712         int doFork = TRUE;
713
714         char *p;
715
716         /* do normal option parsing */
717 /*BRCM begin*/
718         /*
719         while ((opt = getopt(argc, argv, "m:nO:s:b:R:LC::")) > 0) {
720         */
721         /* brcm, l - local log level, r - remote log level */
722         while ((opt = getopt(argc, argv, "m:nO:s:Sb:R:l:r:LC")) > 0) {
723 /*BRCM end*/
724                 switch (opt) {
725                 case 'm':
726                         MarkInterval = atoi(optarg) * 60;
727                         break;
728                 case 'n':
729                         doFork = FALSE;
730                         break;
731                 case 'O':
732                         logFilePath = optarg;
733                         break;
734 #ifdef CONFIG_FEATURE_ROTATE_LOGFILE
735                 case 's':
736                         logFileSize = atoi(optarg) * 1024;
737                         break;
738                 case 'b':
739                         logFileRotate = atoi(optarg);
740                         if( logFileRotate > 99 ) logFileRotate = 99;
741                         break;
742 #endif
743 #ifdef CONFIG_FEATURE_REMOTE_LOG
744                 case 'R':
745                         RemoteHost = bb_xstrdup(optarg);
746                         if ((p = strchr(RemoteHost, ':'))) {
747                                 RemotePort = atoi(p + 1);
748                                 *p = '\0';
749                         }
750                         doRemoteLog = TRUE;
751                         break;
752                 case 'L':
753                         local_logging = TRUE;
754                         break;
755 #endif
756 #ifdef CONFIG_FEATURE_IPC_SYSLOG
757                 case 'C':
758                         if (optarg) {
759                                 int buf_size = atoi(optarg);
760                                 if (buf_size >= 4) {
761                                         shm_size = buf_size * 1024;
762                                 }
763                         }
764                         circular_logging = TRUE;
765                         break;
766 #endif
767                 case 'S':
768                         small = true;
769                         break;
770 /*BRCM begin*/
771                 case 'l':
772                         localLogLevel = atoi(optarg);
773                         break;
774                 case 'r':
775                         remoteLogLevel = atoi(optarg);
776                         break; 
777 /*BRCM end*/
778                 default:
779                         bb_show_usage();
780                 }
781         }
782
783 #ifdef CONFIG_FEATURE_REMOTE_LOG
784         /* If they have not specified remote logging, then log locally */
785         if (doRemoteLog == FALSE)
786                 local_logging = TRUE;
787 #endif
788
789
790         /* Store away localhost's name before the fork */
791         gethostname(LocalHostName, sizeof(LocalHostName));
792         if ((p = strchr(LocalHostName, '.'))) {
793                 *p = '\0';
794         }
795
796         umask(0);
797
798         if (doFork == TRUE) {
799 #if defined(__uClinux__)
800                 vfork_daemon_rexec(0, 1, argc, argv, "-n");
801 #else /* __uClinux__ */
802                 if(daemon(0, 1) < 0)
803                         bb_perror_msg_and_die("daemon");
804 #endif /* __uClinux__ */
805         }
806         doSyslogd();
807
808         return EXIT_SUCCESS;
809 }
810
811 /*
812 Local Variables
813 c-file-style: "linux"
814 c-basic-offset: 4
815 tab-width: 4
816 End:
817 */