aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Whitley <markw@lineo.com>2001-03-12 22:51:50 +0000
committerMark Whitley <markw@lineo.com>2001-03-12 22:51:50 +0000
commit6317c4baf79c25d7f77897b064eb4f0b7d9f070e (patch)
tree5fc8fe65a4903f6224925a72b53a4f46e2b0b1d3
parent4987bbf97924044c88007c45ee2674d97b93ad92 (diff)
downloadbusybox-w32-6317c4baf79c25d7f77897b064eb4f0b7d9f070e.tar.gz
busybox-w32-6317c4baf79c25d7f77897b064eb4f0b7d9f070e.tar.bz2
busybox-w32-6317c4baf79c25d7f77897b064eb4f0b7d9f070e.zip
Applied patch from Gennady Feldman to split up syslogd.c into syslogd and
klogd (as it should be).
-rw-r--r--Config.h2
-rw-r--r--applets.h6
-rw-r--r--applets/usage.h23
-rw-r--r--busybox.h5
-rw-r--r--include/applets.h6
-rw-r--r--include/busybox.h5
-rw-r--r--include/usage.h23
-rw-r--r--klogd.c171
-rw-r--r--logger.c5
-rw-r--r--logread.c135
-rw-r--r--sysklogd/klogd.c171
-rw-r--r--sysklogd/logger.c5
-rw-r--r--sysklogd/logread.c135
-rw-r--r--sysklogd/syslogd.c318
-rw-r--r--syslogd.c318
-rw-r--r--usage.h23
-rw-r--r--utility.c18
17 files changed, 1115 insertions, 254 deletions
diff --git a/Config.h b/Config.h
index 8c6bfe3ec..b6f2f8a05 100644
--- a/Config.h
+++ b/Config.h
@@ -52,6 +52,7 @@
52//#define BB_INSMOD 52//#define BB_INSMOD
53#define BB_KILL 53#define BB_KILL
54#define BB_KILLALL 54#define BB_KILLALL
55#define BB_KLOGD
55//#define BB_LENGTH 56//#define BB_LENGTH
56#define BB_LN 57#define BB_LN
57//#define BB_LOADACM 58//#define BB_LOADACM
@@ -59,6 +60,7 @@
59//#define BB_LOADKMAP 60//#define BB_LOADKMAP
60#define BB_LOGGER 61#define BB_LOGGER
61//#define BB_LOGNAME 62//#define BB_LOGNAME
63#define BB_LOGREAD
62#define BB_LS 64#define BB_LS
63#define BB_LSMOD 65#define BB_LSMOD
64//#define BB_MAKEDEVS 66//#define BB_MAKEDEVS
diff --git a/applets.h b/applets.h
index 36817fef7..b3fb291d7 100644
--- a/applets.h
+++ b/applets.h
@@ -191,6 +191,9 @@
191#ifdef BB_KILLALL 191#ifdef BB_KILLALL
192 APPLET(killall, kill_main, _BB_DIR_USR_BIN) 192 APPLET(killall, kill_main, _BB_DIR_USR_BIN)
193#endif 193#endif
194#ifdef BB_KLOGD
195 APPLET(klogd, klogd_main, _BB_DIR_SBIN)
196#endif
194#ifdef BB_LENGTH 197#ifdef BB_LENGTH
195 APPLET(length, length_main, _BB_DIR_USR_BIN) 198 APPLET(length, length_main, _BB_DIR_USR_BIN)
196#endif 199#endif
@@ -215,6 +218,9 @@
215#ifdef BB_LOGNAME 218#ifdef BB_LOGNAME
216 APPLET(logname, logname_main, _BB_DIR_USR_BIN) 219 APPLET(logname, logname_main, _BB_DIR_USR_BIN)
217#endif 220#endif
221#ifdef BB_LOGREAD
222 APPLET(logread, logread_main, _BB_DIR_SBIN)
223#endif
218#ifdef BB_LS 224#ifdef BB_LS
219 APPLET(ls, ls_main, _BB_DIR_BIN) 225 APPLET(ls, ls_main, _BB_DIR_BIN)
220#endif 226#endif
diff --git a/applets/usage.h b/applets/usage.h
index 8ba86d569..f241d3a04 100644
--- a/applets/usage.h
+++ b/applets/usage.h
@@ -468,6 +468,13 @@
468 "Options:\n" \ 468 "Options:\n" \
469 "\t-l\tList all signal names and numbers." 469 "\t-l\tList all signal names and numbers."
470 470
471#define klogd_trivial_usage \
472 "-n"
473#define klogd_full_usage \
474 "Kernel logger.\n"\
475 "Options:\n"\
476 "\t-n\tRun as a foreground process."
477
471#define length_trivial_usage \ 478#define length_trivial_usage \
472 "STRING" 479 "STRING"
473#define length_full_usage \ 480#define length_full_usage \
@@ -513,6 +520,12 @@
513#define logname_full_usage \ 520#define logname_full_usage \
514 "Print the name of the current user." 521 "Print the name of the current user."
515 522
523#define logread_trivial_usage \
524 ""
525
526#define logread_full_usage \
527 "Shows the messages from syslogd (using circular buffer)."
528
516#ifdef BB_FEATURE_LS_TIMESTAMPS 529#ifdef BB_FEATURE_LS_TIMESTAMPS
517 #define USAGE_LS_TIMESTAMPS(a) a 530 #define USAGE_LS_TIMESTAMPS(a) a
518#else 531#else
@@ -913,11 +926,6 @@
913 "Write all buffered filesystem blocks to disk." 926 "Write all buffered filesystem blocks to disk."
914 927
915 928
916#ifdef BB_FEATURE_KLOGD
917 #define USAGE_KLOGD(a) a
918#else
919 #define USAGE_KLOGD(a)
920#endif
921#ifdef BB_FEATURE_REMOTE_LOG 929#ifdef BB_FEATURE_REMOTE_LOG
922 #define USAGE_REMOTE_LOG(a) a 930 #define USAGE_REMOTE_LOG(a) a
923#else 931#else
@@ -926,12 +934,11 @@
926#define syslogd_trivial_usage \ 934#define syslogd_trivial_usage \
927 "[OPTION]..." 935 "[OPTION]..."
928#define syslogd_full_usage \ 936#define syslogd_full_usage \
929 "Linux system and kernel (provides klogd) logging utility.\n" \ 937 "Linux system and kernel logging utility.\n" \
930 "Note that this version of syslogd/klogd ignores /etc/syslog.conf.\n\n" \ 938 "Note that this version of syslogd ignores /etc/syslog.conf.\n\n" \
931 "Options:\n" \ 939 "Options:\n" \
932 "\t-m NUM\t\tInterval between MARK lines (default=20min, 0=off)\n" \ 940 "\t-m NUM\t\tInterval between MARK lines (default=20min, 0=off)\n" \
933 "\t-n\t\tRun as a foreground process\n" \ 941 "\t-n\t\tRun as a foreground process\n" \
934 USAGE_KLOGD("\t-K\t\tDo not start up the klogd process\n") \
935 "\t-O FILE\t\tUse an alternate log file (default=/var/log/messages)" \ 942 "\t-O FILE\t\tUse an alternate log file (default=/var/log/messages)" \
936 USAGE_REMOTE_LOG( \ 943 USAGE_REMOTE_LOG( \
937 "\n\t-R HOST[:PORT]\tLog to IP or hostname on PORT (default PORT=514/UDP)\n" \ 944 "\n\t-R HOST[:PORT]\tLog to IP or hostname on PORT (default PORT=514/UDP)\n" \
diff --git a/busybox.h b/busybox.h
index d9362b58b..abf62410f 100644
--- a/busybox.h
+++ b/busybox.h
@@ -205,6 +205,11 @@ int nfsmount(const char *spec, const char *node, int *flags,
205#define RB_POWER_OFF 0x4321fedc 205#define RB_POWER_OFF 0x4321fedc
206#endif 206#endif
207 207
208#if defined(BB_KLOGD) || defined(BB_LOGGER)
209void syslog_msg_with_name(const char *name, int facility, int pri, const char *msg);
210void syslog_msg(int facility, int pri, const char *msg);
211#endif
212
208/* Include our own copy of struct sysinfo to avoid binary compatability 213/* Include our own copy of struct sysinfo to avoid binary compatability
209 * problems with Linux 2.4, which changed things. Grumble, grumble. */ 214 * problems with Linux 2.4, which changed things. Grumble, grumble. */
210struct sysinfo { 215struct sysinfo {
diff --git a/include/applets.h b/include/applets.h
index 36817fef7..b3fb291d7 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -191,6 +191,9 @@
191#ifdef BB_KILLALL 191#ifdef BB_KILLALL
192 APPLET(killall, kill_main, _BB_DIR_USR_BIN) 192 APPLET(killall, kill_main, _BB_DIR_USR_BIN)
193#endif 193#endif
194#ifdef BB_KLOGD
195 APPLET(klogd, klogd_main, _BB_DIR_SBIN)
196#endif
194#ifdef BB_LENGTH 197#ifdef BB_LENGTH
195 APPLET(length, length_main, _BB_DIR_USR_BIN) 198 APPLET(length, length_main, _BB_DIR_USR_BIN)
196#endif 199#endif
@@ -215,6 +218,9 @@
215#ifdef BB_LOGNAME 218#ifdef BB_LOGNAME
216 APPLET(logname, logname_main, _BB_DIR_USR_BIN) 219 APPLET(logname, logname_main, _BB_DIR_USR_BIN)
217#endif 220#endif
221#ifdef BB_LOGREAD
222 APPLET(logread, logread_main, _BB_DIR_SBIN)
223#endif
218#ifdef BB_LS 224#ifdef BB_LS
219 APPLET(ls, ls_main, _BB_DIR_BIN) 225 APPLET(ls, ls_main, _BB_DIR_BIN)
220#endif 226#endif
diff --git a/include/busybox.h b/include/busybox.h
index d9362b58b..abf62410f 100644
--- a/include/busybox.h
+++ b/include/busybox.h
@@ -205,6 +205,11 @@ int nfsmount(const char *spec, const char *node, int *flags,
205#define RB_POWER_OFF 0x4321fedc 205#define RB_POWER_OFF 0x4321fedc
206#endif 206#endif
207 207
208#if defined(BB_KLOGD) || defined(BB_LOGGER)
209void syslog_msg_with_name(const char *name, int facility, int pri, const char *msg);
210void syslog_msg(int facility, int pri, const char *msg);
211#endif
212
208/* Include our own copy of struct sysinfo to avoid binary compatability 213/* Include our own copy of struct sysinfo to avoid binary compatability
209 * problems with Linux 2.4, which changed things. Grumble, grumble. */ 214 * problems with Linux 2.4, which changed things. Grumble, grumble. */
210struct sysinfo { 215struct sysinfo {
diff --git a/include/usage.h b/include/usage.h
index 8ba86d569..f241d3a04 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -468,6 +468,13 @@
468 "Options:\n" \ 468 "Options:\n" \
469 "\t-l\tList all signal names and numbers." 469 "\t-l\tList all signal names and numbers."
470 470
471#define klogd_trivial_usage \
472 "-n"
473#define klogd_full_usage \
474 "Kernel logger.\n"\
475 "Options:\n"\
476 "\t-n\tRun as a foreground process."
477
471#define length_trivial_usage \ 478#define length_trivial_usage \
472 "STRING" 479 "STRING"
473#define length_full_usage \ 480#define length_full_usage \
@@ -513,6 +520,12 @@
513#define logname_full_usage \ 520#define logname_full_usage \
514 "Print the name of the current user." 521 "Print the name of the current user."
515 522
523#define logread_trivial_usage \
524 ""
525
526#define logread_full_usage \
527 "Shows the messages from syslogd (using circular buffer)."
528
516#ifdef BB_FEATURE_LS_TIMESTAMPS 529#ifdef BB_FEATURE_LS_TIMESTAMPS
517 #define USAGE_LS_TIMESTAMPS(a) a 530 #define USAGE_LS_TIMESTAMPS(a) a
518#else 531#else
@@ -913,11 +926,6 @@
913 "Write all buffered filesystem blocks to disk." 926 "Write all buffered filesystem blocks to disk."
914 927
915 928
916#ifdef BB_FEATURE_KLOGD
917 #define USAGE_KLOGD(a) a
918#else
919 #define USAGE_KLOGD(a)
920#endif
921#ifdef BB_FEATURE_REMOTE_LOG 929#ifdef BB_FEATURE_REMOTE_LOG
922 #define USAGE_REMOTE_LOG(a) a 930 #define USAGE_REMOTE_LOG(a) a
923#else 931#else
@@ -926,12 +934,11 @@
926#define syslogd_trivial_usage \ 934#define syslogd_trivial_usage \
927 "[OPTION]..." 935 "[OPTION]..."
928#define syslogd_full_usage \ 936#define syslogd_full_usage \
929 "Linux system and kernel (provides klogd) logging utility.\n" \ 937 "Linux system and kernel logging utility.\n" \
930 "Note that this version of syslogd/klogd ignores /etc/syslog.conf.\n\n" \ 938 "Note that this version of syslogd ignores /etc/syslog.conf.\n\n" \
931 "Options:\n" \ 939 "Options:\n" \
932 "\t-m NUM\t\tInterval between MARK lines (default=20min, 0=off)\n" \ 940 "\t-m NUM\t\tInterval between MARK lines (default=20min, 0=off)\n" \
933 "\t-n\t\tRun as a foreground process\n" \ 941 "\t-n\t\tRun as a foreground process\n" \
934 USAGE_KLOGD("\t-K\t\tDo not start up the klogd process\n") \
935 "\t-O FILE\t\tUse an alternate log file (default=/var/log/messages)" \ 942 "\t-O FILE\t\tUse an alternate log file (default=/var/log/messages)" \
936 USAGE_REMOTE_LOG( \ 943 USAGE_REMOTE_LOG( \
937 "\n\t-R HOST[:PORT]\tLog to IP or hostname on PORT (default PORT=514/UDP)\n" \ 944 "\n\t-R HOST[:PORT]\tLog to IP or hostname on PORT (default PORT=514/UDP)\n" \
diff --git a/klogd.c b/klogd.c
new file mode 100644
index 000000000..f44383637
--- /dev/null
+++ b/klogd.c
@@ -0,0 +1,171 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini klogd implementation for busybox
4 *
5 * Copyright (C) 2001 by Gennady Feldman <gfeldman@cachier.com>.
6 * Changes: Made this a standalone busybox module which uses standalone
7 * syslog() client interface.
8 *
9 * Copyright (C) 1999,2000,2001 by Lineo, inc.
10 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
11 *
12 * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org>
13 *
14 * "circular buffer" Copyright (C) 2000 by Gennady Feldman <gfeldman@mail.com>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <signal.h> /* for our signal() handlers */
35#include <string.h> /* strncpy() */
36#include <errno.h> /* errno and friends */
37#include <unistd.h>
38#include <ctype.h>
39#include <sys/syslog.h>
40
41#if ! defined __GLIBC__ && ! defined __UCLIBC__
42#include <sys/syscall.h>
43#include <linux/unistd.h>
44typedef unsigned int socklen_t;
45
46#ifndef __alpha__
47# define __NR_klogctl __NR_syslog
48static inline _syscall3(int, klogctl, int, type, char *, b, int, len);
49#else /* __alpha__ */
50#define klogctl syslog
51#endif
52
53#else
54# include <sys/klog.h>
55#endif
56#include "busybox.h"
57
58static void klogd_signal(int sig)
59{
60 klogctl(7, NULL, 0);
61 klogctl(0, 0, 0);
62 //logMessage(0, "Kernel log daemon exiting.");
63 syslog_msg(LOG_DAEMON, 0, "Kernel log daemon exiting.");
64 exit(TRUE);
65}
66
67static void doKlogd (void) __attribute__ ((noreturn));
68static void doKlogd (void)
69{
70 int priority = LOG_INFO;
71 char log_buffer[4096];
72 int i, n, lastc;
73 char *start;
74
75 /* Set up sig handlers */
76 signal(SIGINT, klogd_signal);
77 signal(SIGKILL, klogd_signal);
78 signal(SIGTERM, klogd_signal);
79 signal(SIGHUP, SIG_IGN);
80
81 /* "Open the log. Currently a NOP." */
82 klogctl(1, NULL, 0);
83
84 syslog_msg(LOG_DAEMON, 0, "klogd started: BusyBox v" BB_VER " (" BB_BT ")");
85
86 while (1) {
87 /* Use kernel syscalls */
88 memset(log_buffer, '\0', sizeof(log_buffer));
89 n = klogctl(2, log_buffer, sizeof(log_buffer));
90 if (n < 0) {
91 char message[80];
92
93 if (errno == EINTR)
94 continue;
95 snprintf(message, 79, "klogd: Error return from sys_sycall: %d - %s.\n",
96 errno, strerror(errno));
97 syslog_msg(LOG_DAEMON, LOG_SYSLOG | LOG_ERR, message);
98 exit(1);
99 }
100
101 /* klogctl buffer parsing modelled after code in dmesg.c */
102 start=&log_buffer[0];
103 lastc='\0';
104 for (i=0; i<n; i++) {
105 if (lastc == '\0' && log_buffer[i] == '<') {
106 priority = 0;
107 i++;
108 while (isdigit(log_buffer[i])) {
109 priority = priority*10+(log_buffer[i]-'0');
110 i++;
111 }
112 if (log_buffer[i] == '>') i++;
113 start = &log_buffer[i];
114 }
115 if (log_buffer[i] == '\n') {
116 log_buffer[i] = '\0'; /* zero terminate this message */
117 syslog_msg(LOG_DAEMON, LOG_KERN | priority, start);
118 start = &log_buffer[i+1];
119 priority = LOG_INFO;
120 }
121 lastc = log_buffer[i];
122 }
123 }
124}
125
126static void daemon_init (char **argv, char *dz, void fn (void))
127{
128 setsid(); /* start a new session? */
129 strncpy(argv[0], dz, strlen(argv[0]));
130 fn();
131 exit(0);
132}
133
134extern int klogd_main(int argc, char **argv)
135{
136 /* no options, no getopt */
137 int opt, pid;
138 int doFork = TRUE;
139
140 /* do normal option parsing */
141 while ((opt = getopt(argc, argv, "n")) > 0) {
142 switch (opt) {
143 case 'n':
144 doFork = FALSE;
145 break;
146 default:
147 show_usage();
148 }
149 }
150
151 if (doFork == TRUE) {
152 pid = fork();
153 if (pid < 0)
154 exit(pid);
155 else if (pid == 0) {
156 daemon_init (argv, "klogd", doKlogd);
157 }
158 } else {
159 doKlogd();
160 }
161
162 return EXIT_SUCCESS;
163}
164
165/*
166Local Variables
167c-file-style: "linux"
168c-basic-offset: 4
169tab-width: 4
170End:
171*/
diff --git a/logger.c b/logger.c
index 1218d8d2e..b8aae3d28 100644
--- a/logger.c
+++ b/logger.c
@@ -148,9 +148,10 @@ extern int logger_main(int argc, char **argv)
148 message[strlen(message)-1] = '\0'; 148 message[strlen(message)-1] = '\0';
149 } 149 }
150 150
151 openlog(name, option, (pri | LOG_FACMASK)); 151 /*openlog(name, option, (pri | LOG_FACMASK));
152 syslog(pri, "%s", message); 152 syslog(pri, "%s", message);
153 closelog(); 153 closelog();*/
154 syslog_msg_with_name(name,(pri | LOG_FACMASK),pri,message);
154 return EXIT_SUCCESS; 155 return EXIT_SUCCESS;
155} 156}
156 157
diff --git a/logread.c b/logread.c
new file mode 100644
index 000000000..3bf4c541e
--- /dev/null
+++ b/logread.c
@@ -0,0 +1,135 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * circular buffer syslog implementation for busybox
4 *
5 * Copyright (C) 2000 by Gennady Feldman <gfeldman@cachier.com>
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
20 * 02111-1307 USA
21 *
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <sys/ipc.h>
28#include <sys/types.h>
29#include <sys/sem.h>
30#include <sys/shm.h>
31#include <signal.h>
32#include <setjmp.h>
33#include "busybox.h"
34
35static const long KEY_ID = 0x414e4547; /*"GENA"*/
36
37static struct shbuf_ds {
38 int size; // size of data written
39 int head; // start of message list
40 int tail; // end of message list
41 char data[1]; // data/messages
42} *buf = NULL; // shared memory pointer
43
44
45// Semaphore operation structures
46static struct sembuf SMrup[1] = {{0, -1, IPC_NOWAIT | SEM_UNDO}}; // set SMrup
47static struct sembuf SMrdn[2] = {{1, 0}, {0, +1, SEM_UNDO}}; // set SMrdn
48
49static int shmid = -1; // ipc shared memory id
50static int semid = -1; // ipc semaphore id
51static jmp_buf jmp_env;
52
53static void error_exit(const char *str);
54static void interrupted(int sig);
55
56/*
57 * sem_up - up()'s a semaphore.
58 */
59static inline void sem_up(int semid)
60{
61 if ( semop(semid, SMrup, 1) == -1 )
62 error_exit("semop[SMrup]");
63}
64
65/*
66 * sem_down - down()'s a semaphore
67 */
68static inline void sem_down(int semid)
69{
70 if ( semop(semid, SMrdn, 2) == -1 )
71 error_exit("semop[SMrdn]");
72}
73
74extern int logread_main(int argc, char **argv)
75{
76 int i;
77
78 /* no options, no getopt */
79 if (argc > 1)
80 show_usage();
81
82 // handle intrrupt signal
83 if (setjmp(jmp_env)) goto output_end;
84
85 // attempt to redefine ^C signal
86 signal(SIGINT, interrupted);
87
88 if ( (shmid = shmget(KEY_ID, 0, 0)) == -1)
89 error_exit("Can't find circular buffer");
90
91 // Attach shared memory to our char*
92 if ( (buf = shmat(shmid, NULL, SHM_RDONLY)) == NULL)
93 error_exit("Can't get access to circular buffer from syslogd");
94
95 if ( (semid = semget(KEY_ID, 0, 0)) == -1)
96 error_exit("Can't get access to semaphone(s) for circular buffer from syslogd");
97
98 sem_down(semid);
99 // Read Memory
100 i=buf->head;
101
102 //printf("head: %i tail: %i size: %i\n",buf->head,buf->tail,buf->size);
103 if (buf->head == buf->tail) {
104 printf("<empty syslog>\n");
105 }
106
107 while ( i != buf->tail) {
108 printf("%s", buf->data+i);
109 i+= strlen(buf->data+i) + 1;
110 if (i >= buf->size )
111 i=0;
112 }
113 sem_up(semid);
114
115output_end:
116 if (shmid != -1)
117 shmdt(buf);
118
119 return EXIT_SUCCESS;
120}
121
122static void interrupted(int sig){
123 signal(SIGINT, SIG_IGN);
124 longjmp(jmp_env, 1);
125}
126
127static void error_exit(const char *str){
128 perror(str);
129 //release all acquired resources
130 if (shmid != -1)
131 shmdt(buf);
132
133 exit(1);
134}
135
diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c
new file mode 100644
index 000000000..f44383637
--- /dev/null
+++ b/sysklogd/klogd.c
@@ -0,0 +1,171 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Mini klogd implementation for busybox
4 *
5 * Copyright (C) 2001 by Gennady Feldman <gfeldman@cachier.com>.
6 * Changes: Made this a standalone busybox module which uses standalone
7 * syslog() client interface.
8 *
9 * Copyright (C) 1999,2000,2001 by Lineo, inc.
10 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
11 *
12 * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org>
13 *
14 * "circular buffer" Copyright (C) 2000 by Gennady Feldman <gfeldman@mail.com>
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <signal.h> /* for our signal() handlers */
35#include <string.h> /* strncpy() */
36#include <errno.h> /* errno and friends */
37#include <unistd.h>
38#include <ctype.h>
39#include <sys/syslog.h>
40
41#if ! defined __GLIBC__ && ! defined __UCLIBC__
42#include <sys/syscall.h>
43#include <linux/unistd.h>
44typedef unsigned int socklen_t;
45
46#ifndef __alpha__
47# define __NR_klogctl __NR_syslog
48static inline _syscall3(int, klogctl, int, type, char *, b, int, len);
49#else /* __alpha__ */
50#define klogctl syslog
51#endif
52
53#else
54# include <sys/klog.h>
55#endif
56#include "busybox.h"
57
58static void klogd_signal(int sig)
59{
60 klogctl(7, NULL, 0);
61 klogctl(0, 0, 0);
62 //logMessage(0, "Kernel log daemon exiting.");
63 syslog_msg(LOG_DAEMON, 0, "Kernel log daemon exiting.");
64 exit(TRUE);
65}
66
67static void doKlogd (void) __attribute__ ((noreturn));
68static void doKlogd (void)
69{
70 int priority = LOG_INFO;
71 char log_buffer[4096];
72 int i, n, lastc;
73 char *start;
74
75 /* Set up sig handlers */
76 signal(SIGINT, klogd_signal);
77 signal(SIGKILL, klogd_signal);
78 signal(SIGTERM, klogd_signal);
79 signal(SIGHUP, SIG_IGN);
80
81 /* "Open the log. Currently a NOP." */
82 klogctl(1, NULL, 0);
83
84 syslog_msg(LOG_DAEMON, 0, "klogd started: BusyBox v" BB_VER " (" BB_BT ")");
85
86 while (1) {
87 /* Use kernel syscalls */
88 memset(log_buffer, '\0', sizeof(log_buffer));
89 n = klogctl(2, log_buffer, sizeof(log_buffer));
90 if (n < 0) {
91 char message[80];
92
93 if (errno == EINTR)
94 continue;
95 snprintf(message, 79, "klogd: Error return from sys_sycall: %d - %s.\n",
96 errno, strerror(errno));
97 syslog_msg(LOG_DAEMON, LOG_SYSLOG | LOG_ERR, message);
98 exit(1);
99 }
100
101 /* klogctl buffer parsing modelled after code in dmesg.c */
102 start=&log_buffer[0];
103 lastc='\0';
104 for (i=0; i<n; i++) {
105 if (lastc == '\0' && log_buffer[i] == '<') {
106 priority = 0;
107 i++;
108 while (isdigit(log_buffer[i])) {
109 priority = priority*10+(log_buffer[i]-'0');
110 i++;
111 }
112 if (log_buffer[i] == '>') i++;
113 start = &log_buffer[i];
114 }
115 if (log_buffer[i] == '\n') {
116 log_buffer[i] = '\0'; /* zero terminate this message */
117 syslog_msg(LOG_DAEMON, LOG_KERN | priority, start);
118 start = &log_buffer[i+1];
119 priority = LOG_INFO;
120 }
121 lastc = log_buffer[i];
122 }
123 }
124}
125
126static void daemon_init (char **argv, char *dz, void fn (void))
127{
128 setsid(); /* start a new session? */
129 strncpy(argv[0], dz, strlen(argv[0]));
130 fn();
131 exit(0);
132}
133
134extern int klogd_main(int argc, char **argv)
135{
136 /* no options, no getopt */
137 int opt, pid;
138 int doFork = TRUE;
139
140 /* do normal option parsing */
141 while ((opt = getopt(argc, argv, "n")) > 0) {
142 switch (opt) {
143 case 'n':
144 doFork = FALSE;
145 break;
146 default:
147 show_usage();
148 }
149 }
150
151 if (doFork == TRUE) {
152 pid = fork();
153 if (pid < 0)
154 exit(pid);
155 else if (pid == 0) {
156 daemon_init (argv, "klogd", doKlogd);
157 }
158 } else {
159 doKlogd();
160 }
161
162 return EXIT_SUCCESS;
163}
164
165/*
166Local Variables
167c-file-style: "linux"
168c-basic-offset: 4
169tab-width: 4
170End:
171*/
diff --git a/sysklogd/logger.c b/sysklogd/logger.c
index 1218d8d2e..b8aae3d28 100644
--- a/sysklogd/logger.c
+++ b/sysklogd/logger.c
@@ -148,9 +148,10 @@ extern int logger_main(int argc, char **argv)
148 message[strlen(message)-1] = '\0'; 148 message[strlen(message)-1] = '\0';
149 } 149 }
150 150
151 openlog(name, option, (pri | LOG_FACMASK)); 151 /*openlog(name, option, (pri | LOG_FACMASK));
152 syslog(pri, "%s", message); 152 syslog(pri, "%s", message);
153 closelog(); 153 closelog();*/
154 syslog_msg_with_name(name,(pri | LOG_FACMASK),pri,message);
154 return EXIT_SUCCESS; 155 return EXIT_SUCCESS;
155} 156}
156 157
diff --git a/sysklogd/logread.c b/sysklogd/logread.c
new file mode 100644
index 000000000..3bf4c541e
--- /dev/null
+++ b/sysklogd/logread.c
@@ -0,0 +1,135 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * circular buffer syslog implementation for busybox
4 *
5 * Copyright (C) 2000 by Gennady Feldman <gfeldman@cachier.com>
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
20 * 02111-1307 USA
21 *
22 */
23
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <sys/ipc.h>
28#include <sys/types.h>
29#include <sys/sem.h>
30#include <sys/shm.h>
31#include <signal.h>
32#include <setjmp.h>
33#include "busybox.h"
34
35static const long KEY_ID = 0x414e4547; /*"GENA"*/
36
37static struct shbuf_ds {
38 int size; // size of data written
39 int head; // start of message list
40 int tail; // end of message list
41 char data[1]; // data/messages
42} *buf = NULL; // shared memory pointer
43
44
45// Semaphore operation structures
46static struct sembuf SMrup[1] = {{0, -1, IPC_NOWAIT | SEM_UNDO}}; // set SMrup
47static struct sembuf SMrdn[2] = {{1, 0}, {0, +1, SEM_UNDO}}; // set SMrdn
48
49static int shmid = -1; // ipc shared memory id
50static int semid = -1; // ipc semaphore id
51static jmp_buf jmp_env;
52
53static void error_exit(const char *str);
54static void interrupted(int sig);
55
56/*
57 * sem_up - up()'s a semaphore.
58 */
59static inline void sem_up(int semid)
60{
61 if ( semop(semid, SMrup, 1) == -1 )
62 error_exit("semop[SMrup]");
63}
64
65/*
66 * sem_down - down()'s a semaphore
67 */
68static inline void sem_down(int semid)
69{
70 if ( semop(semid, SMrdn, 2) == -1 )
71 error_exit("semop[SMrdn]");
72}
73
74extern int logread_main(int argc, char **argv)
75{
76 int i;
77
78 /* no options, no getopt */
79 if (argc > 1)
80 show_usage();
81
82 // handle intrrupt signal
83 if (setjmp(jmp_env)) goto output_end;
84
85 // attempt to redefine ^C signal
86 signal(SIGINT, interrupted);
87
88 if ( (shmid = shmget(KEY_ID, 0, 0)) == -1)
89 error_exit("Can't find circular buffer");
90
91 // Attach shared memory to our char*
92 if ( (buf = shmat(shmid, NULL, SHM_RDONLY)) == NULL)
93 error_exit("Can't get access to circular buffer from syslogd");
94
95 if ( (semid = semget(KEY_ID, 0, 0)) == -1)
96 error_exit("Can't get access to semaphone(s) for circular buffer from syslogd");
97
98 sem_down(semid);
99 // Read Memory
100 i=buf->head;
101
102 //printf("head: %i tail: %i size: %i\n",buf->head,buf->tail,buf->size);
103 if (buf->head == buf->tail) {
104 printf("<empty syslog>\n");
105 }
106
107 while ( i != buf->tail) {
108 printf("%s", buf->data+i);
109 i+= strlen(buf->data+i) + 1;
110 if (i >= buf->size )
111 i=0;
112 }
113 sem_up(semid);
114
115output_end:
116 if (shmid != -1)
117 shmdt(buf);
118
119 return EXIT_SUCCESS;
120}
121
122static void interrupted(int sig){
123 signal(SIGINT, SIG_IGN);
124 longjmp(jmp_env, 1);
125}
126
127static void error_exit(const char *str){
128 perror(str);
129 //release all acquired resources
130 if (shmid != -1)
131 shmdt(buf);
132
133 exit(1);
134}
135
diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 1276201c3..a7f982a35 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -7,6 +7,8 @@
7 * 7 *
8 * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org> 8 * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org>
9 * 9 *
10 * "circular buffer" Copyright (C) 2001 by Gennady Feldman <gfeldman@cachier.com>
11 *
10 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 13 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or 14 * the Free Software Foundation; either version 2 of the License, or
@@ -40,25 +42,8 @@
40#include <sys/un.h> 42#include <sys/un.h>
41#include <sys/param.h> 43#include <sys/param.h>
42 44
43#if ! defined __GLIBC__ && ! defined __UCLIBC__
44#include <sys/syscall.h>
45#include <linux/unistd.h>
46typedef unsigned int socklen_t;
47
48#ifndef __alpha__
49# define __NR_klogctl __NR_syslog
50static inline _syscall3(int, klogctl, int, type, char *, b, int, len);
51#else /* __alpha__ */
52#define klogctl syslog
53#endif
54
55#else
56# include <sys/klog.h>
57#endif
58#include "busybox.h" 45#include "busybox.h"
59 46
60
61
62/* SYSLOG_NAMES defined to pull some extra junk from syslog.h */ 47/* SYSLOG_NAMES defined to pull some extra junk from syslog.h */
63#define SYSLOG_NAMES 48#define SYSLOG_NAMES
64#include <sys/syslog.h> 49#include <sys/syslog.h>
@@ -91,6 +76,184 @@ static int doRemoteLog = FALSE;
91static int local_logging = FALSE; 76static int local_logging = FALSE;
92#endif 77#endif
93 78
79/* circular buffer variables/structures */
80#ifdef BB_FEATURE_IPC_SYSLOG
81
82#include <sys/ipc.h>
83#include <sys/sem.h>
84#include <sys/shm.h>
85
86/* our shared key */
87static const long KEY_ID = 0x414e4547; /*"GENA"*/
88
89// Semaphore operation structures
90static struct shbuf_ds {
91 int size; // size of data written
92 int head; // start of message list
93 int tail; // end of message list
94 char data[1]; // data/messages
95} *buf = NULL; // shared memory pointer
96
97static struct sembuf SMwup[1] = {{1, -1, IPC_NOWAIT}}; // set SMwup
98static struct sembuf SMwdn[3] = {{0, 0}, {1, 0}, {1, +1}}; // set SMwdn
99
100static int shmid = -1; // ipc shared memory id
101static int s_semid = -1; // ipc semaphore id
102int data_size = 16000; // data size
103int shm_size = 16000 + sizeof(*buf); // our buffer size
104static int circular_logging = FALSE;
105
106/*
107 * sem_up - up()'s a semaphore.
108 */
109static inline void sem_up(int semid)
110{
111 if ( semop(semid, SMwup, 1) == -1 )
112 perror_msg_and_die("semop[SMwup]");
113}
114
115/*
116 * sem_down - down()'s a semaphore
117 */
118static inline void sem_down(int semid)
119{
120 if ( semop(semid, SMwdn, 2) == -1 )
121 perror_msg_and_die("semop[SMwdn]");
122}
123
124
125void ipcsyslog_cleanup(void){
126 printf("Exiting Syslogd!\n");
127 if (shmid != -1)
128 shmdt(buf);
129
130 if (shmid != -1)
131 shmctl(shmid, IPC_RMID, NULL);
132 if (s_semid != -1)
133 semctl(s_semid, 0, IPC_RMID, 0);
134}
135
136void ipcsyslog_init(void){
137 if (buf == NULL){
138 if ((shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023)) == -1)
139 perror_msg_and_die("shmget");
140
141
142 if ((buf = shmat(shmid, NULL, 0)) == NULL)
143 perror_msg_and_die("shmat");
144
145
146 buf->size=data_size;
147 buf->head=buf->tail=0;
148
149 // we'll trust the OS to set initial semval to 0 (let's hope)
150 if ((s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023)) == -1){
151 if (errno == EEXIST){
152 if ((s_semid = semget(KEY_ID, 2, 0)) == -1)
153 perror_msg_and_die("semget");
154 }else
155 perror_msg_and_die("semget");
156 }
157 }else{
158 printf("Buffer already allocated just grab the semaphore?");
159 }
160}
161
162/* write message to buffer */
163void circ_message(const char *msg){
164 int l=strlen(msg)+1; /* count the whole message w/ '\0' included */
165
166 sem_down(s_semid);
167
168 /*
169 * Circular Buffer Algorithm:
170 * --------------------------
171 *
172 * Start-off w/ empty buffer of specific size SHM_SIZ
173 * Start filling it up w/ messages. I use '\0' as separator to break up messages.
174 * This is also very handy since we can do printf on message.
175 *
176 * Once the buffer is full we need to get rid of the first message in buffer and
177 * insert the new message. (Note: if the message being added is >1 message then
178 * we will need to "remove" >1 old message from the buffer). The way this is done
179 * is the following:
180 * When we reach the end of the buffer we set a mark and start from the beginning.
181 * Now what about the beginning and end of the buffer? Well we have the "head"
182 * index/pointer which is the starting point for the messages and we have "tail"
183 * index/pointer which is the ending point for the messages. When we "display" the
184 * messages we start from the beginning and continue until we reach "tail". If we
185 * reach end of buffer, then we just start from the beginning (offset 0). "head" and
186 * "tail" are actually offsets from the beginning of the buffer.
187 *
188 * Note: This algorithm uses Linux IPC mechanism w/ shared memory and semaphores to provide
189 * a threasafe way of handling shared memory operations.
190 */
191 if ( (buf->tail + l) < buf->size ){
192 /* before we append the message we need to check the HEAD so that we won't
193 overwrite any of the message that we still need and adjust HEAD to point
194 to the next message! */
195 if ( buf->tail < buf->head){
196 if ( (buf->tail + l) >= buf->head ){
197 /* we need to move the HEAD to point to the next message
198 * Theoretically we have enough room to add the whole message to the
199 * buffer, because of the first outer IF statement, so we don't have
200 * to worry about overflows here!
201 */
202 int k= buf->tail + l - buf->head; /* we need to know how many bytes
203 we are overwriting to make
204 enough room */
205 char *c=memchr(buf->data+buf->head + k,'\0',buf->size - (buf->head + k));
206 if (c != NULL) {/* do a sanity check just in case! */
207 buf->head = c - buf->data + 1; /* we need to convert pointer to
208 offset + skip the '\0' since
209 we need to point to the beginning
210 of the next message */
211 /* Note: HEAD is only used to "retrieve" messages, it's not used
212 when writing messages into our buffer */
213 }else{ /* show an error message to know we messed up? */
214 printf("Weird! Can't find the terminator token??? \n");
215 buf->head=0;
216 }
217 }
218 } /* in other cases no overflows have been done yet, so we don't care! */
219
220 /* we should be ok to append the message now */
221 strncpy(buf->data + buf->tail,msg,l); /* append our message */
222 buf->tail+=l; /* count full message w/ '\0' terminating char */
223 }else{
224 /* we need to break up the message and "circle" it around */
225 char *c;
226 int k=buf->tail + l - buf->size; /* count # of bytes we don't fit */
227
228 /* We need to move HEAD! This is always the case since we are going
229 * to "circle" the message.
230 */
231 c=memchr(buf->data + k ,'\0', buf->size - k);
232
233 if (c != NULL) /* if we don't have '\0'??? weird!!! */{
234 /* move head pointer*/
235 buf->head=c-buf->data+1;
236
237 /* now write the first part of the message */
238 strncpy(buf->data + buf->tail, msg, l - k - 1);
239
240 /* ALWAYS terminate end of buffer w/ '\0' */
241 buf->data[buf->size-1]='\0';
242
243 /* now write out the rest of the string to the beginning of the buffer */
244 strcpy(buf->data, &msg[l-k-1]);
245
246 /* we need to place the TAIL at the end of the message */
247 buf->tail = k + 1;
248 }else{
249 printf("Weird! Can't find the terminator token from the beginning??? \n");
250 buf->head = buf->tail = 0; /* reset buffer, since it's probably corrupted */
251 }
252
253 }
254 sem_up(s_semid);
255}
256#endif
94/* Note: There is also a function called "message()" in init.c */ 257/* Note: There is also a function called "message()" in init.c */
95/* Print a message to the log file. */ 258/* Print a message to the log file. */
96static void message (char *fmt, ...) __attribute__ ((format (printf, 1, 2))); 259static void message (char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
@@ -104,6 +267,16 @@ static void message (char *fmt, ...)
104 fl.l_start = 0; 267 fl.l_start = 0;
105 fl.l_len = 1; 268 fl.l_len = 1;
106 269
270#ifdef BB_FEATURE_IPC_SYSLOG
271 if ((circular_logging == TRUE) && (buf != NULL)){
272 char b[1024];
273 va_start (arguments, fmt);
274 vsprintf (b, fmt, arguments);
275 va_end (arguments);
276 circ_message(b);
277
278 }else
279#endif
107 if ((fd = device_open (logFilePath, 280 if ((fd = device_open (logFilePath,
108 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND | 281 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
109 O_NONBLOCK)) >= 0) { 282 O_NONBLOCK)) >= 0) {
@@ -197,6 +370,10 @@ static void quit_signal(int sig)
197{ 370{
198 logMessage(0, "System log daemon exiting."); 371 logMessage(0, "System log daemon exiting.");
199 unlink(lfile); 372 unlink(lfile);
373#ifdef BB_FEATURE_IPC_SYSLOG
374 ipcsyslog_cleanup();
375#endif
376
200 exit(TRUE); 377 exit(TRUE);
201} 378}
202 379
@@ -382,85 +559,6 @@ static void doSyslogd (void)
382 } /* for main loop */ 559 } /* for main loop */
383} 560}
384 561
385#ifdef BB_FEATURE_KLOGD
386
387static void klogd_signal(int sig)
388{
389 klogctl(7, NULL, 0);
390 klogctl(0, 0, 0);
391 logMessage(0, "Kernel log daemon exiting.");
392 exit(TRUE);
393}
394
395static void doKlogd (void) __attribute__ ((noreturn));
396static void doKlogd (void)
397{
398 int priority = LOG_INFO;
399 char log_buffer[4096];
400 int i, n, lastc;
401 char *start;
402
403 /* Set up sig handlers */
404 signal(SIGINT, klogd_signal);
405 signal(SIGKILL, klogd_signal);
406 signal(SIGTERM, klogd_signal);
407 signal(SIGHUP, SIG_IGN);
408
409#ifdef BB_FEATURE_REMOTE_LOG
410 if (doRemoteLog == TRUE){
411 init_RemoteLog();
412 }
413#endif
414
415 logMessage(0, "klogd started: "
416 "BusyBox v" BB_VER " (" BB_BT ")");
417
418 /* "Open the log. Currently a NOP." */
419 klogctl(1, NULL, 0);
420
421 while (1) {
422 /* Use kernel syscalls */
423 memset(log_buffer, '\0', sizeof(log_buffer));
424 n = klogctl(2, log_buffer, sizeof(log_buffer));
425 if (n < 0) {
426 char message[80];
427
428 if (errno == EINTR)
429 continue;
430 snprintf(message, 79, "klogd: Error return from sys_sycall: " \
431 "%d - %s.\n", errno, strerror(errno));
432 logMessage(LOG_SYSLOG | LOG_ERR, message);
433 exit(1);
434 }
435
436 /* klogctl buffer parsing modelled after code in dmesg.c */
437 start=&log_buffer[0];
438 lastc='\0';
439 for (i=0; i<n; i++) {
440 if (lastc == '\0' && log_buffer[i] == '<') {
441 priority = 0;
442 i++;
443 while (isdigit(log_buffer[i])) {
444 priority = priority*10+(log_buffer[i]-'0');
445 i++;
446 }
447 if (log_buffer[i] == '>') i++;
448 start = &log_buffer[i];
449 }
450 if (log_buffer[i] == '\n') {
451 log_buffer[i] = '\0'; /* zero terminate this message */
452 logMessage(LOG_KERN | priority, start);
453 start = &log_buffer[i+1];
454 priority = LOG_INFO;
455 }
456 lastc = log_buffer[i];
457 }
458 }
459
460}
461
462#endif
463
464static void daemon_init (char **argv, char *dz, void fn (void)) 562static void daemon_init (char **argv, char *dz, void fn (void))
465{ 563{
466 setsid(); 564 setsid();
@@ -472,16 +570,13 @@ static void daemon_init (char **argv, char *dz, void fn (void))
472 570
473extern int syslogd_main(int argc, char **argv) 571extern int syslogd_main(int argc, char **argv)
474{ 572{
475 int opt, pid, klogd_pid; 573 int opt, pid;
476 int doFork = TRUE; 574 int doFork = TRUE;
477 575
478#ifdef BB_FEATURE_KLOGD
479 int startKlogd = TRUE;
480#endif
481 char *p; 576 char *p;
482 577
483 /* do normal option parsing */ 578 /* do normal option parsing */
484 while ((opt = getopt(argc, argv, "m:nKO:R:L")) > 0) { 579 while ((opt = getopt(argc, argv, "m:nO:R:LC")) > 0) {
485 switch (opt) { 580 switch (opt) {
486 case 'm': 581 case 'm':
487 MarkInterval = atoi(optarg) * 60; 582 MarkInterval = atoi(optarg) * 60;
@@ -489,11 +584,6 @@ extern int syslogd_main(int argc, char **argv)
489 case 'n': 584 case 'n':
490 doFork = FALSE; 585 doFork = FALSE;
491 break; 586 break;
492#ifdef BB_FEATURE_KLOGD
493 case 'K':
494 startKlogd = FALSE;
495 break;
496#endif
497 case 'O': 587 case 'O':
498 logFilePath = strdup(optarg); 588 logFilePath = strdup(optarg);
499 break; 589 break;
@@ -510,6 +600,11 @@ extern int syslogd_main(int argc, char **argv)
510 local_logging = TRUE; 600 local_logging = TRUE;
511 break; 601 break;
512#endif 602#endif
603#ifdef BB_FEATURE_IPC_SYSLOG
604 case 'C':
605 circular_logging = TRUE;
606 break;
607#endif
513 default: 608 default:
514 show_usage(); 609 show_usage();
515 } 610 }
@@ -521,6 +616,7 @@ extern int syslogd_main(int argc, char **argv)
521 local_logging = TRUE; 616 local_logging = TRUE;
522#endif 617#endif
523 618
619
524 /* Store away localhost's name before the fork */ 620 /* Store away localhost's name before the fork */
525 gethostname(LocalHostName, sizeof(LocalHostName)); 621 gethostname(LocalHostName, sizeof(LocalHostName));
526 if ((p = strchr(LocalHostName, '.'))) { 622 if ((p = strchr(LocalHostName, '.'))) {
@@ -529,13 +625,9 @@ extern int syslogd_main(int argc, char **argv)
529 625
530 umask(0); 626 umask(0);
531 627
532#ifdef BB_FEATURE_KLOGD 628#ifdef BB_FEATURE_IPC_SYSLOG
533 /* Start up the klogd process */ 629 if (circular_logging == TRUE ){
534 if (startKlogd == TRUE) { 630 ipcsyslog_init();
535 klogd_pid = fork();
536 if (klogd_pid == 0) {
537 daemon_init (argv, "klogd", doKlogd);
538 }
539 } 631 }
540#endif 632#endif
541 633
diff --git a/syslogd.c b/syslogd.c
index 1276201c3..a7f982a35 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -7,6 +7,8 @@
7 * 7 *
8 * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org> 8 * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org>
9 * 9 *
10 * "circular buffer" Copyright (C) 2001 by Gennady Feldman <gfeldman@cachier.com>
11 *
10 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 13 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or 14 * the Free Software Foundation; either version 2 of the License, or
@@ -40,25 +42,8 @@
40#include <sys/un.h> 42#include <sys/un.h>
41#include <sys/param.h> 43#include <sys/param.h>
42 44
43#if ! defined __GLIBC__ && ! defined __UCLIBC__
44#include <sys/syscall.h>
45#include <linux/unistd.h>
46typedef unsigned int socklen_t;
47
48#ifndef __alpha__
49# define __NR_klogctl __NR_syslog
50static inline _syscall3(int, klogctl, int, type, char *, b, int, len);
51#else /* __alpha__ */
52#define klogctl syslog
53#endif
54
55#else
56# include <sys/klog.h>
57#endif
58#include "busybox.h" 45#include "busybox.h"
59 46
60
61
62/* SYSLOG_NAMES defined to pull some extra junk from syslog.h */ 47/* SYSLOG_NAMES defined to pull some extra junk from syslog.h */
63#define SYSLOG_NAMES 48#define SYSLOG_NAMES
64#include <sys/syslog.h> 49#include <sys/syslog.h>
@@ -91,6 +76,184 @@ static int doRemoteLog = FALSE;
91static int local_logging = FALSE; 76static int local_logging = FALSE;
92#endif 77#endif
93 78
79/* circular buffer variables/structures */
80#ifdef BB_FEATURE_IPC_SYSLOG
81
82#include <sys/ipc.h>
83#include <sys/sem.h>
84#include <sys/shm.h>
85
86/* our shared key */
87static const long KEY_ID = 0x414e4547; /*"GENA"*/
88
89// Semaphore operation structures
90static struct shbuf_ds {
91 int size; // size of data written
92 int head; // start of message list
93 int tail; // end of message list
94 char data[1]; // data/messages
95} *buf = NULL; // shared memory pointer
96
97static struct sembuf SMwup[1] = {{1, -1, IPC_NOWAIT}}; // set SMwup
98static struct sembuf SMwdn[3] = {{0, 0}, {1, 0}, {1, +1}}; // set SMwdn
99
100static int shmid = -1; // ipc shared memory id
101static int s_semid = -1; // ipc semaphore id
102int data_size = 16000; // data size
103int shm_size = 16000 + sizeof(*buf); // our buffer size
104static int circular_logging = FALSE;
105
106/*
107 * sem_up - up()'s a semaphore.
108 */
109static inline void sem_up(int semid)
110{
111 if ( semop(semid, SMwup, 1) == -1 )
112 perror_msg_and_die("semop[SMwup]");
113}
114
115/*
116 * sem_down - down()'s a semaphore
117 */
118static inline void sem_down(int semid)
119{
120 if ( semop(semid, SMwdn, 2) == -1 )
121 perror_msg_and_die("semop[SMwdn]");
122}
123
124
125void ipcsyslog_cleanup(void){
126 printf("Exiting Syslogd!\n");
127 if (shmid != -1)
128 shmdt(buf);
129
130 if (shmid != -1)
131 shmctl(shmid, IPC_RMID, NULL);
132 if (s_semid != -1)
133 semctl(s_semid, 0, IPC_RMID, 0);
134}
135
136void ipcsyslog_init(void){
137 if (buf == NULL){
138 if ((shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023)) == -1)
139 perror_msg_and_die("shmget");
140
141
142 if ((buf = shmat(shmid, NULL, 0)) == NULL)
143 perror_msg_and_die("shmat");
144
145
146 buf->size=data_size;
147 buf->head=buf->tail=0;
148
149 // we'll trust the OS to set initial semval to 0 (let's hope)
150 if ((s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023)) == -1){
151 if (errno == EEXIST){
152 if ((s_semid = semget(KEY_ID, 2, 0)) == -1)
153 perror_msg_and_die("semget");
154 }else
155 perror_msg_and_die("semget");
156 }
157 }else{
158 printf("Buffer already allocated just grab the semaphore?");
159 }
160}
161
162/* write message to buffer */
163void circ_message(const char *msg){
164 int l=strlen(msg)+1; /* count the whole message w/ '\0' included */
165
166 sem_down(s_semid);
167
168 /*
169 * Circular Buffer Algorithm:
170 * --------------------------
171 *
172 * Start-off w/ empty buffer of specific size SHM_SIZ
173 * Start filling it up w/ messages. I use '\0' as separator to break up messages.
174 * This is also very handy since we can do printf on message.
175 *
176 * Once the buffer is full we need to get rid of the first message in buffer and
177 * insert the new message. (Note: if the message being added is >1 message then
178 * we will need to "remove" >1 old message from the buffer). The way this is done
179 * is the following:
180 * When we reach the end of the buffer we set a mark and start from the beginning.
181 * Now what about the beginning and end of the buffer? Well we have the "head"
182 * index/pointer which is the starting point for the messages and we have "tail"
183 * index/pointer which is the ending point for the messages. When we "display" the
184 * messages we start from the beginning and continue until we reach "tail". If we
185 * reach end of buffer, then we just start from the beginning (offset 0). "head" and
186 * "tail" are actually offsets from the beginning of the buffer.
187 *
188 * Note: This algorithm uses Linux IPC mechanism w/ shared memory and semaphores to provide
189 * a threasafe way of handling shared memory operations.
190 */
191 if ( (buf->tail + l) < buf->size ){
192 /* before we append the message we need to check the HEAD so that we won't
193 overwrite any of the message that we still need and adjust HEAD to point
194 to the next message! */
195 if ( buf->tail < buf->head){
196 if ( (buf->tail + l) >= buf->head ){
197 /* we need to move the HEAD to point to the next message
198 * Theoretically we have enough room to add the whole message to the
199 * buffer, because of the first outer IF statement, so we don't have
200 * to worry about overflows here!
201 */
202 int k= buf->tail + l - buf->head; /* we need to know how many bytes
203 we are overwriting to make
204 enough room */
205 char *c=memchr(buf->data+buf->head + k,'\0',buf->size - (buf->head + k));
206 if (c != NULL) {/* do a sanity check just in case! */
207 buf->head = c - buf->data + 1; /* we need to convert pointer to
208 offset + skip the '\0' since
209 we need to point to the beginning
210 of the next message */
211 /* Note: HEAD is only used to "retrieve" messages, it's not used
212 when writing messages into our buffer */
213 }else{ /* show an error message to know we messed up? */
214 printf("Weird! Can't find the terminator token??? \n");
215 buf->head=0;
216 }
217 }
218 } /* in other cases no overflows have been done yet, so we don't care! */
219
220 /* we should be ok to append the message now */
221 strncpy(buf->data + buf->tail,msg,l); /* append our message */
222 buf->tail+=l; /* count full message w/ '\0' terminating char */
223 }else{
224 /* we need to break up the message and "circle" it around */
225 char *c;
226 int k=buf->tail + l - buf->size; /* count # of bytes we don't fit */
227
228 /* We need to move HEAD! This is always the case since we are going
229 * to "circle" the message.
230 */
231 c=memchr(buf->data + k ,'\0', buf->size - k);
232
233 if (c != NULL) /* if we don't have '\0'??? weird!!! */{
234 /* move head pointer*/
235 buf->head=c-buf->data+1;
236
237 /* now write the first part of the message */
238 strncpy(buf->data + buf->tail, msg, l - k - 1);
239
240 /* ALWAYS terminate end of buffer w/ '\0' */
241 buf->data[buf->size-1]='\0';
242
243 /* now write out the rest of the string to the beginning of the buffer */
244 strcpy(buf->data, &msg[l-k-1]);
245
246 /* we need to place the TAIL at the end of the message */
247 buf->tail = k + 1;
248 }else{
249 printf("Weird! Can't find the terminator token from the beginning??? \n");
250 buf->head = buf->tail = 0; /* reset buffer, since it's probably corrupted */
251 }
252
253 }
254 sem_up(s_semid);
255}
256#endif
94/* Note: There is also a function called "message()" in init.c */ 257/* Note: There is also a function called "message()" in init.c */
95/* Print a message to the log file. */ 258/* Print a message to the log file. */
96static void message (char *fmt, ...) __attribute__ ((format (printf, 1, 2))); 259static void message (char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
@@ -104,6 +267,16 @@ static void message (char *fmt, ...)
104 fl.l_start = 0; 267 fl.l_start = 0;
105 fl.l_len = 1; 268 fl.l_len = 1;
106 269
270#ifdef BB_FEATURE_IPC_SYSLOG
271 if ((circular_logging == TRUE) && (buf != NULL)){
272 char b[1024];
273 va_start (arguments, fmt);
274 vsprintf (b, fmt, arguments);
275 va_end (arguments);
276 circ_message(b);
277
278 }else
279#endif
107 if ((fd = device_open (logFilePath, 280 if ((fd = device_open (logFilePath,
108 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND | 281 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
109 O_NONBLOCK)) >= 0) { 282 O_NONBLOCK)) >= 0) {
@@ -197,6 +370,10 @@ static void quit_signal(int sig)
197{ 370{
198 logMessage(0, "System log daemon exiting."); 371 logMessage(0, "System log daemon exiting.");
199 unlink(lfile); 372 unlink(lfile);
373#ifdef BB_FEATURE_IPC_SYSLOG
374 ipcsyslog_cleanup();
375#endif
376
200 exit(TRUE); 377 exit(TRUE);
201} 378}
202 379
@@ -382,85 +559,6 @@ static void doSyslogd (void)
382 } /* for main loop */ 559 } /* for main loop */
383} 560}
384 561
385#ifdef BB_FEATURE_KLOGD
386
387static void klogd_signal(int sig)
388{
389 klogctl(7, NULL, 0);
390 klogctl(0, 0, 0);
391 logMessage(0, "Kernel log daemon exiting.");
392 exit(TRUE);
393}
394
395static void doKlogd (void) __attribute__ ((noreturn));
396static void doKlogd (void)
397{
398 int priority = LOG_INFO;
399 char log_buffer[4096];
400 int i, n, lastc;
401 char *start;
402
403 /* Set up sig handlers */
404 signal(SIGINT, klogd_signal);
405 signal(SIGKILL, klogd_signal);
406 signal(SIGTERM, klogd_signal);
407 signal(SIGHUP, SIG_IGN);
408
409#ifdef BB_FEATURE_REMOTE_LOG
410 if (doRemoteLog == TRUE){
411 init_RemoteLog();
412 }
413#endif
414
415 logMessage(0, "klogd started: "
416 "BusyBox v" BB_VER " (" BB_BT ")");
417
418 /* "Open the log. Currently a NOP." */
419 klogctl(1, NULL, 0);
420
421 while (1) {
422 /* Use kernel syscalls */
423 memset(log_buffer, '\0', sizeof(log_buffer));
424 n = klogctl(2, log_buffer, sizeof(log_buffer));
425 if (n < 0) {
426 char message[80];
427
428 if (errno == EINTR)
429 continue;
430 snprintf(message, 79, "klogd: Error return from sys_sycall: " \
431 "%d - %s.\n", errno, strerror(errno));
432 logMessage(LOG_SYSLOG | LOG_ERR, message);
433 exit(1);
434 }
435
436 /* klogctl buffer parsing modelled after code in dmesg.c */
437 start=&log_buffer[0];
438 lastc='\0';
439 for (i=0; i<n; i++) {
440 if (lastc == '\0' && log_buffer[i] == '<') {
441 priority = 0;
442 i++;
443 while (isdigit(log_buffer[i])) {
444 priority = priority*10+(log_buffer[i]-'0');
445 i++;
446 }
447 if (log_buffer[i] == '>') i++;
448 start = &log_buffer[i];
449 }
450 if (log_buffer[i] == '\n') {
451 log_buffer[i] = '\0'; /* zero terminate this message */
452 logMessage(LOG_KERN | priority, start);
453 start = &log_buffer[i+1];
454 priority = LOG_INFO;
455 }
456 lastc = log_buffer[i];
457 }
458 }
459
460}
461
462#endif
463
464static void daemon_init (char **argv, char *dz, void fn (void)) 562static void daemon_init (char **argv, char *dz, void fn (void))
465{ 563{
466 setsid(); 564 setsid();
@@ -472,16 +570,13 @@ static void daemon_init (char **argv, char *dz, void fn (void))
472 570
473extern int syslogd_main(int argc, char **argv) 571extern int syslogd_main(int argc, char **argv)
474{ 572{
475 int opt, pid, klogd_pid; 573 int opt, pid;
476 int doFork = TRUE; 574 int doFork = TRUE;
477 575
478#ifdef BB_FEATURE_KLOGD
479 int startKlogd = TRUE;
480#endif
481 char *p; 576 char *p;
482 577
483 /* do normal option parsing */ 578 /* do normal option parsing */
484 while ((opt = getopt(argc, argv, "m:nKO:R:L")) > 0) { 579 while ((opt = getopt(argc, argv, "m:nO:R:LC")) > 0) {
485 switch (opt) { 580 switch (opt) {
486 case 'm': 581 case 'm':
487 MarkInterval = atoi(optarg) * 60; 582 MarkInterval = atoi(optarg) * 60;
@@ -489,11 +584,6 @@ extern int syslogd_main(int argc, char **argv)
489 case 'n': 584 case 'n':
490 doFork = FALSE; 585 doFork = FALSE;
491 break; 586 break;
492#ifdef BB_FEATURE_KLOGD
493 case 'K':
494 startKlogd = FALSE;
495 break;
496#endif
497 case 'O': 587 case 'O':
498 logFilePath = strdup(optarg); 588 logFilePath = strdup(optarg);
499 break; 589 break;
@@ -510,6 +600,11 @@ extern int syslogd_main(int argc, char **argv)
510 local_logging = TRUE; 600 local_logging = TRUE;
511 break; 601 break;
512#endif 602#endif
603#ifdef BB_FEATURE_IPC_SYSLOG
604 case 'C':
605 circular_logging = TRUE;
606 break;
607#endif
513 default: 608 default:
514 show_usage(); 609 show_usage();
515 } 610 }
@@ -521,6 +616,7 @@ extern int syslogd_main(int argc, char **argv)
521 local_logging = TRUE; 616 local_logging = TRUE;
522#endif 617#endif
523 618
619
524 /* Store away localhost's name before the fork */ 620 /* Store away localhost's name before the fork */
525 gethostname(LocalHostName, sizeof(LocalHostName)); 621 gethostname(LocalHostName, sizeof(LocalHostName));
526 if ((p = strchr(LocalHostName, '.'))) { 622 if ((p = strchr(LocalHostName, '.'))) {
@@ -529,13 +625,9 @@ extern int syslogd_main(int argc, char **argv)
529 625
530 umask(0); 626 umask(0);
531 627
532#ifdef BB_FEATURE_KLOGD 628#ifdef BB_FEATURE_IPC_SYSLOG
533 /* Start up the klogd process */ 629 if (circular_logging == TRUE ){
534 if (startKlogd == TRUE) { 630 ipcsyslog_init();
535 klogd_pid = fork();
536 if (klogd_pid == 0) {
537 daemon_init (argv, "klogd", doKlogd);
538 }
539 } 631 }
540#endif 632#endif
541 633
diff --git a/usage.h b/usage.h
index 8ba86d569..f241d3a04 100644
--- a/usage.h
+++ b/usage.h
@@ -468,6 +468,13 @@
468 "Options:\n" \ 468 "Options:\n" \
469 "\t-l\tList all signal names and numbers." 469 "\t-l\tList all signal names and numbers."
470 470
471#define klogd_trivial_usage \
472 "-n"
473#define klogd_full_usage \
474 "Kernel logger.\n"\
475 "Options:\n"\
476 "\t-n\tRun as a foreground process."
477
471#define length_trivial_usage \ 478#define length_trivial_usage \
472 "STRING" 479 "STRING"
473#define length_full_usage \ 480#define length_full_usage \
@@ -513,6 +520,12 @@
513#define logname_full_usage \ 520#define logname_full_usage \
514 "Print the name of the current user." 521 "Print the name of the current user."
515 522
523#define logread_trivial_usage \
524 ""
525
526#define logread_full_usage \
527 "Shows the messages from syslogd (using circular buffer)."
528
516#ifdef BB_FEATURE_LS_TIMESTAMPS 529#ifdef BB_FEATURE_LS_TIMESTAMPS
517 #define USAGE_LS_TIMESTAMPS(a) a 530 #define USAGE_LS_TIMESTAMPS(a) a
518#else 531#else
@@ -913,11 +926,6 @@
913 "Write all buffered filesystem blocks to disk." 926 "Write all buffered filesystem blocks to disk."
914 927
915 928
916#ifdef BB_FEATURE_KLOGD
917 #define USAGE_KLOGD(a) a
918#else
919 #define USAGE_KLOGD(a)
920#endif
921#ifdef BB_FEATURE_REMOTE_LOG 929#ifdef BB_FEATURE_REMOTE_LOG
922 #define USAGE_REMOTE_LOG(a) a 930 #define USAGE_REMOTE_LOG(a) a
923#else 931#else
@@ -926,12 +934,11 @@
926#define syslogd_trivial_usage \ 934#define syslogd_trivial_usage \
927 "[OPTION]..." 935 "[OPTION]..."
928#define syslogd_full_usage \ 936#define syslogd_full_usage \
929 "Linux system and kernel (provides klogd) logging utility.\n" \ 937 "Linux system and kernel logging utility.\n" \
930 "Note that this version of syslogd/klogd ignores /etc/syslog.conf.\n\n" \ 938 "Note that this version of syslogd ignores /etc/syslog.conf.\n\n" \
931 "Options:\n" \ 939 "Options:\n" \
932 "\t-m NUM\t\tInterval between MARK lines (default=20min, 0=off)\n" \ 940 "\t-m NUM\t\tInterval between MARK lines (default=20min, 0=off)\n" \
933 "\t-n\t\tRun as a foreground process\n" \ 941 "\t-n\t\tRun as a foreground process\n" \
934 USAGE_KLOGD("\t-K\t\tDo not start up the klogd process\n") \
935 "\t-O FILE\t\tUse an alternate log file (default=/var/log/messages)" \ 942 "\t-O FILE\t\tUse an alternate log file (default=/var/log/messages)" \
936 USAGE_REMOTE_LOG( \ 943 USAGE_REMOTE_LOG( \
937 "\n\t-R HOST[:PORT]\tLog to IP or hostname on PORT (default PORT=514/UDP)\n" \ 944 "\n\t-R HOST[:PORT]\tLog to IP or hostname on PORT (default PORT=514/UDP)\n" \
diff --git a/utility.c b/utility.c
index e54a3ea65..c557130b9 100644
--- a/utility.c
+++ b/utility.c
@@ -77,6 +77,10 @@ const char mtab_file[] = "/proc/mounts";
77# endif 77# endif
78#endif 78#endif
79 79
80#if defined(BB_KLOGD) || defined(BB_LOGGER)
81#include <syslog.h>
82#endif
83
80static struct BB_applet *applet_using; 84static struct BB_applet *applet_using;
81 85
82extern void show_usage(void) 86extern void show_usage(void)
@@ -1828,6 +1832,20 @@ void chomp(char *s)
1828} 1832}
1829#endif 1833#endif
1830 1834
1835#if defined(BB_KLOGD) || defined(BB_LOGGER)
1836void syslog_msg_with_name(const char *name, int facility, int pri, const char *msg)
1837{
1838 openlog(name, 0, facility);
1839 syslog(pri, "%s", msg);
1840 closelog();
1841}
1842
1843void syslog_msg(int facility, int pri, const char *msg)
1844{
1845 syslog_msg_with_name(applet_using->name, facility, pri, msg);
1846}
1847#endif
1848
1831#if defined(BB_SH) 1849#if defined(BB_SH)
1832void trim(char *s) 1850void trim(char *s)
1833{ 1851{