source: MondoRescue/branches/stable/mindi-busybox/sysklogd/syslogd.c

Last change on this file was 1770, checked in by Bruno Cornec, 12 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File size: 15.9 KB
Line 
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 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
14 */
15
16#include "libbb.h"
17#include <paths.h>
18#include <sys/un.h>
19
20/* SYSLOG_NAMES defined to pull prioritynames[] and facilitynames[]
21 * from syslog.h. Grrrr - glibc puts those in _rwdata_! :( */
22#define SYSLOG_NAMES
23#define SYSLOG_NAMES_CONST /* uclibc is saner :) */
24#include <sys/syslog.h>
25#include <sys/uio.h>
26
27#if ENABLE_FEATURE_REMOTE_LOG
28#include <netinet/in.h>
29#endif
30
31#if ENABLE_FEATURE_IPC_SYSLOG
32#include <sys/ipc.h>
33#include <sys/sem.h>
34#include <sys/shm.h>
35#endif
36
37
38#define DEBUG 0
39
40/* MARK code is not very useful, is bloat, and broken:
41 * can deadlock if alarmed to make MARK while writing to IPC buffer
42 * (semaphores are down but do_mark routine tries to down them again) */
43#undef SYSLOGD_MARK
44
45enum { MAX_READ = 256 };
46
47/* Semaphore operation structures */
48struct shbuf_ds {
49    int32_t size;   /* size of data - 1 */
50    int32_t tail;   /* end of message list */
51    char data[1];   /* data/messages */
52};
53
54/* Allows us to have smaller initializer. Ugly. */
55#define GLOBALS \
56    const char *logFilePath;                \
57    int logFD;                              \
58    /* interval between marks in seconds */ \
59    /*int markInterval;*/                   \
60    /* level of messages to be logged */    \
61    int logLevel;                           \
62USE_FEATURE_ROTATE_LOGFILE( \
63    /* max size of file before rotation */  \
64    unsigned logFileSize;                   \
65    /* number of rotated message files */   \
66    unsigned logFileRotate;                 \
67    unsigned curFileSize;                   \
68    smallint isRegular;                     \
69) \
70USE_FEATURE_REMOTE_LOG( \
71    /* udp socket for remote logging */     \
72    int remoteFD;                           \
73    len_and_sockaddr* remoteAddr;           \
74) \
75USE_FEATURE_IPC_SYSLOG( \
76    int shmid; /* ipc shared memory id */   \
77    int s_semid; /* ipc semaphore id */     \
78    int shm_size;                           \
79    struct sembuf SMwup[1];                 \
80    struct sembuf SMwdn[3];                 \
81)
82
83struct init_globals {
84    GLOBALS
85};
86
87struct globals {
88    GLOBALS
89#if ENABLE_FEATURE_IPC_SYSLOG
90    struct shbuf_ds *shbuf;
91#endif
92    time_t last_log_time;
93    /* localhost's name */
94    char localHostName[64];
95
96    /* We recv into recvbuf... */
97    char recvbuf[MAX_READ];
98    /* ...then copy to parsebuf, escaping control chars */
99    /* (can grow x2 max) */
100    char parsebuf[MAX_READ*2];
101    /* ...then sprintf into printbuf, adding timestamp (15 chars),
102     * host (64), fac.prio (20) to the message */
103    /* (growth by: 15 + 64 + 20 + delims = ~110) */
104    char printbuf[MAX_READ*2 + 128];
105};
106
107static const struct init_globals init_data = {
108    .logFilePath = "/var/log/messages",
109    .logFD = -1,
110#ifdef SYSLOGD_MARK
111    .markInterval = 20 * 60,
112#endif
113    .logLevel = 8,
114#if ENABLE_FEATURE_ROTATE_LOGFILE
115    .logFileSize = 200 * 1024,
116    .logFileRotate = 1,
117#endif
118#if ENABLE_FEATURE_REMOTE_LOG
119    .remoteFD = -1,
120#endif
121#if ENABLE_FEATURE_IPC_SYSLOG
122    .shmid = -1,
123    .s_semid = -1,
124    .shm_size = ((CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE)*1024), // default shm size
125    .SMwup = { {1, -1, IPC_NOWAIT} },
126    .SMwdn = { {0, 0}, {1, 0}, {1, +1} },
127#endif
128};
129
130#define G (*ptr_to_globals)
131
132
133/* Options */
134enum {
135    OPTBIT_mark = 0, // -m
136    OPTBIT_nofork, // -n
137    OPTBIT_outfile, // -O
138    OPTBIT_loglevel, // -l
139    OPTBIT_small, // -S
140    USE_FEATURE_ROTATE_LOGFILE(OPTBIT_filesize   ,) // -s
141    USE_FEATURE_ROTATE_LOGFILE(OPTBIT_rotatecnt  ,) // -b
142    USE_FEATURE_REMOTE_LOG(    OPTBIT_remote     ,) // -R
143    USE_FEATURE_REMOTE_LOG(    OPTBIT_localtoo   ,) // -L
144    USE_FEATURE_IPC_SYSLOG(    OPTBIT_circularlog,) // -C
145
146    OPT_mark        = 1 << OPTBIT_mark    ,
147    OPT_nofork      = 1 << OPTBIT_nofork  ,
148    OPT_outfile     = 1 << OPTBIT_outfile ,
149    OPT_loglevel    = 1 << OPTBIT_loglevel,
150    OPT_small       = 1 << OPTBIT_small   ,
151    OPT_filesize    = USE_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_filesize   )) + 0,
152    OPT_rotatecnt   = USE_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_rotatecnt  )) + 0,
153    OPT_remotelog   = USE_FEATURE_REMOTE_LOG(    (1 << OPTBIT_remote     )) + 0,
154    OPT_locallog    = USE_FEATURE_REMOTE_LOG(    (1 << OPTBIT_localtoo   )) + 0,
155    OPT_circularlog = USE_FEATURE_IPC_SYSLOG(    (1 << OPTBIT_circularlog)) + 0,
156};
157#define OPTION_STR "m:nO:l:S" \
158    USE_FEATURE_ROTATE_LOGFILE("s:" ) \
159    USE_FEATURE_ROTATE_LOGFILE("b:" ) \
160    USE_FEATURE_REMOTE_LOG(    "R:" ) \
161    USE_FEATURE_REMOTE_LOG(    "L"  ) \
162    USE_FEATURE_IPC_SYSLOG(    "C::")
163#define OPTION_DECL *opt_m, *opt_l \
164    USE_FEATURE_ROTATE_LOGFILE(,*opt_s) \
165    USE_FEATURE_ROTATE_LOGFILE(,*opt_b) \
166    USE_FEATURE_REMOTE_LOG(    ,*opt_R) \
167    USE_FEATURE_IPC_SYSLOG(    ,*opt_C = NULL)
168#define OPTION_PARAM &opt_m, &G.logFilePath, &opt_l \
169    USE_FEATURE_ROTATE_LOGFILE(,&opt_s) \
170    USE_FEATURE_ROTATE_LOGFILE(,&opt_b) \
171    USE_FEATURE_REMOTE_LOG(    ,&opt_R) \
172    USE_FEATURE_IPC_SYSLOG(    ,&opt_C)
173
174
175/* circular buffer variables/structures */
176#if ENABLE_FEATURE_IPC_SYSLOG
177
178#if CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE < 4
179#error Sorry, you must set the syslogd buffer size to at least 4KB.
180#error Please check CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE
181#endif
182
183/* our shared key */
184#define KEY_ID ((long)0x414e4547) /* "GENA" */
185
186static void ipcsyslog_cleanup(void)
187{
188    if (G.shmid != -1) {
189        shmdt(G.shbuf);
190    }
191    if (G.shmid != -1) {
192        shmctl(G.shmid, IPC_RMID, NULL);
193    }
194    if (G.s_semid != -1) {
195        semctl(G.s_semid, 0, IPC_RMID, 0);
196    }
197}
198
199static void ipcsyslog_init(void)
200{
201    if (DEBUG)
202        printf("shmget(%lx, %d,...)\n", KEY_ID, G.shm_size);
203
204    G.shmid = shmget(KEY_ID, G.shm_size, IPC_CREAT | 0644);
205    if (G.shmid == -1) {
206        bb_perror_msg_and_die("shmget");
207    }
208
209    G.shbuf = shmat(G.shmid, NULL, 0);
210    if (!G.shbuf) {
211        bb_perror_msg_and_die("shmat");
212    }
213
214    memset(G.shbuf, 0, G.shm_size);
215    G.shbuf->size = G.shm_size - offsetof(struct shbuf_ds, data) - 1;
216    /*G.shbuf->tail = 0;*/
217
218    // we'll trust the OS to set initial semval to 0 (let's hope)
219    G.s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023);
220    if (G.s_semid == -1) {
221        if (errno == EEXIST) {
222            G.s_semid = semget(KEY_ID, 2, 0);
223            if (G.s_semid != -1)
224                return;
225        }
226        bb_perror_msg_and_die("semget");
227    }
228}
229
230/* Write message to shared mem buffer */
231static void log_to_shmem(const char *msg, int len)
232{
233    int old_tail, new_tail;
234
235    if (semop(G.s_semid, G.SMwdn, 3) == -1) {
236        bb_perror_msg_and_die("SMwdn");
237    }
238
239    /* Circular Buffer Algorithm:
240     * --------------------------
241     * tail == position where to store next syslog message.
242     * tail's max value is (shbuf->size - 1)
243     * Last byte of buffer is never used and remains NUL.
244     */
245    len++; /* length with NUL included */
246 again:
247    old_tail = G.shbuf->tail;
248    new_tail = old_tail + len;
249    if (new_tail < G.shbuf->size) {
250        /* store message, set new tail */
251        memcpy(G.shbuf->data + old_tail, msg, len);
252        G.shbuf->tail = new_tail;
253    } else {
254        /* k == available buffer space ahead of old tail */
255        int k = G.shbuf->size - old_tail;
256        /* copy what fits to the end of buffer, and repeat */
257        memcpy(G.shbuf->data + old_tail, msg, k);
258        msg += k;
259        len -= k;
260        G.shbuf->tail = 0;
261        goto again;
262    }
263    if (semop(G.s_semid, G.SMwup, 1) == -1) {
264        bb_perror_msg_and_die("SMwup");
265    }
266    if (DEBUG)
267        printf("tail:%d\n", G.shbuf->tail);
268}
269#else
270void ipcsyslog_cleanup(void);
271void ipcsyslog_init(void);
272void log_to_shmem(const char *msg);
273#endif /* FEATURE_IPC_SYSLOG */
274
275
276/* Print a message to the log file. */
277static void log_locally(char *msg)
278{
279    struct flock fl;
280    int len = strlen(msg);
281
282#if ENABLE_FEATURE_IPC_SYSLOG
283    if ((option_mask32 & OPT_circularlog) && G.shbuf) {
284        log_to_shmem(msg, len);
285        return;
286    }
287#endif
288    if (G.logFD >= 0) {
289        time_t cur;
290        time(&cur);
291        if (G.last_log_time != cur) {
292            G.last_log_time = cur; /* reopen log file every second */
293            close(G.logFD);
294            goto reopen;
295        }
296    } else {
297 reopen:
298        G.logFD = device_open(G.logFilePath, O_WRONLY | O_CREAT
299                    | O_NOCTTY | O_APPEND | O_NONBLOCK);
300        if (G.logFD < 0) {
301            /* cannot open logfile? - print to /dev/console then */
302            int fd = device_open(_PATH_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK);
303            if (fd < 0)
304                fd = 2; /* then stderr, dammit */
305            full_write(fd, msg, len);
306            if (fd != 2)
307                close(fd);
308            return;
309        }
310#if ENABLE_FEATURE_ROTATE_LOGFILE
311        {
312            struct stat statf;
313            G.isRegular = (fstat(G.logFD, &statf) == 0 && S_ISREG(statf.st_mode));
314            /* bug (mostly harmless): can wrap around if file > 4gb */
315            G.curFileSize = statf.st_size;
316        }
317#endif
318    }
319
320    fl.l_whence = SEEK_SET;
321    fl.l_start = 0;
322    fl.l_len = 1;
323    fl.l_type = F_WRLCK;
324    fcntl(G.logFD, F_SETLKW, &fl);
325
326#if ENABLE_FEATURE_ROTATE_LOGFILE
327    if (G.logFileSize && G.isRegular && G.curFileSize > G.logFileSize) {
328        if (G.logFileRotate) { /* always 0..99 */
329            int i = strlen(G.logFilePath) + 3 + 1;
330            char oldFile[i];
331            char newFile[i];
332            i = G.logFileRotate - 1;
333            /* rename: f.8 -> f.9; f.7 -> f.8; ... */
334            while (1) {
335                sprintf(newFile, "%s.%d", G.logFilePath, i);
336                if (i == 0) break;
337                sprintf(oldFile, "%s.%d", G.logFilePath, --i);
338                rename(oldFile, newFile);
339            }
340            /* newFile == "f.0" now */
341            rename(G.logFilePath, newFile);
342            fl.l_type = F_UNLCK;
343            fcntl(G.logFD, F_SETLKW, &fl);
344            close(G.logFD);
345            goto reopen;
346        }
347        ftruncate(G.logFD, 0);
348    }
349    G.curFileSize +=
350#endif
351                    full_write(G.logFD, msg, len);
352    fl.l_type = F_UNLCK;
353    fcntl(G.logFD, F_SETLKW, &fl);
354}
355
356static void parse_fac_prio_20(int pri, char *res20)
357{
358    const CODE *c_pri, *c_fac;
359
360    if (pri != 0) {
361        c_fac = facilitynames;
362        while (c_fac->c_name) {
363            if (c_fac->c_val != (LOG_FAC(pri) << 3)) {
364                c_fac++; continue;
365            }
366            /* facility is found, look for prio */
367            c_pri = prioritynames;
368            while (c_pri->c_name) {
369                if (c_pri->c_val != LOG_PRI(pri)) {
370                    c_pri++; continue;
371                }
372                snprintf(res20, 20, "%s.%s",
373                        c_fac->c_name, c_pri->c_name);
374                return;
375            }
376            /* prio not found, bail out */
377            break;
378        }
379        snprintf(res20, 20, "<%d>", pri);
380    }
381}
382
383/* len parameter is used only for "is there a timestamp?" check.
384 * NB: some callers cheat and supply 0 when they know
385 * that there is no timestamp, short-cutting the test. */
386static void timestamp_and_log(int pri, char *msg, int len)
387{
388    char *timestamp;
389
390    if (len < 16 || msg[3] != ' ' || msg[6] != ' '
391     || msg[9] != ':' || msg[12] != ':' || msg[15] != ' '
392    ) {
393        time_t now;
394        time(&now);
395        timestamp = ctime(&now) + 4;
396    } else {
397        timestamp = msg;
398        msg += 16;
399    }
400    timestamp[15] = '\0';
401
402    /* Log message locally (to file or shared mem) */
403    if (!ENABLE_FEATURE_REMOTE_LOG || (option_mask32 & OPT_locallog)) {
404        if (LOG_PRI(pri) < G.logLevel) {
405            if (option_mask32 & OPT_small)
406                sprintf(G.printbuf, "%s %s\n", timestamp, msg);
407            else {
408                char res[20];
409                parse_fac_prio_20(pri, res);
410                sprintf(G.printbuf, "%s %s %s %s\n", timestamp, G.localHostName, res, msg);
411            }
412            log_locally(G.printbuf);
413        }
414    }
415}
416
417static void split_escape_and_log(char *tmpbuf, int len)
418{
419    char *p = tmpbuf;
420
421    tmpbuf += len;
422    while (p < tmpbuf) {
423        char c;
424        char *q = G.parsebuf;
425        int pri = (LOG_USER | LOG_NOTICE);
426
427        if (*p == '<') {
428            /* Parse the magic priority number */
429            pri = bb_strtou(p + 1, &p, 10);
430            if (*p == '>') p++;
431            if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) {
432                pri = (LOG_USER | LOG_NOTICE);
433            }
434        }
435
436        while ((c = *p++)) {
437            if (c == '\n')
438                c = ' ';
439            if (!(c & ~0x1f) && c != '\t') {
440                *q++ = '^';
441                c += '@'; /* ^@, ^A, ^B... */
442            }
443            *q++ = c;
444        }
445        *q = '\0';
446        /* Now log it */
447        timestamp_and_log(pri, G.parsebuf, q - G.parsebuf);
448    }
449}
450
451static void quit_signal(int sig)
452{
453    timestamp_and_log(LOG_SYSLOG | LOG_INFO, (char*)"syslogd exiting", 0);
454    puts("syslogd exiting");
455    if (ENABLE_FEATURE_IPC_SYSLOG)
456        ipcsyslog_cleanup();
457    exit(1);
458}
459
460#ifdef SYSLOGD_MARK
461static void do_mark(int sig)
462{
463    if (G.markInterval) {
464        timestamp_and_log(LOG_SYSLOG | LOG_INFO, (char*)"-- MARK --", 0);
465        alarm(G.markInterval);
466    }
467}
468#endif
469
470static void do_syslogd(void) ATTRIBUTE_NORETURN;
471static void do_syslogd(void)
472{
473    struct sockaddr_un sunx;
474    int sock_fd;
475    fd_set fds;
476    char *dev_log_name;
477
478    /* Set up signal handlers */
479    signal(SIGINT, quit_signal);
480    signal(SIGTERM, quit_signal);
481    signal(SIGQUIT, quit_signal);
482    signal(SIGHUP, SIG_IGN);
483    signal(SIGCHLD, SIG_IGN);
484#ifdef SIGCLD
485    signal(SIGCLD, SIG_IGN);
486#endif
487#ifdef SYSLOGD_MARK
488    signal(SIGALRM, do_mark);
489    alarm(G.markInterval);
490#endif
491    remove_pidfile("/var/run/syslogd.pid");
492
493    memset(&sunx, 0, sizeof(sunx));
494    sunx.sun_family = AF_UNIX;
495    strcpy(sunx.sun_path, "/dev/log");
496
497    /* Unlink old /dev/log or object it points to. */
498    /* (if it exists, bind will fail) */
499    logmode = LOGMODE_NONE;
500    dev_log_name = xmalloc_readlink_or_warn("/dev/log");
501    logmode = LOGMODE_STDIO;
502    if (dev_log_name) {
503        int fd = xopen(".", O_NONBLOCK);
504        xchdir("/dev");
505        /* we do not check whether this is a link also */
506        unlink(dev_log_name);
507        fchdir(fd);
508        close(fd);
509        safe_strncpy(sunx.sun_path, dev_log_name, sizeof(sunx.sun_path));
510        free(dev_log_name);
511    } else {
512        unlink("/dev/log");
513    }
514
515    sock_fd = xsocket(AF_UNIX, SOCK_DGRAM, 0);
516    xbind(sock_fd, (struct sockaddr *) &sunx, sizeof(sunx));
517
518    if (chmod("/dev/log", 0666) < 0) {
519        bb_perror_msg_and_die("cannot set permission on /dev/log");
520    }
521    if (ENABLE_FEATURE_IPC_SYSLOG && (option_mask32 & OPT_circularlog)) {
522        ipcsyslog_init();
523    }
524
525    timestamp_and_log(LOG_SYSLOG | LOG_INFO,
526            (char*)"syslogd started: BusyBox v" BB_VER, 0);
527
528    for (;;) {
529        FD_ZERO(&fds);
530        FD_SET(sock_fd, &fds);
531
532        if (select(sock_fd + 1, &fds, NULL, NULL, NULL) < 0) {
533            if (errno == EINTR) {
534                /* alarm may have happened */
535                continue;
536            }
537            bb_perror_msg_and_die("select");
538        }
539
540        if (FD_ISSET(sock_fd, &fds)) {
541            int i;
542            i = recv(sock_fd, G.recvbuf, MAX_READ - 1, 0);
543            if (i <= 0)
544                bb_perror_msg_and_die("UNIX socket error");
545            /* TODO: maybe suppress duplicates? */
546#if ENABLE_FEATURE_REMOTE_LOG
547            /* We are not modifying log messages in any way before send */
548            /* Remote site cannot trust _us_ anyway and need to do validation again */
549            if (G.remoteAddr) {
550                if (-1 == G.remoteFD) {
551                    G.remoteFD = socket(G.remoteAddr->sa.sa_family, SOCK_DGRAM, 0);
552                }
553                if (-1 != G.remoteFD) {
554                    /* send message to remote logger, ignore possible error */
555                    sendto(G.remoteFD, G.recvbuf, i, MSG_DONTWAIT,
556                        &G.remoteAddr->sa, G.remoteAddr->len);
557                }
558            }
559#endif
560            G.recvbuf[i] = '\0';
561            split_escape_and_log(G.recvbuf, i);
562        } /* FD_ISSET() */
563    } /* for */
564}
565
566int syslogd_main(int argc, char **argv);
567int syslogd_main(int argc, char **argv)
568{
569    char OPTION_DECL;
570    char *p;
571
572    PTR_TO_GLOBALS = memcpy(xzalloc(sizeof(G)), &init_data, sizeof(init_data));
573
574    /* do normal option parsing */
575    opt_complementary = "=0"; /* no non-option params */
576    getopt32(argv, OPTION_STR, OPTION_PARAM);
577#ifdef SYSLOGD_MARK
578    if (option_mask32 & OPT_mark) // -m
579        G.markInterval = xatou_range(opt_m, 0, INT_MAX/60) * 60;
580#endif
581    //if (option_mask32 & OPT_nofork) // -n
582    //if (option_mask32 & OPT_outfile) // -O
583    if (option_mask32 & OPT_loglevel) // -l
584        G.logLevel = xatou_range(opt_l, 1, 8);
585    //if (option_mask32 & OPT_small) // -S
586#if ENABLE_FEATURE_ROTATE_LOGFILE
587    if (option_mask32 & OPT_filesize) // -s
588        G.logFileSize = xatou_range(opt_s, 0, INT_MAX/1024) * 1024;
589    if (option_mask32 & OPT_rotatecnt) // -b
590        G.logFileRotate = xatou_range(opt_b, 0, 99);
591#endif
592#if ENABLE_FEATURE_REMOTE_LOG
593    if (option_mask32 & OPT_remotelog) { // -R
594        G.remoteAddr = xhost2sockaddr(opt_R, 514);
595    }
596    //if (option_mask32 & OPT_locallog) // -L
597#endif
598#if ENABLE_FEATURE_IPC_SYSLOG
599    if (opt_C) // -Cn
600        G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024;
601#endif
602
603    /* If they have not specified remote logging, then log locally */
604    if (ENABLE_FEATURE_REMOTE_LOG && !(option_mask32 & OPT_remotelog))
605        option_mask32 |= OPT_locallog;
606
607    /* Store away localhost's name before the fork */
608    gethostname(G.localHostName, sizeof(G.localHostName));
609    p = strchr(G.localHostName, '.');
610    if (p) {
611        *p = '\0';
612    }
613
614    if (!(option_mask32 & OPT_nofork)) {
615        bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
616    }
617    umask(0);
618    write_pidfile("/var/run/syslogd.pid");
619    do_syslogd();
620    /* return EXIT_SUCCESS; */
621}
Note: See TracBrowser for help on using the repository browser.