OSDN Git Service

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