diff options
author | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 1999-11-25 07:30:46 +0000 |
---|---|---|
committer | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 1999-11-25 07:30:46 +0000 |
commit | 2dc5d63dfcb30058e2368a2c3dd86f539d2c2075 (patch) | |
tree | a177e322b9e77485a609429acfdc43824eca0222 /syslogd.c | |
parent | dc1e72211f7f42a0d6a46a409e74c82c0b7b6a51 (diff) | |
download | busybox-w32-2dc5d63dfcb30058e2368a2c3dd86f539d2c2075.tar.gz busybox-w32-2dc5d63dfcb30058e2368a2c3dd86f539d2c2075.tar.bz2 busybox-w32-2dc5d63dfcb30058e2368a2c3dd86f539d2c2075.zip |
Stuf
git-svn-id: svn://busybox.net/trunk/busybox@118 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'syslogd.c')
-rw-r--r-- | syslogd.c | 316 |
1 files changed, 263 insertions, 53 deletions
@@ -1,86 +1,296 @@ | |||
1 | /* userver.c - simple server for Unix domain sockets */ | 1 | /* |
2 | 2 | * Mini syslogd implementation for busybox | |
3 | /* Waits for a connection on the ./sample-socket Unix domain | 3 | * |
4 | socket. Once a connection has been established, copy data | 4 | * Copyright (C) 1999 by Lineo, inc. |
5 | from the socket to stdout until the other end closes the | 5 | * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org> |
6 | connection, and then wait for another connection to the socket. */ | 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 | */ | ||
7 | 22 | ||
23 | #include "internal.h" | ||
8 | #include <stdio.h> | 24 | #include <stdio.h> |
9 | #include <sys/socket.h> | 25 | #include <sys/socket.h> |
10 | #include <sys/un.h> | 26 | #include <sys/un.h> |
11 | #include <unistd.h> | 27 | #include <unistd.h> |
28 | #include <time.h> | ||
29 | #include <sys/types.h> | ||
30 | #include <sys/stat.h> | ||
31 | #include <fcntl.h> | ||
32 | #include <signal.h> | ||
33 | #include <ctype.h> | ||
34 | #include <netdb.h> | ||
35 | |||
36 | |||
37 | /* SYSLOG_NAMES defined to pull some extra junk from syslog.h */ | ||
38 | #define SYSLOG_NAMES | ||
39 | #include <sys/syslog.h> | ||
40 | |||
41 | /* Path for the file where all log messages are written */ | ||
42 | #define __LOG_FILE "/var/log/messages" | ||
43 | /* Path to the current console device */ | ||
44 | #define __DEV_CONSOLE "/dev/console" | ||
45 | |||
46 | |||
47 | static char* logFilePath = __LOG_FILE; | ||
48 | /* interval between marks in seconds */ | ||
49 | static int MarkInterval = 20*60; | ||
50 | /* localhost's name */ | ||
51 | static char LocalHostName[32]; | ||
12 | 52 | ||
13 | #define _PATH_LOG "/dev/log" | 53 | static const char syslogd_usage[] = |
54 | "syslogd [OPTION]...\n\n" | ||
55 | "Linux system logging utility.\n\n" | ||
56 | "Options:\n" | ||
57 | "\t-m\tChange the mark timestamp interval. default=20min. 0=off\n" | ||
58 | "\t-n\tDo not fork into the background (for when run by init)\n" | ||
59 | "\t-O\tSpecify an alternate log file. default=/var/log/messages\n"; | ||
14 | 60 | ||
15 | 61 | ||
16 | /* issue an error message via perror() and terminate the program */ | 62 | |
17 | void die(char * message) { | 63 | /* try to open up the specified device */ |
18 | perror(message); | 64 | static int device_open(char *device, int mode) |
19 | exit(1); | 65 | { |
66 | int m, f, fd = -1; | ||
67 | |||
68 | m = mode | O_NONBLOCK; | ||
69 | |||
70 | /* Retry up to 5 times */ | ||
71 | for (f = 0; f < 5; f++) | ||
72 | if ((fd = open(device, m)) >= 0) | ||
73 | break; | ||
74 | if (fd < 0) | ||
75 | return fd; | ||
76 | /* Reset original flags. */ | ||
77 | if (m != mode) | ||
78 | fcntl(fd, F_SETFL, mode); | ||
79 | return fd; | ||
20 | } | 80 | } |
21 | 81 | ||
22 | /* Copies data from file descriptor 'from' to file descriptor 'to' | 82 | /* print a message to the log file */ |
23 | until nothing is left to be copied. Exits if an error occurs. */ | 83 | static void message(char *fmt, ...) |
24 | void copyData(int from, int to) { | 84 | { |
25 | char buf[1024]; | 85 | int fd; |
26 | int amount; | 86 | va_list arguments; |
27 | 87 | ||
28 | while ((amount = read(from, buf, sizeof(buf))) > 0) { | 88 | if ((fd = device_open(logFilePath, O_WRONLY|O_CREAT|O_NOCTTY|O_APPEND|O_NONBLOCK)) >= 0) { |
29 | if (write(to, buf, amount) != amount) { | 89 | va_start(arguments, fmt); |
30 | die("write"); | 90 | vdprintf(fd, fmt, arguments); |
31 | return; | 91 | va_end(arguments); |
32 | } | 92 | close(fd); |
93 | } else { | ||
94 | /* Always send console messages to /dev/console so people will see them. */ | ||
95 | if ((fd = device_open(__DEV_CONSOLE, O_WRONLY|O_NOCTTY|O_NONBLOCK)) >= 0) { | ||
96 | va_start(arguments, fmt); | ||
97 | vdprintf(fd, fmt, arguments); | ||
98 | va_end(arguments); | ||
99 | close(fd); | ||
100 | } else { | ||
101 | fprintf(stderr, "Bummer, can't print: "); | ||
102 | va_start(arguments, fmt); | ||
103 | vfprintf(stderr, fmt, arguments); | ||
104 | fflush(stderr); | ||
105 | va_end(arguments); | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | |||
110 | static void logMessage( int pri, char* msg) | ||
111 | { | ||
112 | time_t now; | ||
113 | char *timestamp; | ||
114 | static char res[20]; | ||
115 | CODE *c_pri, *c_fac; | ||
116 | |||
117 | for (c_fac=facilitynames; c_fac->c_name && !(c_fac->c_val==LOG_FAC(pri)<<3); c_fac++); | ||
118 | for (c_pri=prioritynames; c_pri->c_name && !(c_pri->c_val==LOG_PRI(pri)); c_pri++); | ||
119 | if (*c_fac->c_name=='\0' || *c_pri->c_name=='\0') | ||
120 | snprintf (res, sizeof(res), "<%d>", pri); | ||
121 | else | ||
122 | snprintf (res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name); | ||
123 | |||
124 | if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' || | ||
125 | msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') | ||
126 | { | ||
127 | time(&now); | ||
128 | timestamp = ctime(&now) + 4; | ||
129 | timestamp[15] = '\0'; | ||
130 | } else { | ||
131 | timestamp = msg; | ||
132 | timestamp[15] = '\0'; | ||
133 | msg += 16; | ||
33 | } | 134 | } |
34 | if (amount < 0) | 135 | |
35 | die("read"); | 136 | /* todo: supress duplicates */ |
137 | |||
138 | /* now spew out the message to wherever it is supposed to go */ | ||
139 | message( "%s %s %s %s\n", timestamp, LocalHostName, res, msg); | ||
36 | } | 140 | } |
37 | 141 | ||
142 | static void quit_signal(int sig) | ||
143 | { | ||
144 | logMessage(LOG_SYSLOG|LOG_INFO, "syslogd exiting"); | ||
145 | exit( TRUE); | ||
146 | } | ||
38 | 147 | ||
39 | int main(void) { | 148 | static void restart_signal(int sig) |
40 | struct sockaddr_un address; | 149 | { |
150 | /* pretend to restart */ | ||
151 | logMessage(LOG_SYSLOG|LOG_INFO, "syslogd restarting"); | ||
152 | } | ||
153 | |||
154 | static void domark(int sig) | ||
155 | { | ||
156 | if (MarkInterval > 0) { | ||
157 | logMessage(LOG_SYSLOG|LOG_INFO, "-- MARK --"); | ||
158 | signal(SIGALRM, domark); | ||
159 | alarm(MarkInterval); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | static void doSyslogd(void) | ||
164 | { | ||
165 | struct sockaddr_un sunx; | ||
41 | int fd, conn; | 166 | int fd, conn; |
42 | size_t addrLength; | 167 | size_t addrLength; |
168 | char buf[1024]; | ||
169 | char *q, *p = buf; | ||
170 | int readSize; | ||
43 | 171 | ||
44 | /* Remove any preexisting socket (or other file) */ | 172 | /* Remove any preexisting socket/file */ |
45 | unlink(_PATH_LOG); | 173 | unlink(_PATH_LOG); |
46 | 174 | ||
47 | memset(&address, 0, sizeof(address)); | 175 | /* Set up sig handlers */ |
48 | address.sun_family = AF_UNIX; /* Unix domain socket */ | 176 | signal(SIGINT, quit_signal); |
49 | strncpy(address.sun_path, _PATH_LOG, sizeof(address.sun_path)); | 177 | signal(SIGTERM, quit_signal); |
178 | signal(SIGQUIT, quit_signal); | ||
179 | signal(SIGHUP, restart_signal); | ||
180 | signal(SIGALRM, domark); | ||
181 | alarm(MarkInterval); | ||
50 | 182 | ||
51 | if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) | 183 | memset(&sunx, 0, sizeof(sunx)); |
52 | die("socket"); | 184 | sunx.sun_family = AF_UNIX; /* Unix domain socket */ |
53 | 185 | strncpy(sunx.sun_path, _PATH_LOG, sizeof(sunx.sun_path)); | |
54 | 186 | if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0 ) { | |
55 | /* The total length of the address includes the sun_family | 187 | perror("Couldn't obtain descriptor for socket " _PATH_LOG); |
56 | element */ | 188 | exit( FALSE); |
57 | addrLength = sizeof(address.sun_family) + | 189 | } |
58 | strlen(address.sun_path); | ||
59 | 190 | ||
60 | if (bind(fd, (struct sockaddr *) &address, addrLength)) | 191 | addrLength = sizeof(sunx.sun_family) + strlen(sunx.sun_path); |
61 | die("bind"); | 192 | if ( (bind(fd, (struct sockaddr *) &sunx, addrLength)) || |
193 | (chmod(_PATH_LOG, 0666) < 0) || | ||
194 | (listen(fd, 5)) ) | ||
195 | { | ||
196 | perror("Could not connect to socket " _PATH_LOG); | ||
197 | exit( FALSE); | ||
198 | } | ||
199 | |||
200 | |||
201 | /* Get localhost's name */ | ||
202 | gethostname(LocalHostName, sizeof(LocalHostName)); | ||
203 | if ( (p = strchr(LocalHostName, '.')) ) { | ||
204 | *p++ = '\0'; | ||
205 | } | ||
206 | |||
207 | logMessage(LOG_SYSLOG|LOG_INFO, "syslogd started: " | ||
208 | "BusyBox v" BB_VER " (" BB_BT ") multi-call binary"); | ||
62 | 209 | ||
63 | if (chmod(_PATH_LOG, 0666) < 0) | ||
64 | die("chmod"); | ||
65 | 210 | ||
66 | if (listen(fd, 5)) | 211 | while ((conn = accept(fd, (struct sockaddr *) &sunx, |
67 | die("listen"); | 212 | &addrLength)) >= 0) |
213 | { | ||
214 | while ((readSize=read(conn, buf, sizeof(buf))) > 0) | ||
215 | { | ||
216 | char line[1025]; | ||
217 | unsigned char c; | ||
218 | int pri = (LOG_USER|LOG_NOTICE); | ||
68 | 219 | ||
220 | memset (line, 0, sizeof(line)); | ||
221 | p = buf; | ||
222 | q = line; | ||
223 | while ( p && (c = *p) && q < &line[sizeof(line) - 1]) { | ||
224 | if (c == '<') { | ||
225 | /* Parse the magic priority number */ | ||
226 | pri = 0; | ||
227 | while (isdigit(*(++p))) { | ||
228 | pri = 10 * pri + (*p - '0'); | ||
229 | } | ||
230 | if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) | ||
231 | pri = (LOG_USER|LOG_NOTICE); | ||
232 | } else if (c == '\n') { | ||
233 | *q++ = ' '; | ||
234 | } else if (iscntrl(c)&&(c<0177)) { | ||
235 | *q++ = '^'; | ||
236 | *q++ = c ^ 0100; | ||
237 | } else { | ||
238 | *q++ = c; | ||
239 | } | ||
240 | p++; | ||
241 | } | ||
242 | *q = '\0'; | ||
69 | 243 | ||
70 | while ((conn = accept(fd, (struct sockaddr *) &address, | 244 | /* Now log it */ |
71 | &addrLength)) >= 0) { | 245 | logMessage( pri, line); |
72 | printf("---- getting data\n"); | 246 | } |
73 | copyData(conn, fileno(stdout)); | ||
74 | printf("---- done\n"); | ||
75 | close(conn); | 247 | close(conn); |
76 | } | 248 | } |
77 | 249 | ||
78 | if (conn < 0) | ||
79 | die("accept"); | ||
80 | |||
81 | close(fd); | 250 | close(fd); |
82 | return 0; | ||
83 | } | 251 | } |
84 | 252 | ||
85 | 253 | ||
254 | extern int syslogd_main(int argc, char **argv) | ||
255 | { | ||
256 | int pid; | ||
257 | int doFork = TRUE; | ||
258 | |||
259 | while (--argc > 0 && **(++argv) == '-') { | ||
260 | while (*(++(*argv))) { | ||
261 | switch (**argv) { | ||
262 | case 'm': | ||
263 | if (--argc == 0) { | ||
264 | usage(syslogd_usage); | ||
265 | } | ||
266 | MarkInterval = atoi(*(++argv))*60; | ||
267 | break; | ||
268 | case 'n': | ||
269 | doFork = FALSE; | ||
270 | break; | ||
271 | case 'O': | ||
272 | if (--argc == 0) { | ||
273 | usage(syslogd_usage); | ||
274 | } | ||
275 | logFilePath = *(++argv); | ||
276 | break; | ||
277 | default: | ||
278 | usage(syslogd_usage); | ||
279 | } | ||
280 | } | ||
281 | } | ||
282 | |||
283 | if (doFork == TRUE) { | ||
284 | pid = fork(); | ||
285 | if ( pid < 0 ) | ||
286 | exit( pid); | ||
287 | else if ( pid == 0 ) { | ||
288 | doSyslogd(); | ||
289 | } | ||
290 | } else { | ||
291 | doSyslogd(); | ||
292 | } | ||
293 | exit( TRUE); | ||
294 | } | ||
295 | |||
86 | 296 | ||