blob: 6db017cd479860bf58595dc12e86a22d553bd8fd [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 Andersenbdfd0d72001-10-24 05:00:29 +00005 * Copyright (C) 1999,2000 by Lineo, inc. and Erik Andersen
6 * Copyright (C) 1999,2000,2001 by Erik Andersen <andersee@debian.org>
Eric Andersen3843e961999-11-25 07:30:46 +00007 *
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 */
Matt Kraaic3088472001-07-06 19:28:07 +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 Andersenbdfd0d72001-10-24 05:00:29 +000068#ifdef CONFIG_FEATURE_REMOTE_LOG
Eric Andersenced2cef2000-07-20 23:41:24 +000069#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 */
Eric Andersenbdfd0d72001-10-24 05:00:29 +000082#ifdef CONFIG_FEATURE_IPC_SYSLOG
Mark Whitley6317c4b2001-03-12 22:51:50 +000083
Gennady Feldman087bc822001-10-26 16:09:09 +000084#if __GNU_LIBRARY__ < 5
85#error Sorry. Looks like you are using libc5.
86#error libc5 shm support isnt good enough.
87#error Please disable CONFIG_FEATURE_IPC_SYSLOG
88#endif
89
Mark Whitley6317c4b2001-03-12 22:51:50 +000090#include <sys/ipc.h>
91#include <sys/sem.h>
92#include <sys/shm.h>
93
94/* our shared key */
95static const long KEY_ID = 0x414e4547; /*"GENA"*/
96
97// Semaphore operation structures
98static struct shbuf_ds {
99 int size; // size of data written
100 int head; // start of message list
101 int tail; // end of message list
102 char data[1]; // data/messages
103} *buf = NULL; // shared memory pointer
104
105static struct sembuf SMwup[1] = {{1, -1, IPC_NOWAIT}}; // set SMwup
106static struct sembuf SMwdn[3] = {{0, 0}, {1, 0}, {1, +1}}; // set SMwdn
107
108static int shmid = -1; // ipc shared memory id
109static int s_semid = -1; // ipc semaphore id
110int data_size = 16000; // data size
111int shm_size = 16000 + sizeof(*buf); // our buffer size
112static int circular_logging = FALSE;
113
114/*
115 * sem_up - up()'s a semaphore.
116 */
117static inline void sem_up(int semid)
118{
119 if ( semop(semid, SMwup, 1) == -1 )
120 perror_msg_and_die("semop[SMwup]");
121}
122
123/*
124 * sem_down - down()'s a semaphore
125 */
126static inline void sem_down(int semid)
127{
Eric Andersenea906502001-04-05 20:55:17 +0000128 if ( semop(semid, SMwdn, 3) == -1 )
Mark Whitley6317c4b2001-03-12 22:51:50 +0000129 perror_msg_and_die("semop[SMwdn]");
130}
131
132
133void ipcsyslog_cleanup(void){
134 printf("Exiting Syslogd!\n");
135 if (shmid != -1)
136 shmdt(buf);
137
138 if (shmid != -1)
139 shmctl(shmid, IPC_RMID, NULL);
140 if (s_semid != -1)
141 semctl(s_semid, 0, IPC_RMID, 0);
142}
143
144void ipcsyslog_init(void){
145 if (buf == NULL){
146 if ((shmid = shmget(KEY_ID, shm_size, IPC_CREAT | 1023)) == -1)
147 perror_msg_and_die("shmget");
148
149
150 if ((buf = shmat(shmid, NULL, 0)) == NULL)
151 perror_msg_and_die("shmat");
152
153
154 buf->size=data_size;
155 buf->head=buf->tail=0;
156
157 // we'll trust the OS to set initial semval to 0 (let's hope)
158 if ((s_semid = semget(KEY_ID, 2, IPC_CREAT | IPC_EXCL | 1023)) == -1){
159 if (errno == EEXIST){
160 if ((s_semid = semget(KEY_ID, 2, 0)) == -1)
161 perror_msg_and_die("semget");
162 }else
163 perror_msg_and_die("semget");
164 }
165 }else{
166 printf("Buffer already allocated just grab the semaphore?");
167 }
168}
169
170/* write message to buffer */
171void circ_message(const char *msg){
172 int l=strlen(msg)+1; /* count the whole message w/ '\0' included */
173
174 sem_down(s_semid);
175
176 /*
177 * Circular Buffer Algorithm:
178 * --------------------------
179 *
180 * Start-off w/ empty buffer of specific size SHM_SIZ
181 * Start filling it up w/ messages. I use '\0' as separator to break up messages.
182 * This is also very handy since we can do printf on message.
183 *
184 * Once the buffer is full we need to get rid of the first message in buffer and
185 * insert the new message. (Note: if the message being added is >1 message then
186 * we will need to "remove" >1 old message from the buffer). The way this is done
187 * is the following:
188 * When we reach the end of the buffer we set a mark and start from the beginning.
189 * Now what about the beginning and end of the buffer? Well we have the "head"
190 * index/pointer which is the starting point for the messages and we have "tail"
191 * index/pointer which is the ending point for the messages. When we "display" the
192 * messages we start from the beginning and continue until we reach "tail". If we
193 * reach end of buffer, then we just start from the beginning (offset 0). "head" and
194 * "tail" are actually offsets from the beginning of the buffer.
195 *
196 * Note: This algorithm uses Linux IPC mechanism w/ shared memory and semaphores to provide
197 * a threasafe way of handling shared memory operations.
198 */
199 if ( (buf->tail + l) < buf->size ){
200 /* before we append the message we need to check the HEAD so that we won't
201 overwrite any of the message that we still need and adjust HEAD to point
202 to the next message! */
203 if ( buf->tail < buf->head){
204 if ( (buf->tail + l) >= buf->head ){
205 /* we need to move the HEAD to point to the next message
206 * Theoretically we have enough room to add the whole message to the
207 * buffer, because of the first outer IF statement, so we don't have
208 * to worry about overflows here!
209 */
210 int k= buf->tail + l - buf->head; /* we need to know how many bytes
211 we are overwriting to make
212 enough room */
213 char *c=memchr(buf->data+buf->head + k,'\0',buf->size - (buf->head + k));
214 if (c != NULL) {/* do a sanity check just in case! */
215 buf->head = c - buf->data + 1; /* we need to convert pointer to
216 offset + skip the '\0' since
217 we need to point to the beginning
218 of the next message */
219 /* Note: HEAD is only used to "retrieve" messages, it's not used
220 when writing messages into our buffer */
221 }else{ /* show an error message to know we messed up? */
222 printf("Weird! Can't find the terminator token??? \n");
223 buf->head=0;
224 }
225 }
226 } /* in other cases no overflows have been done yet, so we don't care! */
227
228 /* we should be ok to append the message now */
229 strncpy(buf->data + buf->tail,msg,l); /* append our message */
230 buf->tail+=l; /* count full message w/ '\0' terminating char */
231 }else{
232 /* we need to break up the message and "circle" it around */
233 char *c;
234 int k=buf->tail + l - buf->size; /* count # of bytes we don't fit */
235
236 /* We need to move HEAD! This is always the case since we are going
237 * to "circle" the message.
238 */
239 c=memchr(buf->data + k ,'\0', buf->size - k);
240
241 if (c != NULL) /* if we don't have '\0'??? weird!!! */{
242 /* move head pointer*/
243 buf->head=c-buf->data+1;
244
245 /* now write the first part of the message */
246 strncpy(buf->data + buf->tail, msg, l - k - 1);
247
248 /* ALWAYS terminate end of buffer w/ '\0' */
249 buf->data[buf->size-1]='\0';
250
251 /* now write out the rest of the string to the beginning of the buffer */
252 strcpy(buf->data, &msg[l-k-1]);
253
254 /* we need to place the TAIL at the end of the message */
255 buf->tail = k + 1;
256 }else{
257 printf("Weird! Can't find the terminator token from the beginning??? \n");
258 buf->head = buf->tail = 0; /* reset buffer, since it's probably corrupted */
259 }
260
261 }
262 sem_up(s_semid);
263}
264#endif
Erik Andersenc053e412000-03-21 01:31:24 +0000265/* Note: There is also a function called "message()" in init.c */
Erik Andersen983b51b2000-04-04 18:14:25 +0000266/* Print a message to the log file. */
Erik Andersenf13df372000-04-18 23:51:51 +0000267static void message (char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
268static void message (char *fmt, ...)
Eric Andersen3843e961999-11-25 07:30:46 +0000269{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000270 int fd;
Erik Andersene3ed1562000-04-19 18:52:56 +0000271 struct flock fl;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000272 va_list arguments;
Eric Andersen3843e961999-11-25 07:30:46 +0000273
Erik Andersene3ed1562000-04-19 18:52:56 +0000274 fl.l_whence = SEEK_SET;
275 fl.l_start = 0;
276 fl.l_len = 1;
277
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000278#ifdef CONFIG_FEATURE_IPC_SYSLOG
Matt Kraai1f0c4362001-12-20 23:13:26 +0000279 if ((circular_logging) && (buf != NULL)){
Mark Whitley6317c4b2001-03-12 22:51:50 +0000280 char b[1024];
281 va_start (arguments, fmt);
282 vsprintf (b, fmt, arguments);
283 va_end (arguments);
284 circ_message(b);
285
286 }else
287#endif
Erik Andersenf13df372000-04-18 23:51:51 +0000288 if ((fd = device_open (logFilePath,
289 O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND |
290 O_NONBLOCK)) >= 0) {
Erik Andersene3ed1562000-04-19 18:52:56 +0000291 fl.l_type = F_WRLCK;
292 fcntl (fd, F_SETLKW, &fl);
Erik Andersenf13df372000-04-18 23:51:51 +0000293 va_start (arguments, fmt);
294 vdprintf (fd, fmt, arguments);
295 va_end (arguments);
Erik Andersene3ed1562000-04-19 18:52:56 +0000296 fl.l_type = F_UNLCK;
297 fcntl (fd, F_SETLKW, &fl);
Erik Andersenf13df372000-04-18 23:51:51 +0000298 close (fd);
Eric Andersen3843e961999-11-25 07:30:46 +0000299 } else {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000300 /* Always send console messages to /dev/console so people will see them. */
Erik Andersenf13df372000-04-18 23:51:51 +0000301 if ((fd = device_open (_PATH_CONSOLE,
302 O_WRONLY | O_NOCTTY | O_NONBLOCK)) >= 0) {
303 va_start (arguments, fmt);
304 vdprintf (fd, fmt, arguments);
305 va_end (arguments);
306 close (fd);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000307 } else {
Erik Andersenf13df372000-04-18 23:51:51 +0000308 fprintf (stderr, "Bummer, can't print: ");
309 va_start (arguments, fmt);
310 vfprintf (stderr, fmt, arguments);
311 fflush (stderr);
312 va_end (arguments);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000313 }
Eric Andersen3843e961999-11-25 07:30:46 +0000314 }
Eric Andersenb99df0f1999-11-24 09:04:33 +0000315}
316
Erik Andersenf13df372000-04-18 23:51:51 +0000317static void logMessage (int pri, char *msg)
Eric Andersen3843e961999-11-25 07:30:46 +0000318{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000319 time_t now;
320 char *timestamp;
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000321 static char res[20] = "";
Erik Andersene49d5ec2000-02-08 19:58:47 +0000322 CODE *c_pri, *c_fac;
Eric Andersenb99df0f1999-11-24 09:04:33 +0000323
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000324 if (pri != 0) {
325 for (c_fac = facilitynames;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000326 c_fac->c_name && !(c_fac->c_val == LOG_FAC(pri) << 3); c_fac++);
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000327 for (c_pri = prioritynames;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000328 c_pri->c_name && !(c_pri->c_val == LOG_PRI(pri)); c_pri++);
Matt Kraai5a964f92000-12-11 20:13:37 +0000329 if (c_fac->c_name == NULL || c_pri->c_name == NULL)
Erik Andersen9ffdaa62000-02-11 21:55:04 +0000330 snprintf(res, sizeof(res), "<%d>", pri);
331 else
332 snprintf(res, sizeof(res), "%s.%s", c_fac->c_name, c_pri->c_name);
333 }
Eric Andersen3843e961999-11-25 07:30:46 +0000334
Erik Andersene49d5ec2000-02-08 19:58:47 +0000335 if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' ||
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000336 msg[9] != ':' || msg[12] != ':' || msg[15] != ' ') {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000337 time(&now);
338 timestamp = ctime(&now) + 4;
339 timestamp[15] = '\0';
340 } else {
341 timestamp = msg;
342 timestamp[15] = '\0';
343 msg += 16;
344 }
Eric Andersen3843e961999-11-25 07:30:46 +0000345
Erik Andersene49d5ec2000-02-08 19:58:47 +0000346 /* todo: supress duplicates */
Eric Andersen3843e961999-11-25 07:30:46 +0000347
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000348#ifdef CONFIG_FEATURE_REMOTE_LOG
Eric Andersenced2cef2000-07-20 23:41:24 +0000349 /* send message to remote logger */
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000350 if ( -1 != remotefd){
Mark Whitley59ab0252001-01-23 22:30:04 +0000351static const int IOV_COUNT = 2;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000352 struct iovec iov[IOV_COUNT];
353 struct iovec *v = iov;
Eric Andersenced2cef2000-07-20 23:41:24 +0000354
Eric Andersen044228d2001-07-17 01:12:36 +0000355 memset(&res, 0, sizeof(res));
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000356 snprintf(res, sizeof(res), "<%d>", pri);
357 v->iov_base = res ;
358 v->iov_len = strlen(res);
359 v++;
Eric Andersenced2cef2000-07-20 23:41:24 +0000360
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000361 v->iov_base = msg;
362 v->iov_len = strlen(msg);
363
364 if ( -1 == writev(remotefd,iov, IOV_COUNT)){
365 error_msg_and_die("syslogd: cannot write to remote file handle on"
Matt Kraaidd19c692001-01-31 19:00:21 +0000366 "%s:%d",RemoteHost,RemotePort);
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000367 }
368 }
Matt Kraai1f0c4362001-12-20 23:13:26 +0000369 if (local_logging)
Eric Andersenced2cef2000-07-20 23:41:24 +0000370#endif
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000371 /* now spew out the message to wherever it is supposed to go */
372 message("%s %s %s %s\n", timestamp, LocalHostName, res, msg);
Eric Andersen76fef0a2000-12-08 19:41:21 +0000373
Eric Andersenced2cef2000-07-20 23:41:24 +0000374
Eric Andersen3843e961999-11-25 07:30:46 +0000375}
376
377static void quit_signal(int sig)
378{
Eric Andersen238bc402001-05-07 17:55:05 +0000379 logMessage(LOG_SYSLOG | LOG_INFO, "System log daemon exiting.");
Erik Andersen983b51b2000-04-04 18:14:25 +0000380 unlink(lfile);
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000381#ifdef CONFIG_FEATURE_IPC_SYSLOG
Mark Whitley6317c4b2001-03-12 22:51:50 +0000382 ipcsyslog_cleanup();
383#endif
384
Erik Andersene49d5ec2000-02-08 19:58:47 +0000385 exit(TRUE);
Eric Andersen3843e961999-11-25 07:30:46 +0000386}
387
Eric Andersen3843e961999-11-25 07:30:46 +0000388static void domark(int sig)
389{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000390 if (MarkInterval > 0) {
391 logMessage(LOG_SYSLOG | LOG_INFO, "-- MARK --");
392 alarm(MarkInterval);
393 }
Eric Andersen3843e961999-11-25 07:30:46 +0000394}
395
Eric Andersen22ecf042001-07-02 17:32:40 +0000396/* This must be a #define, since when DODEBUG and BUFFERS_GO_IN_BSS are
397 * enabled, we otherwise get a "storage size isn't constant error. */
398#define BUFSIZE 1023
Eric Andersen67e32302000-06-19 17:48:02 +0000399static int serveConnection (int conn)
Pavel Roskinda10ec02000-06-07 21:08:25 +0000400{
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000401 RESERVE_CONFIG_BUFFER(tmpbuf, BUFSIZE + 1);
Pavel Roskinda10ec02000-06-07 21:08:25 +0000402 int n_read;
Matt Kraaib6ec7812001-08-14 17:32:23 +0000403 char *p = tmpbuf;
Pavel Roskinda10ec02000-06-07 21:08:25 +0000404
Mark Whitleybff6b182001-03-27 20:17:58 +0000405 n_read = read (conn, tmpbuf, BUFSIZE );
406
Matt Kraaib6ec7812001-08-14 17:32:23 +0000407 while (p < tmpbuf + n_read) {
Pavel Roskinda10ec02000-06-07 21:08:25 +0000408
409 int pri = (LOG_USER | LOG_NOTICE);
410 char line[ BUFSIZE + 1 ];
411 unsigned char c;
412
Matt Kraaib6ec7812001-08-14 17:32:23 +0000413 char *q = line;
Pavel Roskinda10ec02000-06-07 21:08:25 +0000414
Eric Andersenf6aa13d2001-03-23 17:08:21 +0000415 tmpbuf[ n_read - 1 ] = '\0';
Pavel Roskinda10ec02000-06-07 21:08:25 +0000416
417 while (p && (c = *p) && q < &line[ sizeof (line) - 1 ]) {
418 if (c == '<') {
419 /* Parse the magic priority number. */
420 pri = 0;
421 while (isdigit (*(++p))) {
422 pri = 10 * pri + (*p - '0');
423 }
Eric Andersenced2cef2000-07-20 23:41:24 +0000424 if (pri & ~(LOG_FACMASK | LOG_PRIMASK)){
Pavel Roskinda10ec02000-06-07 21:08:25 +0000425 pri = (LOG_USER | LOG_NOTICE);
Eric Andersenced2cef2000-07-20 23:41:24 +0000426 }
Pavel Roskinda10ec02000-06-07 21:08:25 +0000427 } else if (c == '\n') {
428 *q++ = ' ';
429 } else if (iscntrl (c) && (c < 0177)) {
430 *q++ = '^';
431 *q++ = c ^ 0100;
432 } else {
433 *q++ = c;
434 }
435 p++;
436 }
437 *q = '\0';
Matt Kraaib6ec7812001-08-14 17:32:23 +0000438 p++;
Pavel Roskinda10ec02000-06-07 21:08:25 +0000439 /* Now log it */
440 logMessage (pri, line);
441 }
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000442 RELEASE_CONFIG_BUFFER (tmpbuf);
Mark Whitleybff6b182001-03-27 20:17:58 +0000443 return n_read;
Pavel Roskinda10ec02000-06-07 21:08:25 +0000444}
445
Eric Andersenced2cef2000-07-20 23:41:24 +0000446
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000447#ifdef CONFIG_FEATURE_REMOTE_LOG
Eric Andersenced2cef2000-07-20 23:41:24 +0000448static void init_RemoteLog (void){
449
450 struct sockaddr_in remoteaddr;
451 struct hostent *hostinfo;
452 int len = sizeof(remoteaddr);
453
Eric Andersen044228d2001-07-17 01:12:36 +0000454 memset(&remoteaddr, 0, len);
Mark Whitleybff6b182001-03-27 20:17:58 +0000455
Eric Andersenced2cef2000-07-20 23:41:24 +0000456 remotefd = socket(AF_INET, SOCK_DGRAM, 0);
457
458 if (remotefd < 0) {
Matt Kraaidd19c692001-01-31 19:00:21 +0000459 error_msg_and_die("syslogd: cannot create socket");
Eric Andersenced2cef2000-07-20 23:41:24 +0000460 }
461
Matt Kraaic55b8d42001-05-16 15:40:51 +0000462 hostinfo = xgethostbyname(RemoteHost);
Eric Andersenced2cef2000-07-20 23:41:24 +0000463
464 remoteaddr.sin_family = AF_INET;
465 remoteaddr.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list;
466 remoteaddr.sin_port = htons(RemotePort);
467
468 /*
469 Since we are using UDP sockets, connect just sets the default host and port
470 for future operations
471 */
472 if ( 0 != (connect(remotefd, (struct sockaddr *) &remoteaddr, len))){
Matt Kraaidd19c692001-01-31 19:00:21 +0000473 error_msg_and_die("syslogd: cannot connect to remote host %s:%d", RemoteHost, RemotePort);
Eric Andersenced2cef2000-07-20 23:41:24 +0000474 }
475
476}
477#endif
478
Erik Andersen983b51b2000-04-04 18:14:25 +0000479static void doSyslogd (void) __attribute__ ((noreturn));
480static void doSyslogd (void)
Eric Andersen3843e961999-11-25 07:30:46 +0000481{
Erik Andersene49d5ec2000-02-08 19:58:47 +0000482 struct sockaddr_un sunx;
Erik Andersen1d1d9502000-04-21 01:26:49 +0000483 socklen_t addrLength;
484
Erik Andersenf13df372000-04-18 23:51:51 +0000485
Erik Andersen983b51b2000-04-04 18:14:25 +0000486 int sock_fd;
Erik Andersenf13df372000-04-18 23:51:51 +0000487 fd_set fds;
488
Erik Andersenf13df372000-04-18 23:51:51 +0000489 /* Set up signal handlers. */
Erik Andersen983b51b2000-04-04 18:14:25 +0000490 signal (SIGINT, quit_signal);
491 signal (SIGTERM, quit_signal);
492 signal (SIGQUIT, quit_signal);
493 signal (SIGHUP, SIG_IGN);
Pavel Roskind39d1202000-09-13 14:14:29 +0000494 signal (SIGCHLD, SIG_IGN);
495#ifdef SIGCLD
Erik Andersene3ed1562000-04-19 18:52:56 +0000496 signal (SIGCLD, SIG_IGN);
Pavel Roskind39d1202000-09-13 14:14:29 +0000497#endif
Erik Andersen983b51b2000-04-04 18:14:25 +0000498 signal (SIGALRM, domark);
499 alarm (MarkInterval);
Eric Andersenb99df0f1999-11-24 09:04:33 +0000500
Erik Andersenf13df372000-04-18 23:51:51 +0000501 /* Create the syslog file so realpath() can work. */
Eric Andersen87d893c2001-05-03 07:01:41 +0000502 if (realpath (_PATH_LOG, lfile) != NULL)
503 unlink (lfile);
Erik Andersen983b51b2000-04-04 18:14:25 +0000504
Erik Andersenf13df372000-04-18 23:51:51 +0000505 memset (&sunx, 0, sizeof (sunx));
Erik Andersen983b51b2000-04-04 18:14:25 +0000506 sunx.sun_family = AF_UNIX;
Erik Andersenf13df372000-04-18 23:51:51 +0000507 strncpy (sunx.sun_path, lfile, sizeof (sunx.sun_path));
508 if ((sock_fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
Eric Andersen87d893c2001-05-03 07:01:41 +0000509 perror_msg_and_die ("Couldn't get file descriptor for socket " _PATH_LOG);
Eric Andersenb99df0f1999-11-24 09:04:33 +0000510
Erik Andersen983b51b2000-04-04 18:14:25 +0000511 addrLength = sizeof (sunx.sun_family) + strlen (sunx.sun_path);
Erik Andersenf13df372000-04-18 23:51:51 +0000512 if ((bind (sock_fd, (struct sockaddr *) &sunx, addrLength)) || (listen (sock_fd, 5)))
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000513 perror_msg_and_die ("Could not connect to socket " _PATH_LOG);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000514
Erik Andersenf13df372000-04-18 23:51:51 +0000515 if (chmod (lfile, 0666) < 0)
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000516 perror_msg_and_die ("Could not set permission on " _PATH_LOG);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000517
Erik Andersenf13df372000-04-18 23:51:51 +0000518 FD_ZERO (&fds);
519 FD_SET (sock_fd, &fds);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000520
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000521#ifdef CONFIG_FEATURE_IPC_SYSLOG
Matt Kraai1f0c4362001-12-20 23:13:26 +0000522 if (circular_logging ){
Eric Andersenea906502001-04-05 20:55:17 +0000523 ipcsyslog_init();
524 }
525#endif
526
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000527 #ifdef CONFIG_FEATURE_REMOTE_LOG
Matt Kraai1f0c4362001-12-20 23:13:26 +0000528 if (doRemoteLog){
Eric Andersenced2cef2000-07-20 23:41:24 +0000529 init_RemoteLog();
530 }
531 #endif
532
Eric Andersen238bc402001-05-07 17:55:05 +0000533 logMessage (LOG_SYSLOG | LOG_INFO, "syslogd started: " BB_BANNER);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000534
Erik Andersen983b51b2000-04-04 18:14:25 +0000535 for (;;) {
Erik Andersenf13df372000-04-18 23:51:51 +0000536
537 fd_set readfds;
538 int n_ready;
539 int fd;
540
541 memcpy (&readfds, &fds, sizeof (fds));
Erik Andersene49d5ec2000-02-08 19:58:47 +0000542
Erik Andersen983b51b2000-04-04 18:14:25 +0000543 if ((n_ready = select (FD_SETSIZE, &readfds, NULL, NULL, NULL)) < 0) {
544 if (errno == EINTR) continue; /* alarm may have happened. */
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000545 perror_msg_and_die ("select error");
Erik Andersene49d5ec2000-02-08 19:58:47 +0000546 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000547
Erik Andersenf13df372000-04-18 23:51:51 +0000548 for (fd = 0; (n_ready > 0) && (fd < FD_SETSIZE); fd++) {
Erik Andersen983b51b2000-04-04 18:14:25 +0000549 if (FD_ISSET (fd, &readfds)) {
Erik Andersene3ed1562000-04-19 18:52:56 +0000550
Erik Andersenf13df372000-04-18 23:51:51 +0000551 --n_ready;
Erik Andersene3ed1562000-04-19 18:52:56 +0000552
Erik Andersen983b51b2000-04-04 18:14:25 +0000553 if (fd == sock_fd) {
Erik Andersene3ed1562000-04-19 18:52:56 +0000554 int conn;
Erik Andersene3ed1562000-04-19 18:52:56 +0000555
Mark Whitley1a49fc52001-03-12 19:51:09 +0000556 //printf("New Connection request.\n");
Erik Andersenf13df372000-04-18 23:51:51 +0000557 if ((conn = accept (sock_fd, (struct sockaddr *) &sunx, &addrLength)) < 0) {
Matt Kraai1fa1ade2000-12-18 03:57:16 +0000558 perror_msg_and_die ("accept error");
Erik Andersen983b51b2000-04-04 18:14:25 +0000559 }
Erik Andersena6c75222000-04-18 00:00:52 +0000560
Mark Whitley1a49fc52001-03-12 19:51:09 +0000561 FD_SET(conn, &fds);
562 //printf("conn: %i, set_size: %i\n",conn,FD_SETSIZE);
Mark Whitleybff6b182001-03-27 20:17:58 +0000563 } else {
Mark Whitley1a49fc52001-03-12 19:51:09 +0000564 //printf("Serving connection: %i\n",fd);
Mark Whitleybff6b182001-03-27 20:17:58 +0000565 if ( serveConnection(fd) <= 0 ) {
566 close (fd);
567 FD_CLR(fd, &fds);
568 }
Mark Whitley1a49fc52001-03-12 19:51:09 +0000569 } /* fd == sock_fd */
570 }/* FD_ISSET() */
571 }/* for */
572 } /* for main loop */
Eric Andersenb99df0f1999-11-24 09:04:33 +0000573}
574
Eric Andersen3843e961999-11-25 07:30:46 +0000575extern int syslogd_main(int argc, char **argv)
576{
Eric Andersene5c24df2001-03-29 21:58:33 +0000577 int opt;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000578 int doFork = TRUE;
579
Erik Andersene49d5ec2000-02-08 19:58:47 +0000580 char *p;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000581
Eric Andersen394cf222000-12-11 16:48:50 +0000582 /* do normal option parsing */
Mark Whitley6317c4b2001-03-12 22:51:50 +0000583 while ((opt = getopt(argc, argv, "m:nO:R:LC")) > 0) {
Eric Andersen394cf222000-12-11 16:48:50 +0000584 switch (opt) {
Erik Andersene49d5ec2000-02-08 19:58:47 +0000585 case 'm':
Eric Andersen394cf222000-12-11 16:48:50 +0000586 MarkInterval = atoi(optarg) * 60;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000587 break;
588 case 'n':
589 doFork = FALSE;
590 break;
Erik Andersene49d5ec2000-02-08 19:58:47 +0000591 case 'O':
Matt Kraaic8227632001-11-12 16:57:27 +0000592 logFilePath = xstrdup(optarg);
Erik Andersene49d5ec2000-02-08 19:58:47 +0000593 break;
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000594#ifdef CONFIG_FEATURE_REMOTE_LOG
Eric Andersenced2cef2000-07-20 23:41:24 +0000595 case 'R':
Matt Kraaic8227632001-11-12 16:57:27 +0000596 RemoteHost = xstrdup(optarg);
Eric Andersen394cf222000-12-11 16:48:50 +0000597 if ( (p = strchr(RemoteHost, ':'))){
598 RemotePort = atoi(p+1);
599 *p = '\0';
Mark Whitleybff6b182001-03-27 20:17:58 +0000600 }
Eric Andersen394cf222000-12-11 16:48:50 +0000601 doRemoteLog = TRUE;
602 break;
Eric Andersen70d09ed2000-12-11 16:24:16 +0000603 case 'L':
604 local_logging = TRUE;
Eric Andersenbf2b8ae2000-12-08 19:52:01 +0000605 break;
Eric Andersenced2cef2000-07-20 23:41:24 +0000606#endif
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000607#ifdef CONFIG_FEATURE_IPC_SYSLOG
Mark Whitley6317c4b2001-03-12 22:51:50 +0000608 case 'C':
609 circular_logging = TRUE;
610 break;
611#endif
Erik Andersene49d5ec2000-02-08 19:58:47 +0000612 default:
Eric Andersen67991cf2001-02-14 21:23:06 +0000613 show_usage();
Eric Andersen3843e961999-11-25 07:30:46 +0000614 }
Erik Andersene49d5ec2000-02-08 19:58:47 +0000615 }
616
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000617#ifdef CONFIG_FEATURE_REMOTE_LOG
Eric Andersen4ed17822000-12-11 19:28:29 +0000618 /* If they have not specified remote logging, then log locally */
Matt Kraai1f0c4362001-12-20 23:13:26 +0000619 if (! doRemoteLog)
Eric Andersen4ed17822000-12-11 19:28:29 +0000620 local_logging = TRUE;
621#endif
622
Mark Whitley6317c4b2001-03-12 22:51:50 +0000623
Erik Andersene49d5ec2000-02-08 19:58:47 +0000624 /* Store away localhost's name before the fork */
625 gethostname(LocalHostName, sizeof(LocalHostName));
626 if ((p = strchr(LocalHostName, '.'))) {
627 *p++ = '\0';
628 }
629
Erik Andersen983b51b2000-04-04 18:14:25 +0000630 umask(0);
631
Matt Kraai1f0c4362001-12-20 23:13:26 +0000632 if (doFork) {
Eric Andersen72f9a422001-10-28 05:12:20 +0000633#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)
Eric Andersene5c24df2001-03-29 21:58:33 +0000634 if (daemon(0, 1) < 0)
635 perror_msg_and_die("daemon");
Eric Andersen72f9a422001-10-28 05:12:20 +0000636#else
637 error_msg_and_die("daemon not supported");
638#endif
Eric Andersen3843e961999-11-25 07:30:46 +0000639 }
Eric Andersene5c24df2001-03-29 21:58:33 +0000640 doSyslogd();
Eric Andersenb186d981999-12-03 09:19:54 +0000641
Matt Kraai3e856ce2000-12-01 02:55:13 +0000642 return EXIT_SUCCESS;
Eric Andersen3843e961999-11-25 07:30:46 +0000643}
Erik Andersen983b51b2000-04-04 18:14:25 +0000644
645/*
Erik Andersene3ed1562000-04-19 18:52:56 +0000646Local Variables
647c-file-style: "linux"
648c-basic-offset: 4
649tab-width: 4
650End:
651*/