blob: e5ddd3b8202e96eaf0cd1db509826eda28693eee [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Eric Andersen3843e961999-11-25 07:30:46 +00002/*
3 * Mini syslogd implementation for busybox
4 *
Eric Andersen8ec10a92001-01-27 09:33:39 +00005 * Copyright (C) 1999,2000,2001 by Lineo, inc.
Eric Andersen3843e961999-11-25 07:30:46 +00006 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
7 *
Erik Andersenf13df372000-04-18 23:51:51 +00008 * Copyright (C) 2000 by Karl M. Hegbloom <karlheg@debian.org>
9 *
Mark Whitley6317c4b2001-03-12 22:51:50 +000010 * "circular buffer" Copyright (C) 2001 by Gennady Feldman <gfeldman@cachier.com>
11 *
Mark Whitley6bff9cc2001-03-12 23:41:34 +000012 * Maintainer: Gennady Feldman <gena01@cachier.com> as of Mar 12, 2001
13 *
Eric Andersen3843e961999-11-25 07:30:46 +000014 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 *
28 */
Eric Andersenb99df0f1999-11-24 09:04:33 +000029
Eric Andersen67e32302000-06-19 17:48:02 +000030#include <stdio.h>
31#include <stdlib.h>
Eric Andersen3843e961999-11-25 07:30:46 +000032#include <ctype.h>
Eric Andersenb186d981999-12-03 09:19:54 +000033#include <errno.h>
Erik Andersen983b51b2000-04-04 18:14:25 +000034#include <fcntl.h>
35#include <netdb.h>
Eric Andersenb186d981999-12-03 09:19:54 +000036#include <paths.h>
Erik Andersen983b51b2000-04-04 18:14:25 +000037#include <signal.h>
38#include <stdarg.h>
Eric Andersen67e32302000-06-19 17:48:02 +000039#include <time.h>
Eric Andersened3ef502001-01-27 08:24:39 +000040#include <string.h>
Eric Andersen67e32302000-06-19 17:48:02 +000041#include <unistd.h>
Erik Andersen983b51b2000-04-04 18:14:25 +000042#include <sys/socket.h>
Erik Andersen983b51b2000-04-04 18:14:25 +000043#include <sys/types.h>
44#include <sys/un.h>
Erik Andersen7d6ba572000-04-19 20:02:50 +000045#include <sys/param.h>
Eric Andersenb186d981999-12-03 09:19:54 +000046
Eric Andersencbe31da2001-02-20 06:14:08 +000047#include "busybox.h"
Eric Andersen67e32302000-06-19 17:48:02 +000048
Eric Andersen3843e961999-11-25 07:30:46 +000049/* SYSLOG_NAMES defined to pull some extra junk from syslog.h */
50#define SYSLOG_NAMES
51#include <sys/syslog.h>
Eric Andersenced2cef2000-07-20 23:41:24 +000052#include <sys/uio.h>
Eric Andersen3843e961999-11-25 07:30:46 +000053
54/* Path for the file where all log messages are written */
Erik Andersen983b51b2000-04-04 18:14:25 +000055#define __LOG_FILE "/var/log/messages"
Eric Andersen3843e961999-11-25 07:30:46 +000056
Erik Andersen983b51b2000-04-04 18:14:25 +000057/* Path to the unix socket */
Eric Andersenf6aa13d2001-03-23 17:08:21 +000058static char lfile[BUFSIZ] = "";
Eric Andersen3843e961999-11-25 07:30:46 +000059
Erik Andersene49d5ec2000-02-08 19:58:47 +000060static char *logFilePath = __LOG_FILE;
61
Eric Andersen3843e961999-11-25 07:30:46 +000062/* interval between marks in seconds */
Erik Andersene49d5ec2000-02-08 19:58:47 +000063static int MarkInterval = 20 * 60;
64
Eric Andersen3843e961999-11-25 07:30:46 +000065/* localhost's name */
66static char LocalHostName[32];
67
Eric Andersenced2cef2000-07-20 23:41:24 +000068#ifdef BB_FEATURE_REMOTE_LOG
69#include <netinet/in.h>
70/* udp socket for logging to remote host */
Eric Andersenbf2b8ae2000-12-08 19:52:01 +000071static int remotefd = -1;
Eric Andersenced2cef2000-07-20 23:41:24 +000072/* where do we log? */
73static char *RemoteHost;
74/* what port to log to? */
Eric Andersenbf2b8ae2000-12-08 19:52:01 +000075static int RemotePort = 514;
Eric Andersenced2cef2000-07-20 23:41:24 +000076/* To remote log or not to remote log, that is the question. */
Eric Andersenbf2b8ae2000-12-08 19:52:01 +000077static int doRemoteLog = FALSE;
Eric Andersen70d09ed2000-12-11 16:24:16 +000078static int local_logging = FALSE;
Eric Andersenced2cef2000-07-20 23:41:24 +000079#endif
80
Mark Whitley6317c4b2001-03-12 22:51:50 +000081/* circular buffer variables/structures */
82#ifdef BB_FEATURE_IPC_SYSLOG
83
84#include <sys/ipc.h>
85#include <sys/sem.h>
86#include <sys/shm.h>
87
88/* our shared key */
89static const long KEY_ID = 0x414e4547; /*"GENA"*/
90
91// Semaphore operation structures
92static struct shbuf_ds {
93 int size; // size of data written
94 int head; // start of message list
95 int tail; // end of message list
96 char data[1]; // data/messages
97} *buf = NULL; // shared memory pointer
98
99static struct sembuf SMwup[1] = {{1, -1, IPC_NOWAIT}}; // set SMwup
100static struct sembuf SMwdn[3] = {{0, 0}, {1, 0}, {1, +1}}; // set SMwdn
101
102static int shmid = -1; // ipc shared memory id
103static int s_semid = -1; // ipc semaphore id
104int data_size = 16000; // data size
105int shm_size = 16000 + sizeof(*buf); // our buffer size
106static int circular_logging = FALSE;
107
108/*
109 * sem_up - up()'s a semaphore.
110 */
111static inline void sem_up(int semid)
112{
113 if ( semop(semid, SMwup, 1) == -1 )
114 perror_msg_and_die("semop[SMwup]");
115}
116
117/*
118 * sem_down - down()'s a semaphore
119 */
120static inline void sem_down(int semid)
121{
122 if ( semop(semid, SMwdn, 2) == -1 )
123 perror_msg_and_die("semop[SMwdn]");
124}
125
126
127void ipcsyslog_cleanup(void){
128 printf("Exiting Syslogd!\n");
129 if (shmid != -1)
130 shmdt(buf);
131
132 if (shmid != -1)
133 shmctl(shmid, IPC_RMID, NULL);
134 if (s_semid != -1)
135 semctl(s_semid, 0, IPC_RMID, 0);
136}
137
138void ipcsyslog_init(void){
139 if (buf == NULL){
140 if ((shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023)) == -1)
141 perror_msg_and_die("shmget");
142
143
144 if ((buf = shmat(shmid, NULL, 0)) == NULL)
145 perror_msg_and_die("shmat");
146
147
148 buf->size=data_size;
149 buf->head=buf->tail=0;
150
151 // we'll trust the OS to set initial semval to 0 (let's hope)
152 if ((s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023)) == -1){
153 if (errno == EEXIST){
154 if ((s_semid = semget(KEY_ID, 2, 0)) == -1)
155 perror_msg_and_die("semget");
156 }else
157 perror_msg_and_die("semget");
158 }
159 }else{
160 printf("Buffer already allocated just grab the semaphore?");
161 }
162}
163
164/* write message to buffer */
165void circ_message(const char *msg){
166 int l=strlen(msg)+1; /* count the whole message w/ '\0' included */
167
168 sem_down(s_semid);
169
170 /*
171 * Circular Buffer Algorithm:
172 * --------------------------
173 *
174 * Start-off w/ empty buffer of specific size SHM_SIZ
175 * Start filling it up w/ messages. I use '\0' as separator to break up messages.
176 * This is also very handy since we can do printf on message.
177 *
178 * Once the buffer is full we need to get rid of the first message in buffer and
179 * insert the new message. (Note: if the message being added is >1 message then
180 * we will need to "remove" >1 old message from the buffer). The way this is done
181 * is the following:
182 * When we reach the end of the buffer we set a mark and start from the beginning.
183 * Now what about the beginning and end of the buffer? Well we have the "head"
184 * index/pointer which is the starting point for the messages and we have "tail"
185 * index/pointer which is the ending point for the messages. When we "display" the
186 * messages we start from the beginning and continue until we reach "tail". If we
187 * reach end of buffer, then we just start from the beginning (offset 0). "head" and
188 * "tail" are actually offsets from the beginning of the buffer.
189 *
190 * Note: This algorithm uses Linux IPC mechanism w/ shared memory and semaphores to provide
191 * a threasafe way of handling shared memory operations.
192 */
193 if ( (buf->tail + l) < buf->size ){
194 /* before we append the message we need to check the HEAD so that we won't
195 overwrite any of the message that we still need and adjust HEAD to point
196 to the next message! */
197 if ( buf->tail < buf->head){
198 if ( (buf->tail + l) >= buf->head ){
199 /* we need to move the HEAD to point to the next message
200 * Theoretically we have enough room to add the whole message to the
201 * buffer, because of the first outer IF statement, so we don't have
202 * to worry about overflows here!
203 */
204 int k= buf->tail + l - buf->head; /* we need to know how many bytes
205 we are overwriting to make
206 enough room */
207 char *c=memchr(buf->data+buf->head + k,'\0',buf->size - (buf->head + k));
208 if (c != NULL) {/* do a sanity check just in case! */
209 buf->head = c - buf->data + 1; /* we need to convert pointer to
210 offset + skip the '\0' since
211 we need to point to the beginning
212 of the next message */
213 /* Note: HEAD is only used to "retrieve" messages, it's not used
214 when writing messages into our buffer */
215 }else{ /* show an error message to know we messed up? */
216 printf("Weird! Can't find the terminator token??? \n");
217 buf->head=0;
218 }
219 }
220 } /* in other cases no overflows have been done yet, so we don't care! */
221
222 /* we should be ok to append the message now */
223 strncpy(buf->data + buf->tail,msg,l); /* append our message */
224 buf->tail+=l; /* count full message w/ '\0' terminating char */
225 }else{
226 /* we need to break up the message and "circle" it around */
227 char *c;
228 int k=buf->tail + l - buf->size; /* count # of bytes we don't fit */
229
230 /* We need to move HEAD! This is always the case since we are going
231 * to "circle" the message.
232 */
233 c=memchr(buf->data + k ,'\0', buf->size - k);
234
235 if (c != NULL) /* if we don't have '\0'??? weird!!! */{
236 /* move head pointer*/
237 buf->head=c-buf->data+1;
238
239 /* now write the first part of the message */
240 strncpy(buf->data + buf->tail, msg, l - k - 1);
241
242 /* ALWAYS terminate end of buffer w/ '\0' */
243 buf->data[buf->size-1]='\0';
244
245 /* now write out the rest of the string to the beginning of the buffer */
246 strcpy(buf->data, &msg[l-k-1]);
247
248 /* we need to place the TAIL at the end of the message */
249 buf->tail = k + 1;
250 }else{
251 printf("Weird! Can't find the terminator token from the beginning??? \n");
252 buf->head = buf->tail = 0; /* reset buffer, since it's probably corrupted */
253 }
254
255 }
256 sem_up(s_semid);
257}
258#endif
Erik Andersenc053e412000-03-21 01:31:24 +0000259/* Note: There is also a function called "message()" in init.c */
Erik Andersen983b51b2000-04-04 18:14:25 +0000260/* Print a message to the log file. */
Erik Andersenf13df372000-04-18 23:51:51 +0000261static void message (char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
262static void message (char *fmt, ...)
Eric Andersen3843e961999-11-25 07:30:46 +0000263{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000264 int fd;
Erik Andersene3ed1562000-04-19 18:52:56 +0000265 struct flock fl;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000266 va_list arguments;
Eric Andersen3843e961999-11-25 07:30:46 +0000267
Erik Andersene3ed1562000-04-19 18:52:56 +0000268 fl.l_whence = SEEK_SET;
269 fl.l_start = 0;
270 fl.l_len = 1;
271
Mark Whitley6317c4b2001-03-12 22:51:50 +0000272#ifdef BB_FEATURE_IPC_SYSLOG
273 if ((circular_logging == TRUE) && (buf != NULL)){
274 char b[1024];
275 va_start (arguments, fmt);
276 vsprintf (b, fmt, arguments);
277 va_end (arguments);
278 circ_message(b);
279
280 }else
281#endif
Erik Andersenf13df372000-04-18 23:51:51 +0000282 if ((fd = device_open (logFilePath,
283 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
284 O_NONBLOCK)) >= 0) {
Erik Andersene3ed1562000-04-19 18:52:56 +0000285 fl.l_type = F_WRLCK;
286 fcntl (fd, F_SETLKW, &fl);
Erik Andersenf13df372000-04-18 23:51:51 +0000287 va_start (arguments, fmt);
288 vdprintf (fd, fmt, arguments);
289 va_end (arguments);
Erik Andersene3ed1562000-04-19 18:52:56 +0000290 fl.l_type = F_UNLCK;
291 fcntl (fd, F_SETLKW, &fl);
Erik Andersenf13df372000-04-18 23:51:51 +0000292 close (fd);
Eric Andersen3843e961999-11-25 07:30:46 +0000293 } else {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000294 /* Always send console messages to /dev/console so people will see them. */
Erik Andersenf13df372000-04-18 23:51:51 +0000295 if ((fd = device_open (_PATH_CONSOLE,
296 O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) {
297 va_start (arguments, fmt);
298 vdprintf (fd, fmt, arguments);
299 va_end (arguments);
300 close (fd);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000301 } else {
Erik Andersenf13df372000-04-18 23:51:51 +0000302 fprintf (stderr, "Bummer, can't print: ");
303 va_start (arguments, fmt);
304 vfprintf (stderr, fmt, arguments);
305 fflush (stderr);
306 va_end (arguments);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000307 }
Eric Andersen3843e961999-11-25 07:30:46 +0000308 }
Eric Andersenb99df0f1999-11-24 09:04:33 +0000309}
310
Erik Andersenf13df372000-04-18 23:51:51 +0000311static void logMessage (int pri, char *msg)
Eric Andersen3843e961999-11-25 07:30:46 +0000312{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000313 time_t now;
314 char *timestamp;
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000315 static char res[20] = "";
Erik Andersene49d5ec2000-02-08 19:58:47 +0000316 CODE *c_pri, *c_fac;
Eric Andersenb99df0f1999-11-24 09:04:33 +0000317
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000318 if (pri != 0) {
319 for (c_fac = facilitynames;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000320 c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++);
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000321 for (c_pri = prioritynames;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000322 c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++);
Matt Kraai5a964f92000-12-11 20:13:37 +0000323 if (c_fac->c_name == NULL || c_pri->c_name == NULL)
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000324 snprintf(res, sizeof(res), "<%d>", pri);
325 else
326 snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name);
327 }
Eric Andersen3843e961999-11-25 07:30:46 +0000328
Erik Andersene49d5ec2000-02-08 19:58:47 +0000329 if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' ||
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000330 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000331 time(&now);
332 timestamp = ctime(&now) + 4;
333 timestamp[15] = '\0';
334 } else {
335 timestamp = msg;
336 timestamp[15] = '\0';
337 msg += 16;
338 }
Eric Andersen3843e961999-11-25 07:30:46 +0000339
Erik Andersene49d5ec2000-02-08 19:58:47 +0000340 /* todo: supress duplicates */
Eric Andersen3843e961999-11-25 07:30:46 +0000341
Eric Andersenced2cef2000-07-20 23:41:24 +0000342#ifdef BB_FEATURE_REMOTE_LOG
343 /* send message to remote logger */
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000344 if ( -1 != remotefd){
Mark Whitley59ab0252001-01-23 22:30:04 +0000345static const int IOV_COUNT = 2;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000346 struct iovec iov[IOV_COUNT];
347 struct iovec *v = iov;
Eric Andersenced2cef2000-07-20 23:41:24 +0000348
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000349 bzero(&res, sizeof(res));
350 snprintf(res, sizeof(res), "<%d>", pri);
351 v->iov_base = res ;
352 v->iov_len = strlen(res);
353 v++;
Eric Andersenced2cef2000-07-20 23:41:24 +0000354
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000355 v->iov_base = msg;
356 v->iov_len = strlen(msg);
357
358 if ( -1 == writev(remotefd,iov, IOV_COUNT)){
359 error_msg_and_die("syslogd: cannot write to remote file handle on"
Matt Kraaidd19c692001-01-31 19:00:21 +0000360 "%s:%d",RemoteHost,RemotePort);
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000361 }
362 }
363 if (local_logging == TRUE)
Eric Andersenced2cef2000-07-20 23:41:24 +0000364#endif
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000365 /* now spew out the message to wherever it is supposed to go */
366 message("%s %s %s %s\n", timestamp, LocalHostName, res, msg);
Eric Andersen76fef0a2000-12-08 19:41:21 +0000367
Eric Andersenced2cef2000-07-20 23:41:24 +0000368
Eric Andersen3843e961999-11-25 07:30:46 +0000369}
370
371static void quit_signal(int sig)
372{
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000373 logMessage(0, "System log daemon exiting.");
Erik Andersen983b51b2000-04-04 18:14:25 +0000374 unlink(lfile);
Mark Whitley6317c4b2001-03-12 22:51:50 +0000375#ifdef BB_FEATURE_IPC_SYSLOG
376 ipcsyslog_cleanup();
377#endif
378
Erik Andersene49d5ec2000-02-08 19:58:47 +0000379 exit(TRUE);
Eric Andersen3843e961999-11-25 07:30:46 +0000380}
381
Eric Andersen3843e961999-11-25 07:30:46 +0000382static void domark(int sig)
383{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000384 if (MarkInterval > 0) {
385 logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --");
386 alarm(MarkInterval);
387 }
Eric Andersen3843e961999-11-25 07:30:46 +0000388}
389
Mark Whitley59ab0252001-01-23 22:30:04 +0000390static const int BUFSIZE = 1023;
Eric Andersen67e32302000-06-19 17:48:02 +0000391static int serveConnection (int conn)
Pavel Roskinda10ec02000-06-07 21:08:25 +0000392{
Eric Andersenf6aa13d2001-03-23 17:08:21 +0000393 RESERVE_BB_BUFFER(tmpbuf, BUFSIZE + 1);
Pavel Roskinda10ec02000-06-07 21:08:25 +0000394 int n_read;
395
Eric Andersenf6aa13d2001-03-23 17:08:21 +0000396 while ((n_read = read (conn, tmpbuf, BUFSIZE )) > 0) {
Pavel Roskinda10ec02000-06-07 21:08:25 +0000397
398 int pri = (LOG_USER | LOG_NOTICE);
399 char line[ BUFSIZE + 1 ];
400 unsigned char c;
401
Eric Andersenf6aa13d2001-03-23 17:08:21 +0000402 char *p = tmpbuf, *q = line;
Pavel Roskinda10ec02000-06-07 21:08:25 +0000403
Eric Andersenf6aa13d2001-03-23 17:08:21 +0000404 tmpbuf[ n_read - 1 ] = '\0';
Pavel Roskinda10ec02000-06-07 21:08:25 +0000405
406 while (p && (c = *p) && q < &line[ sizeof (line) - 1 ]) {
407 if (c == '<') {
408 /* Parse the magic priority number. */
409 pri = 0;
410 while (isdigit (*(++p))) {
411 pri = 10 * pri + (*p - '0');
412 }
Eric Andersenced2cef2000-07-20 23:41:24 +0000413 if (pri & ~(LOG_FACMASK | LOG_PRIMASK)){
Pavel Roskinda10ec02000-06-07 21:08:25 +0000414 pri = (LOG_USER | LOG_NOTICE);
Eric Andersenced2cef2000-07-20 23:41:24 +0000415 }
Pavel Roskinda10ec02000-06-07 21:08:25 +0000416 } else if (c == '\n') {
417 *q++ = ' ';
418 } else if (iscntrl (c) && (c < 0177)) {
419 *q++ = '^';
420 *q++ = c ^ 0100;
421 } else {
422 *q++ = c;
423 }
424 p++;
425 }
426 *q = '\0';
427 /* Now log it */
428 logMessage (pri, line);
429 }
Eric Andersen67e32302000-06-19 17:48:02 +0000430 return (0);
Pavel Roskinda10ec02000-06-07 21:08:25 +0000431}
432
Eric Andersenced2cef2000-07-20 23:41:24 +0000433
434#ifdef BB_FEATURE_REMOTE_LOG
435static void init_RemoteLog (void){
436
437 struct sockaddr_in remoteaddr;
438 struct hostent *hostinfo;
439 int len = sizeof(remoteaddr);
440
441 bzero(&remoteaddr, len);
442
443 remotefd = socket(AF_INET, SOCK_DGRAM, 0);
444
445 if (remotefd < 0) {
Matt Kraaidd19c692001-01-31 19:00:21 +0000446 error_msg_and_die("syslogd: cannot create socket");
Eric Andersenced2cef2000-07-20 23:41:24 +0000447 }
448
449 hostinfo = (struct hostent *) gethostbyname(RemoteHost);
450
451 if (!hostinfo) {
Matt Kraaidd19c692001-01-31 19:00:21 +0000452 error_msg_and_die("syslogd: cannot resolve remote host name [%s]", RemoteHost);
Eric Andersenced2cef2000-07-20 23:41:24 +0000453 }
454
455 remoteaddr.sin_family = AF_INET;
456 remoteaddr.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
457 remoteaddr.sin_port = htons(RemotePort);
458
459 /*
460 Since we are using UDP sockets, connect just sets the default host and port
461 for future operations
462 */
463 if ( 0 != (connect(remotefd, (struct sockaddr *) &remoteaddr, len))){
Matt Kraaidd19c692001-01-31 19:00:21 +0000464 error_msg_and_die("syslogd: cannot connect to remote host %s:%d", RemoteHost, RemotePort);
Eric Andersenced2cef2000-07-20 23:41:24 +0000465 }
466
467}
468#endif
469
Erik Andersen983b51b2000-04-04 18:14:25 +0000470static void doSyslogd (void) __attribute__ ((noreturn));
471static void doSyslogd (void)
Eric Andersen3843e961999-11-25 07:30:46 +0000472{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000473 struct sockaddr_un sunx;
Erik Andersen1d1d9502000-04-21 01:26:49 +0000474 socklen_t addrLength;
475
Erik Andersenf13df372000-04-18 23:51:51 +0000476
Erik Andersen983b51b2000-04-04 18:14:25 +0000477 int sock_fd;
Erik Andersenf13df372000-04-18 23:51:51 +0000478 fd_set fds;
479
Erik Andersenf13df372000-04-18 23:51:51 +0000480 /* Set up signal handlers. */
Erik Andersen983b51b2000-04-04 18:14:25 +0000481 signal (SIGINT, quit_signal);
482 signal (SIGTERM, quit_signal);
483 signal (SIGQUIT, quit_signal);
484 signal (SIGHUP, SIG_IGN);
Pavel Roskind39d1202000-09-13 14:14:29 +0000485 signal (SIGCHLD, SIG_IGN);
486#ifdef SIGCLD
Erik Andersene3ed1562000-04-19 18:52:56 +0000487 signal (SIGCLD, SIG_IGN);
Pavel Roskind39d1202000-09-13 14:14:29 +0000488#endif
Erik Andersen983b51b2000-04-04 18:14:25 +0000489 signal (SIGALRM, domark);
490 alarm (MarkInterval);
Eric Andersenb99df0f1999-11-24 09:04:33 +0000491
Erik Andersenf13df372000-04-18 23:51:51 +0000492 /* Create the syslog file so realpath() can work. */
493 close (open (_PATH_LOG, O_RDWR | O_CREAT, 0644));
494 if (realpath (_PATH_LOG, lfile) == NULL)
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000495 perror_msg_and_die ("Could not resolve path to " _PATH_LOG);
Eric Andersen14ec6cf1999-12-05 22:17:02 +0000496
Erik Andersen983b51b2000-04-04 18:14:25 +0000497 unlink (lfile);
498
Erik Andersenf13df372000-04-18 23:51:51 +0000499 memset (&sunx, 0, sizeof (sunx));
Erik Andersen983b51b2000-04-04 18:14:25 +0000500 sunx.sun_family = AF_UNIX;
Erik Andersenf13df372000-04-18 23:51:51 +0000501 strncpy (sunx.sun_path, lfile, sizeof (sunx.sun_path));
502 if ((sock_fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000503 perror_msg_and_die ("Couldn't obtain descriptor for socket " _PATH_LOG);
Eric Andersenb99df0f1999-11-24 09:04:33 +0000504
Erik Andersen983b51b2000-04-04 18:14:25 +0000505 addrLength = sizeof (sunx.sun_family) + strlen (sunx.sun_path);
Erik Andersenf13df372000-04-18 23:51:51 +0000506 if ((bind (sock_fd, (struct sockaddr *) &sunx, addrLength)) || (listen (sock_fd, 5)))
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000507 perror_msg_and_die ("Could not connect to socket " _PATH_LOG);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000508
Erik Andersenf13df372000-04-18 23:51:51 +0000509 if (chmod (lfile, 0666) < 0)
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000510 perror_msg_and_die ("Could not set permission on " _PATH_LOG);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000511
Erik Andersenf13df372000-04-18 23:51:51 +0000512 FD_ZERO (&fds);
513 FD_SET (sock_fd, &fds);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000514
Eric Andersenced2cef2000-07-20 23:41:24 +0000515 #ifdef BB_FEATURE_REMOTE_LOG
516 if (doRemoteLog == TRUE){
517 init_RemoteLog();
518 }
519 #endif
520
Erik Andersen983b51b2000-04-04 18:14:25 +0000521 logMessage (0, "syslogd started: BusyBox v" BB_VER " (" BB_BT ")");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000522
Erik Andersen983b51b2000-04-04 18:14:25 +0000523 for (;;) {
Erik Andersenf13df372000-04-18 23:51:51 +0000524
525 fd_set readfds;
526 int n_ready;
527 int fd;
528
529 memcpy (&readfds, &fds, sizeof (fds));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000530
Erik Andersen983b51b2000-04-04 18:14:25 +0000531 if ((n_ready = select (FD_SETSIZE, &readfds, NULL, NULL, NULL)) < 0) {
532 if (errno == EINTR) continue; /* alarm may have happened. */
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000533 perror_msg_and_die ("select error");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000534 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000535
Erik Andersenf13df372000-04-18 23:51:51 +0000536 for (fd = 0; (n_ready > 0) && (fd < FD_SETSIZE); fd++) {
Erik Andersen983b51b2000-04-04 18:14:25 +0000537 if (FD_ISSET (fd, &readfds)) {
Erik Andersene3ed1562000-04-19 18:52:56 +0000538
Erik Andersenf13df372000-04-18 23:51:51 +0000539 --n_ready;
Erik Andersene3ed1562000-04-19 18:52:56 +0000540
Erik Andersen983b51b2000-04-04 18:14:25 +0000541 if (fd == sock_fd) {
Erik Andersene3ed1562000-04-19 18:52:56 +0000542 int conn;
Erik Andersene3ed1562000-04-19 18:52:56 +0000543
Mark Whitley1a49fc52001-03-12 19:51:09 +0000544 //printf("New Connection request.\n");
Erik Andersenf13df372000-04-18 23:51:51 +0000545 if ((conn = accept (sock_fd, (struct sockaddr *) &sunx, &addrLength)) < 0) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000546 perror_msg_and_die ("accept error");
Erik Andersen983b51b2000-04-04 18:14:25 +0000547 }
Erik Andersena6c75222000-04-18 00:00:52 +0000548
Mark Whitley1a49fc52001-03-12 19:51:09 +0000549 FD_SET(conn, &fds);
550 //printf("conn: %i, set_size: %i\n",conn,FD_SETSIZE);
551 } else {
552 //printf("Serving connection: %i\n",fd);
553 serveConnection (fd);
554 close (fd);
555 FD_CLR(fd, &fds);
556 } /* fd == sock_fd */
557 }/* FD_ISSET() */
558 }/* for */
559 } /* for main loop */
Eric Andersenb99df0f1999-11-24 09:04:33 +0000560}
561
Erik Andersen983b51b2000-04-04 18:14:25 +0000562static void daemon_init (char **argv, char *dz, void fn (void))
563{
564 setsid();
565 chdir ("/");
566 strncpy(argv[0], dz, strlen(argv[0]));
567 fn();
568 exit(0);
569}
570
Eric Andersen3843e961999-11-25 07:30:46 +0000571extern int syslogd_main(int argc, char **argv)
572{
Mark Whitley6317c4b2001-03-12 22:51:50 +0000573 int opt, pid;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000574 int doFork = TRUE;
575
Erik Andersene49d5ec2000-02-08 19:58:47 +0000576 char *p;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000577
Eric Andersen394cf222000-12-11 16:48:50 +0000578 /* do normal option parsing */
Mark Whitley6317c4b2001-03-12 22:51:50 +0000579 while ((opt = getopt(argc, argv, "m:nO:R:LC")) > 0) {
Eric Andersen394cf222000-12-11 16:48:50 +0000580 switch (opt) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000581 case 'm':
Eric Andersen394cf222000-12-11 16:48:50 +0000582 MarkInterval = atoi(optarg) * 60;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000583 break;
584 case 'n':
585 doFork = FALSE;
586 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000587 case 'O':
Eric Andersen394cf222000-12-11 16:48:50 +0000588 logFilePath = strdup(optarg);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000589 break;
Eric Andersenced2cef2000-07-20 23:41:24 +0000590#ifdef BB_FEATURE_REMOTE_LOG
591 case 'R':
Eric Andersen394cf222000-12-11 16:48:50 +0000592 RemoteHost = strdup(optarg);
593 if ( (p = strchr(RemoteHost, ':'))){
594 RemotePort = atoi(p+1);
595 *p = '\0';
596 }
597 doRemoteLog = TRUE;
598 break;
Eric Andersen70d09ed2000-12-11 16:24:16 +0000599 case 'L':
600 local_logging = TRUE;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000601 break;
Eric Andersenced2cef2000-07-20 23:41:24 +0000602#endif
Mark Whitley6317c4b2001-03-12 22:51:50 +0000603#ifdef BB_FEATURE_IPC_SYSLOG
604 case 'C':
605 circular_logging = TRUE;
606 break;
607#endif
Erik Andersene49d5ec2000-02-08 19:58:47 +0000608 default:
Eric Andersen67991cf2001-02-14 21:23:06 +0000609 show_usage();
Eric Andersen3843e961999-11-25 07:30:46 +0000610 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000611 }
612
Eric Andersen4ed17822000-12-11 19:28:29 +0000613#ifdef BB_FEATURE_REMOTE_LOG
614 /* If they have not specified remote logging, then log locally */
615 if (doRemoteLog == FALSE)
616 local_logging = TRUE;
617#endif
618
Mark Whitley6317c4b2001-03-12 22:51:50 +0000619
Erik Andersene49d5ec2000-02-08 19:58:47 +0000620 /* Store away localhost's name before the fork */
621 gethostname(LocalHostName, sizeof(LocalHostName));
622 if ((p = strchr(LocalHostName, '.'))) {
623 *p++ = '\0';
624 }
625
Erik Andersen983b51b2000-04-04 18:14:25 +0000626 umask(0);
627
Mark Whitley6317c4b2001-03-12 22:51:50 +0000628#ifdef BB_FEATURE_IPC_SYSLOG
629 if (circular_logging == TRUE ){
630 ipcsyslog_init();
Erik Andersene2729152000-02-18 21:34:17 +0000631 }
632#endif
633
Erik Andersene49d5ec2000-02-08 19:58:47 +0000634 if (doFork == TRUE) {
635 pid = fork();
636 if (pid < 0)
637 exit(pid);
638 else if (pid == 0) {
Erik Andersen983b51b2000-04-04 18:14:25 +0000639 daemon_init (argv, "syslogd", doSyslogd);
Eric Andersen3843e961999-11-25 07:30:46 +0000640 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000641 } else {
642 doSyslogd();
Eric Andersen3843e961999-11-25 07:30:46 +0000643 }
Eric Andersenb186d981999-12-03 09:19:54 +0000644
Matt Kraai3e856ce2000-12-01 02:55:13 +0000645 return EXIT_SUCCESS;
Eric Andersen3843e961999-11-25 07:30:46 +0000646}
Erik Andersen983b51b2000-04-04 18:14:25 +0000647
648/*
Erik Andersene3ed1562000-04-19 18:52:56 +0000649Local Variables
650c-file-style: "linux"
651c-basic-offset: 4
652tab-width: 4
653End:
654*/