summaryrefslogtreecommitdiff
path: root/busybox/sysklogd
diff options
context:
space:
mode:
authornobody <nobody@localhost>2004-10-13 09:42:10 +0000
committernobody <nobody@localhost>2004-10-13 09:42:10 +0000
commit8c59a0bf0e9e2d87b0ff273ea3f0bf05bbbf6373 (patch)
tree1826706cd4fd009fcd14f4f8021005ec8ec0fa59 /busybox/sysklogd
downloadbusybox-w32-8c59a0bf0e9e2d87b0ff273ea3f0bf05bbbf6373.tar.gz
busybox-w32-8c59a0bf0e9e2d87b0ff273ea3f0bf05bbbf6373.tar.bz2
busybox-w32-8c59a0bf0e9e2d87b0ff273ea3f0bf05bbbf6373.zip
This commit was manufactured by cvs2svn to create tag 'busybox_1_00'.
Diffstat (limited to 'busybox/sysklogd')
-rw-r--r--busybox/sysklogd/Config.in109
-rw-r--r--busybox/sysklogd/Makefile32
-rw-r--r--busybox/sysklogd/Makefile.in39
-rw-r--r--busybox/sysklogd/klogd.c165
-rw-r--r--busybox/sysklogd/logger.c204
-rw-r--r--busybox/sysklogd/logread.c186
-rw-r--r--busybox/sysklogd/syslogd.c712
7 files changed, 1447 insertions, 0 deletions
diff --git a/busybox/sysklogd/Config.in b/busybox/sysklogd/Config.in
new file mode 100644
index 000000000..f77d79e8c
--- /dev/null
+++ b/busybox/sysklogd/Config.in
@@ -0,0 +1,109 @@
1#
2# For a description of the syntax of this configuration file,
3# see scripts/kbuild/config-language.txt.
4#
5
6menu "System Logging Utilities"
7
8config CONFIG_SYSLOGD
9 bool "syslogd"
10 default n
11 help
12 The syslogd utility is used to record logs of all the
13 significant events that occur on a system. Every
14 message that is logged records the date and time of the
15 event, and will generally also record the name of the
16 application that generated the message. When used in
17 conjunction with klogd, messages from the Linux kernel
18 can also be recorded. This is terribly useful,
19 especially for finding what happened when something goes
20 wrong. And something almost always will go wrong if
21 you wait long enough....
22
23config CONFIG_FEATURE_ROTATE_LOGFILE
24 bool " Rotate message files"
25 default n
26 depends on CONFIG_SYSLOGD
27 help
28 This enables syslogd to rotate the message files
29 on his own. No need to use an external rotatescript.
30
31config CONFIG_FEATURE_REMOTE_LOG
32 bool " Remote Log support"
33 default n
34 depends on CONFIG_SYSLOGD
35 help
36 When you enable this feature, the syslogd utility can
37 be used to send system log messages to another system
38 connected via a network. This allows the remote
39 machine to log all the system messages, which can be
40 terribly useful for reducing the number of serial
41 cables you use. It can also be a very good security
42 measure to prevent system logs from being tampered with
43 by an intruder.
44
45config CONFIG_FEATURE_IPC_SYSLOG
46 bool " Circular Buffer support"
47 default n
48 depends on CONFIG_SYSLOGD
49 help
50 When you enable this feature, the syslogd utility will
51 use a circular buffer to record system log messages.
52 When the buffer is filled it will continue to overwrite
53 the oldest messages. This can be very useful for
54 systems with little or no permanent storage, since
55 otherwise system logs can eventually fill up your
56 entire filesystem, which may cause your system to
57 break badly.
58
59config CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE
60 int " Circular buffer size in Kbytes (minimum 4KB)"
61 default 16
62 depends on CONFIG_FEATURE_IPC_SYSLOG
63 help
64 This option sets the size of the circular buffer
65 used to record system log messages.
66
67config CONFIG_LOGREAD
68 bool " logread"
69 default y
70 depends on CONFIG_FEATURE_IPC_SYSLOG
71 help
72 If you enabled Circular Buffer support, you almost
73 certainly want to enable this feature as well. This
74 utility will allow you to read the messages that are
75 stored in the syslogd circular buffer.
76
77config CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
78 bool " logread double buffering"
79 default n
80 depends on CONFIG_LOGREAD
81 help
82 'logread' ouput to slow serial terminals can have
83 side effects on syslog because of the semaphore.
84 This option make logread to double buffer copy
85 from circular buffer, minimizing semaphore
86 contention at some minor memory expense.
87
88config CONFIG_KLOGD
89 bool "klogd"
90 default n
91 depends on CONFIG_SYSLOGD
92 help
93 klogd is a utility which intercepts and logs all
94 messages from the Linux kernel and sends the messages
95 out to the 'syslogd' utility so they can be logged. If
96 you wish to record the messages produced by the kernel,
97 you should enable this option.
98
99config CONFIG_LOGGER
100 bool "logger"
101 default n
102 help
103 The logger utility allows you to send arbitrary text
104 messages to the system log (i.e. the 'syslogd' utility) so
105 they can be logged. This is generally used to help locate
106 problems that occur within programs and scripts.
107
108endmenu
109
diff --git a/busybox/sysklogd/Makefile b/busybox/sysklogd/Makefile
new file mode 100644
index 000000000..78b0c0090
--- /dev/null
+++ b/busybox/sysklogd/Makefile
@@ -0,0 +1,32 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#
19
20top_srcdir=..
21top_buildddir=..
22srcdir=$(top_srcdir)/sysklogd
23SYSKLOGD_DIR:=./
24include $(top_builddir)/Rules.mak
25include $(top_builddir)/.config
26include Makefile.in
27all: $(libraries-y)
28-include $(top_builddir)/.depend
29
30clean:
31 rm -f *.o *.a $(AR_TARGET)
32
diff --git a/busybox/sysklogd/Makefile.in b/busybox/sysklogd/Makefile.in
new file mode 100644
index 000000000..99a5f823c
--- /dev/null
+++ b/busybox/sysklogd/Makefile.in
@@ -0,0 +1,39 @@
1# Makefile for busybox
2#
3# Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13# General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18#
19
20SYSKLOGD_AR:=sysklogd.a
21ifndef $(SYSKLOGD_DIR)
22SYSKLOGD_DIR:=$(top_builddir)/sysklogd/
23endif
24srcdir=$(top_srcdir)/sysklogd
25
26SYSKLOGD-:=
27SYSKLOGD-$(CONFIG_KLOGD) += klogd.o
28SYSKLOGD-$(CONFIG_LOGGER) += logger.o
29SYSKLOGD-$(CONFIG_LOGREAD) += logread.o
30SYSKLOGD-$(CONFIG_SYSLOGD) += syslogd.o
31
32libraries-y+=$(SYSKLOGD_DIR)$(SYSKLOGD_AR)
33
34$(SYSKLOGD_DIR)$(SYSKLOGD_AR): $(patsubst %,$(SYSKLOGD_DIR)%, $(SYSKLOGD-y))
35 $(AR) -ro $@ $(patsubst %,$(SYSKLOGD_DIR)%, $(SYSKLOGD-y))
36
37$(SYSKLOGD_DIR)%.o: $(srcdir)/%.c
38 $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
39
diff --git a/busybox/sysklogd/klogd.c b/busybox/sysklogd/klogd.c
new file mode 100644
index 000000000..c908b593c
--- /dev/null
+++ b/busybox/sysklogd/klogd.c
@@ -0,0 +1,165 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini klogd implementation for busybox
4 *
5 * Copyright (C) 2001 by Gennady Feldman <gfeldman@gena01.com>.
6 * Changes: Made this a standalone busybox module which uses standalone
7 * syslog() client interface.
8 *
9 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
10 *
11 * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org>
12 *
13 * "circular buffer" Copyright (C) 2000 by Gennady Feldman <gfeldman@gena01.com>
14 *
15 * Maintainer: Gennady Feldman <gfeldman@gena01.com> as of Mar 12, 2001
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 *
31 */
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <signal.h> /* for our signal() handlers */
36#include <string.h> /* strncpy() */
37#include <errno.h> /* errno and friends */
38#include <unistd.h>
39#include <ctype.h>
40#include <sys/syslog.h>
41#include <sys/klog.h>
42
43#include "busybox.h"
44
45static void klogd_signal(int sig)
46{
47 klogctl(7, NULL, 0);
48 klogctl(0, 0, 0);
49 /* logMessage(0, "Kernel log daemon exiting."); */
50 syslog(LOG_NOTICE, "Kernel log daemon exiting.");
51 exit(EXIT_SUCCESS);
52}
53
54static void doKlogd(const int console_log_level) __attribute__ ((noreturn));
55static void doKlogd(const int console_log_level)
56{
57 int priority = LOG_INFO;
58 char log_buffer[4096];
59 int i, n, lastc;
60 char *start;
61
62 openlog("kernel", 0, LOG_KERN);
63
64 /* Set up sig handlers */
65 signal(SIGINT, klogd_signal);
66 signal(SIGKILL, klogd_signal);
67 signal(SIGTERM, klogd_signal);
68 signal(SIGHUP, SIG_IGN);
69
70 /* "Open the log. Currently a NOP." */
71 klogctl(1, NULL, 0);
72
73 /* Set level of kernel console messaging.. */
74 if (console_log_level != -1)
75 klogctl(8, NULL, console_log_level);
76
77 syslog(LOG_NOTICE, "klogd started: " BB_BANNER);
78
79 while (1) {
80 /* Use kernel syscalls */
81 memset(log_buffer, '\0', sizeof(log_buffer));
82 n = klogctl(2, log_buffer, sizeof(log_buffer));
83 if (n < 0) {
84 if (errno == EINTR)
85 continue;
86 syslog(LOG_ERR, "klogd: Error return from sys_sycall: %d - %m.\n", errno);
87 exit(EXIT_FAILURE);
88 }
89
90 /* klogctl buffer parsing modelled after code in dmesg.c */
91 start = &log_buffer[0];
92 lastc = '\0';
93 for (i = 0; i < n; i++) {
94 if (lastc == '\0' && log_buffer[i] == '<') {
95 priority = 0;
96 i++;
97 while (isdigit(log_buffer[i])) {
98 priority = priority * 10 + (log_buffer[i] - '0');
99 i++;
100 }
101 if (log_buffer[i] == '>')
102 i++;
103 start = &log_buffer[i];
104 }
105 if (log_buffer[i] == '\n') {
106 log_buffer[i] = '\0'; /* zero terminate this message */
107 syslog(priority, "%s", start);
108 start = &log_buffer[i + 1];
109 priority = LOG_INFO;
110 }
111 lastc = log_buffer[i];
112 }
113 }
114}
115
116extern int klogd_main(int argc, char **argv)
117{
118 /* no options, no getopt */
119 int opt;
120 int doFork = TRUE;
121 unsigned char console_log_level = -1;
122
123 /* do normal option parsing */
124 while ((opt = getopt(argc, argv, "c:n")) > 0) {
125 switch (opt) {
126 case 'c':
127 if ((optarg == NULL) || (optarg[1] != '\0')) {
128 bb_show_usage();
129 }
130 /* Valid levels are between 1 and 8 */
131 console_log_level = *optarg - '1';
132 if (console_log_level > 7) {
133 bb_show_usage();
134 }
135 console_log_level++;
136
137 break;
138 case 'n':
139 doFork = FALSE;
140 break;
141 default:
142 bb_show_usage();
143 }
144 }
145
146 if (doFork) {
147#if defined(__uClinux__)
148 vfork_daemon_rexec(0, 1, argc, argv, "-n");
149#else /* __uClinux__ */
150 if (daemon(0, 1) < 0)
151 bb_perror_msg_and_die("daemon");
152#endif /* __uClinux__ */
153 }
154 doKlogd(console_log_level);
155
156 return EXIT_SUCCESS;
157}
158
159/*
160Local Variables
161c-file-style: "linux"
162c-basic-offset: 4
163tab-width: 4
164End:
165*/
diff --git a/busybox/sysklogd/logger.c b/busybox/sysklogd/logger.c
new file mode 100644
index 000000000..16155316f
--- /dev/null
+++ b/busybox/sysklogd/logger.c
@@ -0,0 +1,204 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini logger implementation for busybox
4 *
5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
23#include <stdio.h>
24#include <unistd.h>
25#include <sys/types.h>
26#include <fcntl.h>
27#include <ctype.h>
28#include <string.h>
29#include <stdlib.h>
30
31#include "busybox.h"
32#if !defined CONFIG_SYSLOGD
33
34#define SYSLOG_NAMES
35#include <sys/syslog.h>
36
37#else
38#include <sys/syslog.h>
39# ifndef __dietlibc__
40 /* We have to do this since the header file defines static
41 * structures. Argh.... bad libc, bad, bad...
42 */
43 typedef struct _code {
44 char *c_name;
45 int c_val;
46 } CODE;
47 extern CODE prioritynames[];
48 extern CODE facilitynames[];
49# endif
50#endif
51
52/* Decode a symbolic name to a numeric value
53 * this function is based on code
54 * Copyright (c) 1983, 1993
55 * The Regents of the University of California. All rights reserved.
56 *
57 * Original copyright notice is retained at the end of this file.
58 */
59static int decode(char *name, CODE * codetab)
60{
61 CODE *c;
62
63 if (isdigit(*name))
64 return (atoi(name));
65 for (c = codetab; c->c_name; c++) {
66 if (!strcasecmp(name, c->c_name)) {
67 return (c->c_val);
68 }
69 }
70
71 return (-1);
72}
73
74/* Decode a symbolic name to a numeric value
75 * this function is based on code
76 * Copyright (c) 1983, 1993
77 * The Regents of the University of California. All rights reserved.
78 *
79 * Original copyright notice is retained at the end of this file.
80 */
81static int pencode(char *s)
82{
83 char *save;
84 int lev, fac = LOG_USER;
85
86 for (save = s; *s && *s != '.'; ++s);
87 if (*s) {
88 *s = '\0';
89 fac = decode(save, facilitynames);
90 if (fac < 0)
91 bb_error_msg_and_die("unknown facility name: %s", save);
92 *s++ = '.';
93 } else {
94 s = save;
95 }
96 lev = decode(s, prioritynames);
97 if (lev < 0)
98 bb_error_msg_and_die("unknown priority name: %s", save);
99 return ((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
100}
101
102
103extern int logger_main(int argc, char **argv)
104{
105 int pri = LOG_USER | LOG_NOTICE;
106 int option = 0;
107 int c, i, opt;
108 char buf[1024], name[128];
109
110 /* Fill out the name string early (may be overwritten later) */
111 my_getpwuid(name, geteuid(), sizeof(name));
112
113 /* Parse any options */
114 while ((opt = getopt(argc, argv, "p:st:")) > 0) {
115 switch (opt) {
116 case 's':
117 option |= LOG_PERROR;
118 break;
119 case 'p':
120 pri = pencode(optarg);
121 break;
122 case 't':
123 safe_strncpy(name, optarg, sizeof(name));
124 break;
125 default:
126 bb_show_usage();
127 }
128 }
129
130 openlog(name, option, (pri | LOG_FACMASK));
131 if (optind == argc) {
132 do {
133 /* read from stdin */
134 i = 0;
135 while ((c = getc(stdin)) != EOF && c != '\n' &&
136 i < (sizeof(buf)-1)) {
137 buf[i++] = c;
138 }
139 if (i > 0) {
140 buf[i++] = '\0';
141 syslog(pri, "%s", buf);
142 }
143 } while (c != EOF);
144 } else {
145 char *message = NULL;
146 int len = argc - optind; /* for the space between the args
147 and '\0' */
148 opt = len;
149 argv += optind;
150 for (i = 0; i < opt; i++) {
151 len += strlen(*argv);
152 message = xrealloc(message, len);
153 if(!i)
154 message[0] = 0;
155 else
156 strcat(message, " ");
157 strcat(message, *argv);
158 argv++;
159 }
160 syslog(pri, "%s", message);
161 }
162
163 closelog();
164 return EXIT_SUCCESS;
165}
166
167
168/*-
169 * Copyright (c) 1983, 1993
170 * The Regents of the University of California. All rights reserved.
171 *
172 * This is the original license statement for the decode and pencode functions.
173 *
174 * Redistribution and use in source and binary forms, with or without
175 * modification, are permitted provided that the following conditions
176 * are met:
177 * 1. Redistributions of source code must retain the above copyright
178 * notice, this list of conditions and the following disclaimer.
179 * 2. Redistributions in binary form must reproduce the above copyright
180 * notice, this list of conditions and the following disclaimer in the
181 * documentation and/or other materials provided with the distribution.
182 *
183 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
184 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
185 *
186 * 4. Neither the name of the University nor the names of its contributors
187 * may be used to endorse or promote products derived from this software
188 * without specific prior written permission.
189 *
190 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
191 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
192 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
193 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
194 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
195 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
196 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
197 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
198 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
199 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
200 * SUCH DAMAGE.
201 */
202
203
204
diff --git a/busybox/sysklogd/logread.c b/busybox/sysklogd/logread.c
new file mode 100644
index 000000000..70d1db631
--- /dev/null
+++ b/busybox/sysklogd/logread.c
@@ -0,0 +1,186 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * circular buffer syslog implementation for busybox
4 *
5 * Copyright (C) 2000 by Gennady Feldman <gfeldman@gena01.com>
6 *
7 * Maintainer: Gennady Feldman <gfeldman@gena01.com> as of Mar 12, 2001
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 * 02111-1307 USA
23 *
24 */
25
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <sys/ipc.h>
31#include <sys/types.h>
32#include <sys/sem.h>
33#include <sys/shm.h>
34#include <signal.h>
35#include <setjmp.h>
36#include <unistd.h>
37#include "busybox.h"
38
39static const long KEY_ID = 0x414e4547; /*"GENA"*/
40
41static struct shbuf_ds {
42 int size; // size of data written
43 int head; // start of message list
44 int tail; // end of message list
45 char data[1]; // data/messages
46} *buf = NULL; // shared memory pointer
47
48
49// Semaphore operation structures
50static struct sembuf SMrup[1] = {{0, -1, IPC_NOWAIT | SEM_UNDO}}; // set SMrup
51static struct sembuf SMrdn[2] = {{1, 0}, {0, +1, SEM_UNDO}}; // set SMrdn
52
53static int log_shmid = -1; // ipc shared memory id
54static int log_semid = -1; // ipc semaphore id
55static jmp_buf jmp_env;
56
57static void error_exit(const char *str);
58static void interrupted(int sig);
59
60/*
61 * sem_up - up()'s a semaphore.
62 */
63static inline void sem_up(int semid)
64{
65 if ( semop(semid, SMrup, 1) == -1 )
66 error_exit("semop[SMrup]");
67}
68
69/*
70 * sem_down - down()'s a semaphore
71 */
72static inline void sem_down(int semid)
73{
74 if ( semop(semid, SMrdn, 2) == -1 )
75 error_exit("semop[SMrdn]");
76}
77
78extern int logread_main(int argc, char **argv)
79{
80 int i;
81 int follow=0;
82
83 if (argc == 2 && strcmp(argv[1],"-f")==0) {
84 follow = 1;
85 } else {
86 /* no options, no getopt */
87 if (argc > 1)
88 bb_show_usage();
89 }
90
91 // handle intrrupt signal
92 if (setjmp(jmp_env)) goto output_end;
93
94 // attempt to redefine ^C signal
95 signal(SIGINT, interrupted);
96
97 if ( (log_shmid = shmget(KEY_ID, 0, 0)) == -1)
98 error_exit("Can't find circular buffer");
99
100 // Attach shared memory to our char*
101 if ( (buf = shmat(log_shmid, NULL, SHM_RDONLY)) == NULL)
102 error_exit("Can't get access to circular buffer from syslogd");
103
104 if ( (log_semid = semget(KEY_ID, 0, 0)) == -1)
105 error_exit("Can't get access to semaphone(s) for circular buffer from syslogd");
106
107 // Suppose atomic memory move
108 i = follow ? buf->tail : buf->head;
109
110 do {
111#ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
112 char *buf_data;
113 int log_len,j;
114#endif
115
116 sem_down(log_semid);
117
118 //printf("head: %i tail: %i size: %i\n",buf->head,buf->tail,buf->size);
119 if (buf->head == buf->tail || i==buf->tail) {
120 if (follow) {
121 sem_up(log_semid);
122 sleep(1); /* TODO: replace me with a sleep_on */
123 continue;
124 } else {
125 printf("<empty syslog>\n");
126 }
127 }
128
129 // Read Memory
130#ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
131 log_len = buf->tail - i;
132 if (log_len < 0)
133 log_len += buf->size;
134 buf_data = (char *)malloc(log_len);
135 if (!buf_data)
136 error_exit("malloc failed");
137
138 if (buf->tail < i) {
139 memcpy(buf_data, buf->data+i, buf->size-i);
140 memcpy(buf_data+buf->size-i, buf->data, buf->tail);
141 } else {
142 memcpy(buf_data, buf->data+i, buf->tail-i);
143 }
144 i = buf->tail;
145
146#else
147 while ( i != buf->tail) {
148 printf("%s", buf->data+i);
149 i+= strlen(buf->data+i) + 1;
150 if (i >= buf->size )
151 i=0;
152 }
153#endif
154 // release the lock on the log chain
155 sem_up(log_semid);
156
157#ifdef CONFIG_FEATURE_LOGREAD_REDUCED_LOCKING
158 for (j=0; j < log_len; j+=strlen(buf_data+j)+1) {
159 printf("%s", buf_data+j);
160 if (follow)
161 fflush(stdout);
162 }
163 free(buf_data);
164#endif
165 } while (follow);
166
167output_end:
168 if (log_shmid != -1)
169 shmdt(buf);
170
171 return EXIT_SUCCESS;
172}
173
174static void interrupted(int sig){
175 signal(SIGINT, SIG_IGN);
176 longjmp(jmp_env, 1);
177}
178
179static void error_exit(const char *str){
180 perror(str);
181 //release all acquired resources
182 if (log_shmid != -1)
183 shmdt(buf);
184
185 exit(1);
186}
diff --git a/busybox/sysklogd/syslogd.c b/busybox/sysklogd/syslogd.c
new file mode 100644
index 000000000..8c6c44ee0
--- /dev/null
+++ b/busybox/sysklogd/syslogd.c
@@ -0,0 +1,712 @@
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/* Path for the file where all log messages are written */
56#define __LOG_FILE "/var/log/messages"
57
58/* Path to the unix socket */
59static char lfile[MAXPATHLEN];
60
61static const char *logFilePath = __LOG_FILE;
62
63#ifdef CONFIG_FEATURE_ROTATE_LOGFILE
64/* max size of message file before being rotated */
65static int logFileSize = 200 * 1024;
66
67/* number of rotated message files */
68static int logFileRotate = 1;
69#endif
70
71/* interval between marks in seconds */
72static int MarkInterval = 20 * 60;
73
74/* localhost's name */
75static char LocalHostName[64];
76
77#ifdef CONFIG_FEATURE_REMOTE_LOG
78#include <netinet/in.h>
79/* udp socket for logging to remote host */
80static int remotefd = -1;
81static struct sockaddr_in remoteaddr;
82
83/* where do we log? */
84static char *RemoteHost;
85
86/* what port to log to? */
87static int RemotePort = 514;
88
89/* To remote log or not to remote log, that is the question. */
90static int doRemoteLog = FALSE;
91static int local_logging = FALSE;
92#endif
93
94/* Make loging output smaller. */
95static bool small = false;
96
97
98#define MAXLINE 1024 /* maximum line length */
99
100
101/* circular buffer variables/structures */
102#ifdef CONFIG_FEATURE_IPC_SYSLOG
103
104#if CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE < 4
105#error Sorry, you must set the syslogd buffer size to at least 4KB.
106#error Please check CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE
107#endif
108
109#include <sys/ipc.h>
110#include <sys/sem.h>
111#include <sys/shm.h>
112
113/* our shared key */
114static const long KEY_ID = 0x414e4547; /*"GENA" */
115
116// Semaphore operation structures
117static struct shbuf_ds {
118 int size; // size of data written
119 int head; // start of message list
120 int tail; // end of message list
121 char data[1]; // data/messages
122} *buf = NULL; // shared memory pointer
123
124static struct sembuf SMwup[1] = { {1, -1, IPC_NOWAIT} }; // set SMwup
125static struct sembuf SMwdn[3] = { {0, 0}, {1, 0}, {1, +1} }; // set SMwdn
126
127static int shmid = -1; // ipc shared memory id
128static int s_semid = -1; // ipc semaphore id
129static int shm_size = ((CONFIG_FEATURE_IPC_SYSLOG_BUFFER_SIZE)*1024); // default shm size
130static int circular_logging = FALSE;
131
132/*
133 * sem_up - up()'s a semaphore.
134 */
135static inline void sem_up(int semid)
136{
137 if (semop(semid, SMwup, 1) == -1) {
138 bb_perror_msg_and_die("semop[SMwup]");
139 }
140}
141
142/*
143 * sem_down - down()'s a semaphore
144 */
145static inline void sem_down(int semid)
146{
147 if (semop(semid, SMwdn, 3) == -1) {
148 bb_perror_msg_and_die("semop[SMwdn]");
149 }
150}
151
152
153void ipcsyslog_cleanup(void)
154{
155 printf("Exiting Syslogd!\n");
156 if (shmid != -1) {
157 shmdt(buf);
158 }
159
160 if (shmid != -1) {
161 shmctl(shmid, IPC_RMID, NULL);
162 }
163 if (s_semid != -1) {
164 semctl(s_semid, 0, IPC_RMID, 0);
165 }
166}
167
168void ipcsyslog_init(void)
169{
170 if (buf == NULL) {
171 if ((shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023)) == -1) {
172 bb_perror_msg_and_die("shmget");
173 }
174
175 if ((buf = shmat(shmid, NULL, 0)) == NULL) {
176 bb_perror_msg_and_die("shmat");
177 }
178
179 buf->size = shm_size - sizeof(*buf);
180 buf->head = buf->tail = 0;
181
182 // we'll trust the OS to set initial semval to 0 (let's hope)
183 if ((s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023)) == -1) {
184 if (errno == EEXIST) {
185 if ((s_semid = semget(KEY_ID, 2, 0)) == -1) {
186 bb_perror_msg_and_die("semget");
187 }
188 } else {
189 bb_perror_msg_and_die("semget");
190 }
191 }
192 } else {
193 printf("Buffer already allocated just grab the semaphore?");
194 }
195}
196
197/* write message to buffer */
198void circ_message(const char *msg)
199{
200 int l = strlen(msg) + 1; /* count the whole message w/ '\0' included */
201
202 sem_down(s_semid);
203
204 /*
205 * Circular Buffer Algorithm:
206 * --------------------------
207 *
208 * Start-off w/ empty buffer of specific size SHM_SIZ
209 * Start filling it up w/ messages. I use '\0' as separator to break up messages.
210 * This is also very handy since we can do printf on message.
211 *
212 * Once the buffer is full we need to get rid of the first message in buffer and
213 * insert the new message. (Note: if the message being added is >1 message then
214 * we will need to "remove" >1 old message from the buffer). The way this is done
215 * is the following:
216 * When we reach the end of the buffer we set a mark and start from the beginning.
217 * Now what about the beginning and end of the buffer? Well we have the "head"
218 * index/pointer which is the starting point for the messages and we have "tail"
219 * index/pointer which is the ending point for the messages. When we "display" the
220 * messages we start from the beginning and continue until we reach "tail". If we
221 * reach end of buffer, then we just start from the beginning (offset 0). "head" and
222 * "tail" are actually offsets from the beginning of the buffer.
223 *
224 * Note: This algorithm uses Linux IPC mechanism w/ shared memory and semaphores to provide
225 * a threasafe way of handling shared memory operations.
226 */
227 if ((buf->tail + l) < buf->size) {
228 /* before we append the message we need to check the HEAD so that we won't
229 overwrite any of the message that we still need and adjust HEAD to point
230 to the next message! */
231 if (buf->tail < buf->head) {
232 if ((buf->tail + l) >= buf->head) {
233 /* we need to move the HEAD to point to the next message
234 * Theoretically we have enough room to add the whole message to the
235 * buffer, because of the first outer IF statement, so we don't have
236 * to worry about overflows here!
237 */
238 int k = buf->tail + l - buf->head; /* we need to know how many bytes
239 we are overwriting to make
240 enough room */
241 char *c =
242 memchr(buf->data + buf->head + k, '\0',
243 buf->size - (buf->head + k));
244 if (c != NULL) { /* do a sanity check just in case! */
245 buf->head = c - buf->data + 1; /* we need to convert pointer to
246 offset + skip the '\0' since
247 we need to point to the beginning
248 of the next message */
249 /* Note: HEAD is only used to "retrieve" messages, it's not used
250 when writing messages into our buffer */
251 } else { /* show an error message to know we messed up? */
252 printf("Weird! Can't find the terminator token??? \n");
253 buf->head = 0;
254 }
255 }
256 }
257
258 /* in other cases no overflows have been done yet, so we don't care! */
259 /* we should be ok to append the message now */
260 strncpy(buf->data + buf->tail, msg, l); /* append our message */
261 buf->tail += l; /* count full message w/ '\0' terminating char */
262 } else {
263 /* we need to break up the message and "circle" it around */
264 char *c;
265 int k = buf->tail + l - buf->size; /* count # of bytes we don't fit */
266
267 /* We need to move HEAD! This is always the case since we are going
268 * to "circle" the message.
269 */
270 c = memchr(buf->data + k, '\0', buf->size - k);
271
272 if (c != NULL) { /* if we don't have '\0'??? weird!!! */
273 /* move head pointer */
274 buf->head = c - buf->data + 1;
275
276 /* now write the first part of the message */
277 strncpy(buf->data + buf->tail, msg, l - k - 1);
278
279 /* ALWAYS terminate end of buffer w/ '\0' */
280 buf->data[buf->size - 1] = '\0';
281
282 /* now write out the rest of the string to the beginning of the buffer */
283 strcpy(buf->data, &msg[l - k - 1]);
284
285 /* we need to place the TAIL at the end of the message */
286 buf->tail = k + 1;
287 } else {
288 printf
289 ("Weird! Can't find the terminator token from the beginning??? \n");
290 buf->head = buf->tail = 0; /* reset buffer, since it's probably corrupted */
291 }
292
293 }
294 sem_up(s_semid);
295}
296#endif /* CONFIG_FEATURE_IPC_SYSLOG */
297
298/* Note: There is also a function called "message()" in init.c */
299/* Print a message to the log file. */
300static void message(char *fmt, ...) __attribute__ ((format(printf, 1, 2)));
301static void message(char *fmt, ...)
302{
303 int fd;
304 struct flock fl;
305 va_list arguments;
306
307 fl.l_whence = SEEK_SET;
308 fl.l_start = 0;
309 fl.l_len = 1;
310
311#ifdef CONFIG_FEATURE_IPC_SYSLOG
312 if ((circular_logging == TRUE) && (buf != NULL)) {
313 char b[1024];
314
315 va_start(arguments, fmt);
316 vsnprintf(b, sizeof(b) - 1, fmt, arguments);
317 va_end(arguments);
318 circ_message(b);
319
320 } else
321#endif
322 if ((fd =
323 device_open(logFilePath,
324 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
325 O_NONBLOCK)) >= 0) {
326 fl.l_type = F_WRLCK;
327 fcntl(fd, F_SETLKW, &fl);
328#ifdef CONFIG_FEATURE_ROTATE_LOGFILE
329 if ( logFileSize > 0 ) {
330 struct stat statf;
331 int r = fstat(fd, &statf);
332 if( !r && (statf.st_mode & S_IFREG)
333 && (lseek(fd,0,SEEK_END) > logFileSize) ) {
334 if(logFileRotate > 0) {
335 int i;
336 char oldFile[(strlen(logFilePath)+3)], newFile[(strlen(logFilePath)+3)];
337 for(i=logFileRotate-1;i>0;i--) {
338 sprintf(oldFile, "%s.%d", logFilePath, i-1);
339 sprintf(newFile, "%s.%d", logFilePath, i);
340 rename(oldFile, newFile);
341 }
342 sprintf(newFile, "%s.%d", logFilePath, 0);
343 fl.l_type = F_UNLCK;
344 fcntl (fd, F_SETLKW, &fl);
345 close(fd);
346 rename(logFilePath, newFile);
347 fd = device_open (logFilePath,
348 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
349 O_NONBLOCK);
350 fl.l_type = F_WRLCK;
351 fcntl (fd, F_SETLKW, &fl);
352 } else {
353 ftruncate( fd, 0 );
354 }
355 }
356 }
357#endif
358 va_start(arguments, fmt);
359 vdprintf(fd, fmt, arguments);
360 va_end(arguments);
361 fl.l_type = F_UNLCK;
362 fcntl(fd, F_SETLKW, &fl);
363 close(fd);
364 } else {
365 /* Always send console messages to /dev/console so people will see them. */
366 if ((fd =
367 device_open(_PATH_CONSOLE,
368 O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) {
369 va_start(arguments, fmt);
370 vdprintf(fd, fmt, arguments);
371 va_end(arguments);
372 close(fd);
373 } else {
374 fprintf(stderr, "Bummer, can't print: ");
375 va_start(arguments, fmt);
376 vfprintf(stderr, fmt, arguments);
377 fflush(stderr);
378 va_end(arguments);
379 }
380 }
381}
382
383#ifdef CONFIG_FEATURE_REMOTE_LOG
384static void init_RemoteLog(void)
385{
386 memset(&remoteaddr, 0, sizeof(remoteaddr));
387 remotefd = socket(AF_INET, SOCK_DGRAM, 0);
388
389 if (remotefd < 0) {
390 bb_error_msg("cannot create socket");
391 }
392
393 remoteaddr.sin_family = AF_INET;
394 remoteaddr.sin_addr = *(struct in_addr *) *(xgethostbyname(RemoteHost))->h_addr_list;
395 remoteaddr.sin_port = htons(RemotePort);
396}
397#endif
398
399static void logMessage(int pri, char *msg)
400{
401 time_t now;
402 char *timestamp;
403 static char res[20] = "";
404#ifdef CONFIG_FEATURE_REMOTE_LOG
405 static char line[MAXLINE + 1];
406#endif
407 CODE *c_pri, *c_fac;
408
409 if (pri != 0) {
410 for (c_fac = facilitynames;
411 c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++);
412 for (c_pri = prioritynames;
413 c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++);
414 if (c_fac->c_name == NULL || c_pri->c_name == NULL) {
415 snprintf(res, sizeof(res), "<%d>", pri);
416 } else {
417 snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name);
418 }
419 }
420
421 if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' ||
422 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') {
423 time(&now);
424 timestamp = ctime(&now) + 4;
425 timestamp[15] = '\0';
426 } else {
427 timestamp = msg;
428 timestamp[15] = '\0';
429 msg += 16;
430 }
431
432 /* todo: supress duplicates */
433
434#ifdef CONFIG_FEATURE_REMOTE_LOG
435 if (doRemoteLog == TRUE) {
436 /* trying connect the socket */
437 if (-1 == remotefd) {
438 init_RemoteLog();
439 }
440
441 /* if we have a valid socket, send the message */
442 if (-1 != remotefd) {
443 now = 1;
444 snprintf(line, sizeof(line), "<%d> %s", pri, msg);
445
446 retry:
447 /* send message to remote logger */
448 if(( -1 == sendto(remotefd, line, strlen(line), 0,
449 (struct sockaddr *) &remoteaddr,
450 sizeof(remoteaddr))) && (errno == EINTR)) {
451 /* sleep now seconds and retry (with now * 2) */
452 sleep(now);
453 now *= 2;
454 goto retry;
455 }
456 }
457 }
458
459 if (local_logging == TRUE)
460#endif
461 {
462 /* now spew out the message to wherever it is supposed to go */
463 if (small)
464 message("%s %s\n", timestamp, msg);
465 else
466 message("%s %s %s %s\n", timestamp, LocalHostName, res, msg);
467 }
468}
469
470static void quit_signal(int sig)
471{
472 logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting.");
473 unlink(lfile);
474#ifdef CONFIG_FEATURE_IPC_SYSLOG
475 ipcsyslog_cleanup();
476#endif
477
478 exit(TRUE);
479}
480
481static void domark(int sig)
482{
483 if (MarkInterval > 0) {
484 logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --");
485 alarm(MarkInterval);
486 }
487}
488
489/* This must be a #define, since when CONFIG_DEBUG and BUFFERS_GO_IN_BSS are
490 * enabled, we otherwise get a "storage size isn't constant error. */
491static int serveConnection(char *tmpbuf, int n_read)
492{
493 char *p = tmpbuf;
494
495 while (p < tmpbuf + n_read) {
496
497 int pri = (LOG_USER | LOG_NOTICE);
498 int num_lt = 0;
499 char line[MAXLINE + 1];
500 unsigned char c;
501 char *q = line;
502
503 while ((c = *p) && q < &line[sizeof(line) - 1]) {
504 if (c == '<' && num_lt == 0) {
505 /* Parse the magic priority number. */
506 num_lt++;
507 pri = 0;
508 while (isdigit(*(++p))) {
509 pri = 10 * pri + (*p - '0');
510 }
511 if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) {
512 pri = (LOG_USER | LOG_NOTICE);
513 }
514 } else if (c == '\n') {
515 *q++ = ' ';
516 } else if (iscntrl(c) && (c < 0177)) {
517 *q++ = '^';
518 *q++ = c ^ 0100;
519 } else {
520 *q++ = c;
521 }
522 p++;
523 }
524 *q = '\0';
525 p++;
526 /* Now log it */
527 logMessage(pri, line);
528 }
529 return n_read;
530}
531
532static void doSyslogd(void) __attribute__ ((noreturn));
533static void doSyslogd(void)
534{
535 struct sockaddr_un sunx;
536 socklen_t addrLength;
537
538 int sock_fd;
539 fd_set fds;
540
541 /* Set up signal handlers. */
542 signal(SIGINT, quit_signal);
543 signal(SIGTERM, quit_signal);
544 signal(SIGQUIT, quit_signal);
545 signal(SIGHUP, SIG_IGN);
546 signal(SIGCHLD, SIG_IGN);
547#ifdef SIGCLD
548 signal(SIGCLD, SIG_IGN);
549#endif
550 signal(SIGALRM, domark);
551 alarm(MarkInterval);
552
553 /* Create the syslog file so realpath() can work. */
554 if (realpath(_PATH_LOG, lfile) != NULL) {
555 unlink(lfile);
556 }
557
558 memset(&sunx, 0, sizeof(sunx));
559 sunx.sun_family = AF_UNIX;
560 strncpy(sunx.sun_path, lfile, sizeof(sunx.sun_path));
561 if ((sock_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) {
562 bb_perror_msg_and_die("Couldn't get file descriptor for socket "
563 _PATH_LOG);
564 }
565
566 addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path);
567 if (bind(sock_fd, (struct sockaddr *) &sunx, addrLength) < 0) {
568 bb_perror_msg_and_die("Could not connect to socket " _PATH_LOG);
569 }
570
571 if (chmod(lfile, 0666) < 0) {
572 bb_perror_msg_and_die("Could not set permission on " _PATH_LOG);
573 }
574#ifdef CONFIG_FEATURE_IPC_SYSLOG
575 if (circular_logging == TRUE) {
576 ipcsyslog_init();
577 }
578#endif
579
580#ifdef CONFIG_FEATURE_REMOTE_LOG
581 if (doRemoteLog == TRUE) {
582 init_RemoteLog();
583 }
584#endif
585
586 logMessage(LOG_SYSLOG | LOG_INFO, "syslogd started: " BB_BANNER);
587
588 for (;;) {
589
590 FD_ZERO(&fds);
591 FD_SET(sock_fd, &fds);
592
593 if (select(sock_fd + 1, &fds, NULL, NULL, NULL) < 0) {
594 if (errno == EINTR) {
595 /* alarm may have happened. */
596 continue;
597 }
598 bb_perror_msg_and_die("select error");
599 }
600
601 if (FD_ISSET(sock_fd, &fds)) {
602 int i;
603
604 RESERVE_CONFIG_BUFFER(tmpbuf, MAXLINE + 1);
605
606 memset(tmpbuf, '\0', MAXLINE + 1);
607 if ((i = recv(sock_fd, tmpbuf, MAXLINE, 0)) > 0) {
608 serveConnection(tmpbuf, i);
609 } else {
610 bb_perror_msg_and_die("UNIX socket error");
611 }
612 RELEASE_CONFIG_BUFFER(tmpbuf);
613 } /* FD_ISSET() */
614 } /* for main loop */
615}
616
617extern int syslogd_main(int argc, char **argv)
618{
619 int opt;
620
621 int doFork = TRUE;
622
623 char *p;
624
625 /* do normal option parsing */
626 while ((opt = getopt(argc, argv, "m:nO:s:Sb:R:LC::")) > 0) {
627 switch (opt) {
628 case 'm':
629 MarkInterval = atoi(optarg) * 60;
630 break;
631 case 'n':
632 doFork = FALSE;
633 break;
634 case 'O':
635 logFilePath = optarg;
636 break;
637#ifdef CONFIG_FEATURE_ROTATE_LOGFILE
638 case 's':
639 logFileSize = atoi(optarg) * 1024;
640 break;
641 case 'b':
642 logFileRotate = atoi(optarg);
643 if( logFileRotate > 99 ) logFileRotate = 99;
644 break;
645#endif
646#ifdef CONFIG_FEATURE_REMOTE_LOG
647 case 'R':
648 RemoteHost = bb_xstrdup(optarg);
649 if ((p = strchr(RemoteHost, ':'))) {
650 RemotePort = atoi(p + 1);
651 *p = '\0';
652 }
653 doRemoteLog = TRUE;
654 break;
655 case 'L':
656 local_logging = TRUE;
657 break;
658#endif
659#ifdef CONFIG_FEATURE_IPC_SYSLOG
660 case 'C':
661 if (optarg) {
662 int buf_size = atoi(optarg);
663 if (buf_size >= 4) {
664 shm_size = buf_size * 1024;
665 }
666 }
667 circular_logging = TRUE;
668 break;
669#endif
670 case 'S':
671 small = true;
672 break;
673 default:
674 bb_show_usage();
675 }
676 }
677
678#ifdef CONFIG_FEATURE_REMOTE_LOG
679 /* If they have not specified remote logging, then log locally */
680 if (doRemoteLog == FALSE)
681 local_logging = TRUE;
682#endif
683
684
685 /* Store away localhost's name before the fork */
686 gethostname(LocalHostName, sizeof(LocalHostName));
687 if ((p = strchr(LocalHostName, '.'))) {
688 *p = '\0';
689 }
690
691 umask(0);
692
693 if (doFork == TRUE) {
694#if defined(__uClinux__)
695 vfork_daemon_rexec(0, 1, argc, argv, "-n");
696#else /* __uClinux__ */
697 if(daemon(0, 1) < 0)
698 bb_perror_msg_and_die("daemon");
699#endif /* __uClinux__ */
700 }
701 doSyslogd();
702
703 return EXIT_SUCCESS;
704}
705
706/*
707Local Variables
708c-file-style: "linux"
709c-basic-offset: 4
710tab-width: 4
711End:
712*/