blob: 9f5fc93b1f21745bc3130f6b8c57c4d0b1cc4c03 [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{
Eric Andersenea906502001-04-05 20:55:17 +0000122 if ( semop(semid, SMwdn, 3) == -1 )
Mark Whitley6317c4b2001-03-12 22:51:50 +0000123 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");
Eric Andersenea906502001-04-05 20:55:17 +0000158 } else {
159 sem_up(s_semid);
Mark Whitley6317c4b2001-03-12 22:51:50 +0000160 }
161 }else{
162 printf("Buffer already allocated just grab the semaphore?");
163 }
164}
165
166/* write message to buffer */
167void circ_message(const char *msg){
168 int l=strlen(msg)+1; /* count the whole message w/ '\0' included */
169
170 sem_down(s_semid);
171
172 /*
173 * Circular Buffer Algorithm:
174 * --------------------------
175 *
176 * Start-off w/ empty buffer of specific size SHM_SIZ
177 * Start filling it up w/ messages. I use '\0' as separator to break up messages.
178 * This is also very handy since we can do printf on message.
179 *
180 * Once the buffer is full we need to get rid of the first message in buffer and
181 * insert the new message. (Note: if the message being added is >1 message then
182 * we will need to "remove" >1 old message from the buffer). The way this is done
183 * is the following:
184 * When we reach the end of the buffer we set a mark and start from the beginning.
185 * Now what about the beginning and end of the buffer? Well we have the "head"
186 * index/pointer which is the starting point for the messages and we have "tail"
187 * index/pointer which is the ending point for the messages. When we "display" the
188 * messages we start from the beginning and continue until we reach "tail". If we
189 * reach end of buffer, then we just start from the beginning (offset 0). "head" and
190 * "tail" are actually offsets from the beginning of the buffer.
191 *
192 * Note: This algorithm uses Linux IPC mechanism w/ shared memory and semaphores to provide
193 * a threasafe way of handling shared memory operations.
194 */
195 if ( (buf->tail + l) < buf->size ){
196 /* before we append the message we need to check the HEAD so that we won't
197 overwrite any of the message that we still need and adjust HEAD to point
198 to the next message! */
199 if ( buf->tail < buf->head){
200 if ( (buf->tail + l) >= buf->head ){
201 /* we need to move the HEAD to point to the next message
202 * Theoretically we have enough room to add the whole message to the
203 * buffer, because of the first outer IF statement, so we don't have
204 * to worry about overflows here!
205 */
206 int k= buf->tail + l - buf->head; /* we need to know how many bytes
207 we are overwriting to make
208 enough room */
209 char *c=memchr(buf->data+buf->head + k,'\0',buf->size - (buf->head + k));
210 if (c != NULL) {/* do a sanity check just in case! */
211 buf->head = c - buf->data + 1; /* we need to convert pointer to
212 offset + skip the '\0' since
213 we need to point to the beginning
214 of the next message */
215 /* Note: HEAD is only used to "retrieve" messages, it's not used
216 when writing messages into our buffer */
217 }else{ /* show an error message to know we messed up? */
218 printf("Weird! Can't find the terminator token??? \n");
219 buf->head=0;
220 }
221 }
222 } /* in other cases no overflows have been done yet, so we don't care! */
223
224 /* we should be ok to append the message now */
225 strncpy(buf->data + buf->tail,msg,l); /* append our message */
226 buf->tail+=l; /* count full message w/ '\0' terminating char */
227 }else{
228 /* we need to break up the message and "circle" it around */
229 char *c;
230 int k=buf->tail + l - buf->size; /* count # of bytes we don't fit */
231
232 /* We need to move HEAD! This is always the case since we are going
233 * to "circle" the message.
234 */
235 c=memchr(buf->data + k ,'\0', buf->size - k);
236
237 if (c != NULL) /* if we don't have '\0'??? weird!!! */{
238 /* move head pointer*/
239 buf->head=c-buf->data+1;
240
241 /* now write the first part of the message */
242 strncpy(buf->data + buf->tail, msg, l - k - 1);
243
244 /* ALWAYS terminate end of buffer w/ '\0' */
245 buf->data[buf->size-1]='\0';
246
247 /* now write out the rest of the string to the beginning of the buffer */
248 strcpy(buf->data, &msg[l-k-1]);
249
250 /* we need to place the TAIL at the end of the message */
251 buf->tail = k + 1;
252 }else{
253 printf("Weird! Can't find the terminator token from the beginning??? \n");
254 buf->head = buf->tail = 0; /* reset buffer, since it's probably corrupted */
255 }
256
257 }
258 sem_up(s_semid);
259}
260#endif
Erik Andersenc053e412000-03-21 01:31:24 +0000261/* Note: There is also a function called "message()" in init.c */
Erik Andersen983b51b2000-04-04 18:14:25 +0000262/* Print a message to the log file. */
Erik Andersenf13df372000-04-18 23:51:51 +0000263static void message (char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
264static void message (char *fmt, ...)
Eric Andersen3843e961999-11-25 07:30:46 +0000265{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000266 int fd;
Erik Andersene3ed1562000-04-19 18:52:56 +0000267 struct flock fl;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000268 va_list arguments;
Eric Andersen3843e961999-11-25 07:30:46 +0000269
Erik Andersene3ed1562000-04-19 18:52:56 +0000270 fl.l_whence = SEEK_SET;
271 fl.l_start = 0;
272 fl.l_len = 1;
273
Mark Whitley6317c4b2001-03-12 22:51:50 +0000274#ifdef BB_FEATURE_IPC_SYSLOG
275 if ((circular_logging == TRUE) && (buf != NULL)){
276 char b[1024];
277 va_start (arguments, fmt);
278 vsprintf (b, fmt, arguments);
279 va_end (arguments);
280 circ_message(b);
281
282 }else
283#endif
Erik Andersenf13df372000-04-18 23:51:51 +0000284 if ((fd = device_open (logFilePath,
285 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
286 O_NONBLOCK)) >= 0) {
Erik Andersene3ed1562000-04-19 18:52:56 +0000287 fl.l_type = F_WRLCK;
288 fcntl (fd, F_SETLKW, &fl);
Erik Andersenf13df372000-04-18 23:51:51 +0000289 va_start (arguments, fmt);
290 vdprintf (fd, fmt, arguments);
291 va_end (arguments);
Erik Andersene3ed1562000-04-19 18:52:56 +0000292 fl.l_type = F_UNLCK;
293 fcntl (fd, F_SETLKW, &fl);
Erik Andersenf13df372000-04-18 23:51:51 +0000294 close (fd);
Eric Andersen3843e961999-11-25 07:30:46 +0000295 } else {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000296 /* Always send console messages to /dev/console so people will see them. */
Erik Andersenf13df372000-04-18 23:51:51 +0000297 if ((fd = device_open (_PATH_CONSOLE,
298 O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) {
299 va_start (arguments, fmt);
300 vdprintf (fd, fmt, arguments);
301 va_end (arguments);
302 close (fd);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000303 } else {
Erik Andersenf13df372000-04-18 23:51:51 +0000304 fprintf (stderr, "Bummer, can't print: ");
305 va_start (arguments, fmt);
306 vfprintf (stderr, fmt, arguments);
307 fflush (stderr);
308 va_end (arguments);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000309 }
Eric Andersen3843e961999-11-25 07:30:46 +0000310 }
Eric Andersenb99df0f1999-11-24 09:04:33 +0000311}
312
Erik Andersenf13df372000-04-18 23:51:51 +0000313static void logMessage (int pri, char *msg)
Eric Andersen3843e961999-11-25 07:30:46 +0000314{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000315 time_t now;
316 char *timestamp;
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000317 static char res[20] = "";
Erik Andersene49d5ec2000-02-08 19:58:47 +0000318 CODE *c_pri, *c_fac;
Eric Andersenb99df0f1999-11-24 09:04:33 +0000319
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000320 if (pri != 0) {
321 for (c_fac = facilitynames;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000322 c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++);
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000323 for (c_pri = prioritynames;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000324 c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++);
Matt Kraai5a964f92000-12-11 20:13:37 +0000325 if (c_fac->c_name == NULL || c_pri->c_name == NULL)
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000326 snprintf(res, sizeof(res), "<%d>", pri);
327 else
328 snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name);
329 }
Eric Andersen3843e961999-11-25 07:30:46 +0000330
Erik Andersene49d5ec2000-02-08 19:58:47 +0000331 if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' ||
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000332 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000333 time(&now);
334 timestamp = ctime(&now) + 4;
335 timestamp[15] = '\0';
336 } else {
337 timestamp = msg;
338 timestamp[15] = '\0';
339 msg += 16;
340 }
Eric Andersen3843e961999-11-25 07:30:46 +0000341
Erik Andersene49d5ec2000-02-08 19:58:47 +0000342 /* todo: supress duplicates */
Eric Andersen3843e961999-11-25 07:30:46 +0000343
Eric Andersenced2cef2000-07-20 23:41:24 +0000344#ifdef BB_FEATURE_REMOTE_LOG
345 /* send message to remote logger */
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000346 if ( -1 != remotefd){
Mark Whitley59ab0252001-01-23 22:30:04 +0000347static const int IOV_COUNT = 2;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000348 struct iovec iov[IOV_COUNT];
349 struct iovec *v = iov;
Eric Andersenced2cef2000-07-20 23:41:24 +0000350
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000351 bzero(&res, sizeof(res));
352 snprintf(res, sizeof(res), "<%d>", pri);
353 v->iov_base = res ;
354 v->iov_len = strlen(res);
355 v++;
Eric Andersenced2cef2000-07-20 23:41:24 +0000356
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000357 v->iov_base = msg;
358 v->iov_len = strlen(msg);
359
360 if ( -1 == writev(remotefd,iov, IOV_COUNT)){
361 error_msg_and_die("syslogd: cannot write to remote file handle on"
Matt Kraaidd19c692001-01-31 19:00:21 +0000362 "%s:%d",RemoteHost,RemotePort);
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000363 }
364 }
365 if (local_logging == TRUE)
Eric Andersenced2cef2000-07-20 23:41:24 +0000366#endif
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000367 /* now spew out the message to wherever it is supposed to go */
368 message("%s %s %s %s\n", timestamp, LocalHostName, res, msg);
Eric Andersen76fef0a2000-12-08 19:41:21 +0000369
Eric Andersenced2cef2000-07-20 23:41:24 +0000370
Eric Andersen3843e961999-11-25 07:30:46 +0000371}
372
373static void quit_signal(int sig)
374{
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000375 logMessage(0, "System log daemon exiting.");
Erik Andersen983b51b2000-04-04 18:14:25 +0000376 unlink(lfile);
Mark Whitley6317c4b2001-03-12 22:51:50 +0000377#ifdef BB_FEATURE_IPC_SYSLOG
378 ipcsyslog_cleanup();
379#endif
380
Erik Andersene49d5ec2000-02-08 19:58:47 +0000381 exit(TRUE);
Eric Andersen3843e961999-11-25 07:30:46 +0000382}
383
Eric Andersen3843e961999-11-25 07:30:46 +0000384static void domark(int sig)
385{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000386 if (MarkInterval > 0) {
387 logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --");
388 alarm(MarkInterval);
389 }
Eric Andersen3843e961999-11-25 07:30:46 +0000390}
391
Mark Whitley59ab0252001-01-23 22:30:04 +0000392static const int BUFSIZE = 1023;
Eric Andersen67e32302000-06-19 17:48:02 +0000393static int serveConnection (int conn)
Pavel Roskinda10ec02000-06-07 21:08:25 +0000394{
Eric Andersenf6aa13d2001-03-23 17:08:21 +0000395 RESERVE_BB_BUFFER(tmpbuf, BUFSIZE + 1);
Pavel Roskinda10ec02000-06-07 21:08:25 +0000396 int n_read;
397
Mark Whitleybff6b182001-03-27 20:17:58 +0000398 n_read = read (conn, tmpbuf, BUFSIZE );
399
400 if (n_read > 0) {
Pavel Roskinda10ec02000-06-07 21:08:25 +0000401
402 int pri = (LOG_USER | LOG_NOTICE);
403 char line[ BUFSIZE + 1 ];
404 unsigned char c;
405
Eric Andersenf6aa13d2001-03-23 17:08:21 +0000406 char *p = tmpbuf, *q = line;
Pavel Roskinda10ec02000-06-07 21:08:25 +0000407
Eric Andersenf6aa13d2001-03-23 17:08:21 +0000408 tmpbuf[ n_read - 1 ] = '\0';
Pavel Roskinda10ec02000-06-07 21:08:25 +0000409
410 while (p && (c = *p) && q < &line[ sizeof (line) - 1 ]) {
411 if (c == '<') {
412 /* Parse the magic priority number. */
413 pri = 0;
414 while (isdigit (*(++p))) {
415 pri = 10 * pri + (*p - '0');
416 }
Eric Andersenced2cef2000-07-20 23:41:24 +0000417 if (pri & ~(LOG_FACMASK | LOG_PRIMASK)){
Pavel Roskinda10ec02000-06-07 21:08:25 +0000418 pri = (LOG_USER | LOG_NOTICE);
Eric Andersenced2cef2000-07-20 23:41:24 +0000419 }
Pavel Roskinda10ec02000-06-07 21:08:25 +0000420 } else if (c == '\n') {
421 *q++ = ' ';
422 } else if (iscntrl (c) && (c < 0177)) {
423 *q++ = '^';
424 *q++ = c ^ 0100;
425 } else {
426 *q++ = c;
427 }
428 p++;
429 }
430 *q = '\0';
431 /* Now log it */
432 logMessage (pri, line);
433 }
Mark Whitleybff6b182001-03-27 20:17:58 +0000434 return n_read;
Pavel Roskinda10ec02000-06-07 21:08:25 +0000435}
436
Eric Andersenced2cef2000-07-20 23:41:24 +0000437
438#ifdef BB_FEATURE_REMOTE_LOG
439static void init_RemoteLog (void){
440
441 struct sockaddr_in remoteaddr;
442 struct hostent *hostinfo;
443 int len = sizeof(remoteaddr);
444
445 bzero(&remoteaddr, len);
Mark Whitleybff6b182001-03-27 20:17:58 +0000446
Eric Andersenced2cef2000-07-20 23:41:24 +0000447 remotefd = socket(AF_INET, SOCK_DGRAM, 0);
448
449 if (remotefd < 0) {
Matt Kraaidd19c692001-01-31 19:00:21 +0000450 error_msg_and_die("syslogd: cannot create socket");
Eric Andersenced2cef2000-07-20 23:41:24 +0000451 }
452
453 hostinfo = (struct hostent *) gethostbyname(RemoteHost);
454
455 if (!hostinfo) {
Matt Kraaidd19c692001-01-31 19:00:21 +0000456 error_msg_and_die("syslogd: cannot resolve remote host name [%s]", RemoteHost);
Eric Andersenced2cef2000-07-20 23:41:24 +0000457 }
458
459 remoteaddr.sin_family = AF_INET;
460 remoteaddr.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
461 remoteaddr.sin_port = htons(RemotePort);
462
463 /*
464 Since we are using UDP sockets, connect just sets the default host and port
465 for future operations
466 */
467 if ( 0 != (connect(remotefd, (struct sockaddr *) &remoteaddr, len))){
Matt Kraaidd19c692001-01-31 19:00:21 +0000468 error_msg_and_die("syslogd: cannot connect to remote host %s:%d", RemoteHost, RemotePort);
Eric Andersenced2cef2000-07-20 23:41:24 +0000469 }
470
471}
472#endif
473
Erik Andersen983b51b2000-04-04 18:14:25 +0000474static void doSyslogd (void) __attribute__ ((noreturn));
475static void doSyslogd (void)
Eric Andersen3843e961999-11-25 07:30:46 +0000476{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000477 struct sockaddr_un sunx;
Erik Andersen1d1d9502000-04-21 01:26:49 +0000478 socklen_t addrLength;
479
Erik Andersenf13df372000-04-18 23:51:51 +0000480
Erik Andersen983b51b2000-04-04 18:14:25 +0000481 int sock_fd;
Erik Andersenf13df372000-04-18 23:51:51 +0000482 fd_set fds;
483
Erik Andersenf13df372000-04-18 23:51:51 +0000484 /* Set up signal handlers. */
Erik Andersen983b51b2000-04-04 18:14:25 +0000485 signal (SIGINT, quit_signal);
486 signal (SIGTERM, quit_signal);
487 signal (SIGQUIT, quit_signal);
488 signal (SIGHUP, SIG_IGN);
Pavel Roskind39d1202000-09-13 14:14:29 +0000489 signal (SIGCHLD, SIG_IGN);
490#ifdef SIGCLD
Erik Andersene3ed1562000-04-19 18:52:56 +0000491 signal (SIGCLD, SIG_IGN);
Pavel Roskind39d1202000-09-13 14:14:29 +0000492#endif
Erik Andersen983b51b2000-04-04 18:14:25 +0000493 signal (SIGALRM, domark);
494 alarm (MarkInterval);
Eric Andersenb99df0f1999-11-24 09:04:33 +0000495
Erik Andersenf13df372000-04-18 23:51:51 +0000496 /* Create the syslog file so realpath() can work. */
497 close (open (_PATH_LOG, O_RDWR | O_CREAT, 0644));
498 if (realpath (_PATH_LOG, lfile) == NULL)
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000499 perror_msg_and_die ("Could not resolve path to " _PATH_LOG);
Eric Andersen14ec6cf1999-12-05 22:17:02 +0000500
Erik Andersen983b51b2000-04-04 18:14:25 +0000501 unlink (lfile);
502
Erik Andersenf13df372000-04-18 23:51:51 +0000503 memset (&sunx, 0, sizeof (sunx));
Erik Andersen983b51b2000-04-04 18:14:25 +0000504 sunx.sun_family = AF_UNIX;
Erik Andersenf13df372000-04-18 23:51:51 +0000505 strncpy (sunx.sun_path, lfile, sizeof (sunx.sun_path));
506 if ((sock_fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000507 perror_msg_and_die ("Couldn't obtain descriptor for socket " _PATH_LOG);
Eric Andersenb99df0f1999-11-24 09:04:33 +0000508
Erik Andersen983b51b2000-04-04 18:14:25 +0000509 addrLength = sizeof (sunx.sun_family) + strlen (sunx.sun_path);
Erik Andersenf13df372000-04-18 23:51:51 +0000510 if ((bind (sock_fd, (struct sockaddr *) &sunx, addrLength)) || (listen (sock_fd, 5)))
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000511 perror_msg_and_die ("Could not connect to socket " _PATH_LOG);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000512
Erik Andersenf13df372000-04-18 23:51:51 +0000513 if (chmod (lfile, 0666) < 0)
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000514 perror_msg_and_die ("Could not set permission on " _PATH_LOG);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000515
Erik Andersenf13df372000-04-18 23:51:51 +0000516 FD_ZERO (&fds);
517 FD_SET (sock_fd, &fds);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000518
Eric Andersenea906502001-04-05 20:55:17 +0000519#ifdef BB_FEATURE_IPC_SYSLOG
520 if (circular_logging == TRUE ){
521 ipcsyslog_init();
522 }
523#endif
524
Eric Andersenced2cef2000-07-20 23:41:24 +0000525 #ifdef BB_FEATURE_REMOTE_LOG
526 if (doRemoteLog == TRUE){
527 init_RemoteLog();
528 }
529 #endif
530
Matt Kraai6ba1a802001-04-12 20:11:55 +0000531 logMessage (0, "syslogd started: " BB_BANNER);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000532
Erik Andersen983b51b2000-04-04 18:14:25 +0000533 for (;;) {
Erik Andersenf13df372000-04-18 23:51:51 +0000534
535 fd_set readfds;
536 int n_ready;
537 int fd;
538
539 memcpy (&readfds, &fds, sizeof (fds));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000540
Erik Andersen983b51b2000-04-04 18:14:25 +0000541 if ((n_ready = select (FD_SETSIZE, &readfds, NULL, NULL, NULL)) < 0) {
542 if (errno == EINTR) continue; /* alarm may have happened. */
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000543 perror_msg_and_die ("select error");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000544 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000545
Erik Andersenf13df372000-04-18 23:51:51 +0000546 for (fd = 0; (n_ready > 0) && (fd < FD_SETSIZE); fd++) {
Erik Andersen983b51b2000-04-04 18:14:25 +0000547 if (FD_ISSET (fd, &readfds)) {
Erik Andersene3ed1562000-04-19 18:52:56 +0000548
Erik Andersenf13df372000-04-18 23:51:51 +0000549 --n_ready;
Erik Andersene3ed1562000-04-19 18:52:56 +0000550
Erik Andersen983b51b2000-04-04 18:14:25 +0000551 if (fd == sock_fd) {
Erik Andersene3ed1562000-04-19 18:52:56 +0000552 int conn;
Erik Andersene3ed1562000-04-19 18:52:56 +0000553
Mark Whitley1a49fc52001-03-12 19:51:09 +0000554 //printf("New Connection request.\n");
Erik Andersenf13df372000-04-18 23:51:51 +0000555 if ((conn = accept (sock_fd, (struct sockaddr *) &sunx, &addrLength)) < 0) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000556 perror_msg_and_die ("accept error");
Erik Andersen983b51b2000-04-04 18:14:25 +0000557 }
Erik Andersena6c75222000-04-18 00:00:52 +0000558
Mark Whitley1a49fc52001-03-12 19:51:09 +0000559 FD_SET(conn, &fds);
560 //printf("conn: %i, set_size: %i\n",conn,FD_SETSIZE);
Mark Whitleybff6b182001-03-27 20:17:58 +0000561 } else {
Mark Whitley1a49fc52001-03-12 19:51:09 +0000562 //printf("Serving connection: %i\n",fd);
Mark Whitleybff6b182001-03-27 20:17:58 +0000563 if ( serveConnection(fd) <= 0 ) {
564 close (fd);
565 FD_CLR(fd, &fds);
566 }
Mark Whitley1a49fc52001-03-12 19:51:09 +0000567 } /* fd == sock_fd */
568 }/* FD_ISSET() */
569 }/* for */
570 } /* for main loop */
Eric Andersenb99df0f1999-11-24 09:04:33 +0000571}
572
Eric Andersen3843e961999-11-25 07:30:46 +0000573extern int syslogd_main(int argc, char **argv)
574{
Eric Andersene5c24df2001-03-29 21:58:33 +0000575 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000576 int doFork = TRUE;
577
Erik Andersene49d5ec2000-02-08 19:58:47 +0000578 char *p;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000579
Eric Andersen394cf222000-12-11 16:48:50 +0000580 /* do normal option parsing */
Mark Whitley6317c4b2001-03-12 22:51:50 +0000581 while ((opt = getopt(argc, argv, "m:nO:R:LC")) > 0) {
Eric Andersen394cf222000-12-11 16:48:50 +0000582 switch (opt) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000583 case 'm':
Eric Andersen394cf222000-12-11 16:48:50 +0000584 MarkInterval = atoi(optarg) * 60;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000585 break;
586 case 'n':
587 doFork = FALSE;
588 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000589 case 'O':
Eric Andersen394cf222000-12-11 16:48:50 +0000590 logFilePath = strdup(optarg);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000591 break;
Eric Andersenced2cef2000-07-20 23:41:24 +0000592#ifdef BB_FEATURE_REMOTE_LOG
593 case 'R':
Eric Andersen394cf222000-12-11 16:48:50 +0000594 RemoteHost = strdup(optarg);
595 if ( (p = strchr(RemoteHost, ':'))){
596 RemotePort = atoi(p+1);
597 *p = '\0';
Mark Whitleybff6b182001-03-27 20:17:58 +0000598 }
Eric Andersen394cf222000-12-11 16:48:50 +0000599 doRemoteLog = TRUE;
600 break;
Eric Andersen70d09ed2000-12-11 16:24:16 +0000601 case 'L':
602 local_logging = TRUE;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000603 break;
Eric Andersenced2cef2000-07-20 23:41:24 +0000604#endif
Mark Whitley6317c4b2001-03-12 22:51:50 +0000605#ifdef BB_FEATURE_IPC_SYSLOG
606 case 'C':
607 circular_logging = TRUE;
608 break;
609#endif
Erik Andersene49d5ec2000-02-08 19:58:47 +0000610 default:
Eric Andersen67991cf2001-02-14 21:23:06 +0000611 show_usage();
Eric Andersen3843e961999-11-25 07:30:46 +0000612 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000613 }
614
Eric Andersen4ed17822000-12-11 19:28:29 +0000615#ifdef BB_FEATURE_REMOTE_LOG
616 /* If they have not specified remote logging, then log locally */
617 if (doRemoteLog == FALSE)
618 local_logging = TRUE;
619#endif
620
Mark Whitley6317c4b2001-03-12 22:51:50 +0000621
Erik Andersene49d5ec2000-02-08 19:58:47 +0000622 /* Store away localhost's name before the fork */
623 gethostname(LocalHostName, sizeof(LocalHostName));
624 if ((p = strchr(LocalHostName, '.'))) {
625 *p++ = '\0';
626 }
627
Erik Andersen983b51b2000-04-04 18:14:25 +0000628 umask(0);
629
Erik Andersene49d5ec2000-02-08 19:58:47 +0000630 if (doFork == TRUE) {
Eric Andersene5c24df2001-03-29 21:58:33 +0000631 if (daemon(0, 1) < 0)
632 perror_msg_and_die("daemon");
Eric Andersen3843e961999-11-25 07:30:46 +0000633 }
Eric Andersene5c24df2001-03-29 21:58:33 +0000634 doSyslogd();
Eric Andersenb186d981999-12-03 09:19:54 +0000635
Matt Kraai3e856ce2000-12-01 02:55:13 +0000636 return EXIT_SUCCESS;
Eric Andersen3843e961999-11-25 07:30:46 +0000637}
Erik Andersen983b51b2000-04-04 18:14:25 +0000638
639/*
Erik Andersene3ed1562000-04-19 18:52:56 +0000640Local Variables
641c-file-style: "linux"
642c-basic-offset: 4
643tab-width: 4
644End:
645*/