Kick out usyslogd in favour of syslogd Giovanni's syslogd port

This commit is contained in:
Ben Gras 2006-04-03 13:07:42 +00:00
parent f3771bb74c
commit 6a0829c700
11 changed files with 1567 additions and 115 deletions

View file

@ -203,7 +203,6 @@ ALL = \
update \
uud \
uue \
usyslogd \
vol \
wc \
which \
@ -864,10 +863,6 @@ uud: uud.c
$(CCLD) -o $@ $?
@install -S 4kw $@
usyslogd: usyslogd.c
$(CCLD) -o $@ $?
@install -S 4kw $@
uue: uue.c
$(CCLD) -o $@ $?
@install -S 4kw $@
@ -1101,7 +1096,6 @@ install: \
/usr/bin/uudecode \
/usr/bin/uue \
/usr/bin/uuencode \
/usr/bin/usyslogd \
/usr/bin/vol \
/usr/bin/wc \
/usr/bin/which \
@ -1670,9 +1664,6 @@ install: \
/usr/bin/uudecode: /usr/bin/uud
install -l $? $@
/usr/bin/usyslogd: usyslogd
install -cs -o bin $? $@
/usr/bin/uue: uue
install -cs -o bin $? $@

View file

@ -1,106 +0,0 @@
/* Microsyslogd that does basic syslogging.
*/
#include <stdio.h>
#include <sys/select.h>
#include <sys/utsname.h>
#include <sys/types.h>
#include <time.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
char *nodename;
void logline(FILE *outfp, char *proc, char *line)
{
time_t now;
struct tm *tm;
char *d, *s;
time(&now);
tm = localtime(&now);
d=asctime(tm);
/* Trim off year and newline. */
if((s=strrchr(d, ' ')))
*s = '\0';
if(s=strchr(d, ' ')) d = s+1;
fprintf(outfp, "%s %s: %s\n", d, nodename, line);
}
void copy(int in_fd, FILE *outfp)
{
static char linebuf[5*1024];
int l, acc = 0;
while((l=read(in_fd, linebuf, sizeof(linebuf)-2)) > 0) {
char *b, *eol;
int i;
acc += l;
for(i = 0; i < l; i++)
if(linebuf[i] == '\0')
linebuf[i] = ' ';
if(linebuf[l-1] == '\n') l--;
linebuf[l] = '\n';
linebuf[l+1] = '\0';
b = linebuf;
while(eol = strchr(b, '\n')) {
*eol = '\0';
logline(outfp, "kernel", b);
b = eol+1;
}
}
/* Nothing sensible happened? Avoid busy-looping. */
if(!acc) sleep(1);
return;
}
int
main(int argc, char *argv[])
{
int config_fd, klog_fd, n, maxfd;
char *nn;
FILE *logfp;
struct utsname utsname;
if(uname(&utsname) < 0) {
perror("uname");
return 1;
}
nodename = utsname.nodename;
if((nn=strchr(nodename, '.')))
*nn = '\0';
if((klog_fd = open("/dev/klog", O_NONBLOCK | O_RDONLY)) < 0) {
perror("/dev/klog");
return 1;
}
if(!(logfp = fopen("/usr/log/messages", "a"))) {
return 1;
}
maxfd = klog_fd;
while(1) {
fd_set fds;
FD_ZERO(&fds);
FD_SET(klog_fd, &fds);
n = select(maxfd+1, &fds, NULL, NULL, NULL);
if(n <= 0) {
sleep(1);
continue;
}
if(FD_ISSET(klog_fd, &fds)) {
copy(klog_fd, logfp);
}
fflush(logfp);
sync();
}
return 0;
}

94
commands/syslogd/.depend Normal file
View file

@ -0,0 +1,94 @@
logger.o: /usr/include/ansi.h
logger.o: /usr/include/ctype.h
logger.o: /usr/include/errno.h
logger.o: /usr/include/minix/sys_config.h
logger.o: /usr/include/minix/type.h
logger.o: /usr/include/stdio.h
logger.o: /usr/include/stdlib.h
logger.o: /usr/include/string.h
logger.o: /usr/include/sys/dir.h
logger.o: /usr/include/sys/types.h
logger.o: /usr/include/syslog.h
logger.o: /usr/include/unistd.h
logger.o: logger.c
syslog.o: /usr/include/ansi.h
syslog.o: /usr/include/errno.h
syslog.o: /usr/include/fcntl.h
syslog.o: /usr/include/minix/ioctl.h
syslog.o: /usr/include/minix/sys_config.h
syslog.o: /usr/include/minix/type.h
syslog.o: /usr/include/net/gen/in.h
syslog.o: /usr/include/net/gen/inet.h
syslog.o: /usr/include/net/gen/netdb.h
syslog.o: /usr/include/net/gen/udp.h
syslog.o: /usr/include/net/gen/udp_io.h
syslog.o: /usr/include/net/hton.h
syslog.o: /usr/include/net/ioctl.h
syslog.o: /usr/include/net/netlib.h
syslog.o: /usr/include/stdarg.h
syslog.o: /usr/include/stdio.h
syslog.o: /usr/include/stdlib.h
syslog.o: /usr/include/string.h
syslog.o: /usr/include/sys/dir.h
syslog.o: /usr/include/sys/ioc_cmos.h
syslog.o: /usr/include/sys/ioc_disk.h
syslog.o: /usr/include/sys/ioc_file.h
syslog.o: /usr/include/sys/ioc_memory.h
syslog.o: /usr/include/sys/ioc_scsi.h
syslog.o: /usr/include/sys/ioc_sound.h
syslog.o: /usr/include/sys/ioc_tape.h
syslog.o: /usr/include/sys/ioc_tty.h
syslog.o: /usr/include/sys/ioctl.h
syslog.o: /usr/include/sys/types.h
syslog.o: /usr/include/syslog.h
syslog.o: /usr/include/time.h
syslog.o: /usr/include/unistd.h
syslog.o: syslog.c
syslog_test.o: /usr/include/ansi.h
syslog_test.o: /usr/include/minix/sys_config.h
syslog_test.o: /usr/include/minix/type.h
syslog_test.o: /usr/include/sys/types.h
syslog_test.o: /usr/include/syslog.h
syslog_test.o: /usr/include/unistd.h
syslog_test.o: syslog_test.c
syslogd.o: /usr/include/ansi.h
syslogd.o: /usr/include/ctype.h
syslogd.o: /usr/include/errno.h
syslogd.o: /usr/include/fcntl.h
syslogd.o: /usr/include/limits.h
syslogd.o: /usr/include/minix/ioctl.h
syslogd.o: /usr/include/minix/sys_config.h
syslogd.o: /usr/include/minix/type.h
syslogd.o: /usr/include/net/gen/in.h
syslogd.o: /usr/include/net/gen/netdb.h
syslogd.o: /usr/include/net/gen/udp.h
syslogd.o: /usr/include/net/gen/udp_io.h
syslogd.o: /usr/include/net/hton.h
syslogd.o: /usr/include/net/ioctl.h
syslogd.o: /usr/include/net/netlib.h
syslogd.o: /usr/include/signal.h
syslogd.o: /usr/include/stdio.h
syslogd.o: /usr/include/stdlib.h
syslogd.o: /usr/include/string.h
syslogd.o: /usr/include/sys/dir.h
syslogd.o: /usr/include/sys/ioc_cmos.h
syslogd.o: /usr/include/sys/ioc_disk.h
syslogd.o: /usr/include/sys/ioc_file.h
syslogd.o: /usr/include/sys/ioc_memory.h
syslogd.o: /usr/include/sys/ioc_scsi.h
syslogd.o: /usr/include/sys/ioc_sound.h
syslogd.o: /usr/include/sys/ioc_tape.h
syslogd.o: /usr/include/sys/ioc_tty.h
syslogd.o: /usr/include/sys/ioctl.h
syslogd.o: /usr/include/sys/select.h
syslogd.o: /usr/include/sys/time.h
syslogd.o: /usr/include/sys/types.h
syslogd.o: /usr/include/sys/wait.h
syslogd.o: /usr/include/syslog.h
syslogd.o: /usr/include/time.h
syslogd.o: /usr/include/unistd.h
syslogd.o: syslogd.c

View file

@ -0,0 +1,17 @@
Version 1.1 Oct. 28, 2000
- first release for testing.
Version 1.2 Jan. 23, 2001
- Changed pidfile directory to '/usr/spool/locks'
so at boot old file is deleted.
- Changed the 'debug' variable to 'DbgOpt' so 'debug'
can be a preprocessor define from Makefile.
Version 1.3
- Changes for Minix 3.0
- Changed pidfile to /var/run/syslogd.pid and added code
for setting pathname from Makefile
- Merged code from usyslogd.c to handle kernel messages.
- Reworked Makefile to make a correct installation
$Id$

50
commands/syslogd/Makefile Normal file
View file

@ -0,0 +1,50 @@
##
## @(#)Makefile 1.00 Jan. 11, 2000
##
## Makefile for syslogd/klogd
## $Id$
BINDIR = /usr/bin
CC = exec cc
RM = rm -f
EXTRA = -DPIDFILE=\"/var/run/syslogd.pid\"
CPPFLAGS= -D_MINIX -D_POSIX_SOURCE -Ddebug=0 $(EXTRA) -I.
CFLAGS = -m -O $(CPPFLAGS)
MKDEP = mkdep "$(CC) -E $(CPPFLAGS)"
LDFLAGS = -i -o $@
TARGETS = logger syslogd
SRCS = logger.c syslog.c syslog_test.c syslogd.c
OBJS = logger.o syslog.o syslog_test.o syslogd.o
all: $(TARGETS)
syslogd: syslogd.o
$(CC) $? $(LDFLAGS)
@install -S 8kw $@
syslog_test: syslog_test.o syslog.o
$(CC) syslog_test.o syslog.o $(LDFLAGS)
@install -S 2kw $@
logger: logger.o syslog.o
$(CC) logger.o syslog.o $(LDFLAGS)
@install -S 2kw $@
clean:
$(RM) $(OBJS) $(TARGETS) syslog_test *.BAK core
install: install-bin install-sys
install-bin: $(BINDIR)/logger $(BINDIR)/syslog_test $(BINDIR)/syslogd
$(BINDIR)/logger: logger
install -cs -m 755 -o bin -g operator $? $@
$(BINDIR)/syslog_test: syslog_test
install -cs -m 755 -o bin -g operator $? $@
$(BINDIR)/syslogd: syslogd
install -cs -m 700 -o root -g operator $? $@
install-sys: /etc/syslog.conf
/etc/syslog.conf: syslog.conf
install -c -m 644 -o root -g operator $? $@

69
commands/syslogd/README Normal file
View file

@ -0,0 +1,69 @@
This is just syslogd and the test programs now. syslog() is in libc 4.2
syslogd has been changed to use /proc/kmsg for kernel messages. It also
avoids making any terminal it opens its controlling terminal. Otherwise
we have a dodgy race condition between processes connecting to terminals
which can result in the terminal having the wrong group at the wrong time.
The syslog() in libc 4.2 needs changing to use O_NOCTTY on its opens as
well.
Mike Jagdis Internet: jaggy@purplet.demon.co.uk
FidoNet: Mike Jagdis, 2:252/305
---------------------------------------------------------------------------
Syslogd and Syslog.o
These are the syslogd and syslog ported from 4.3BSD (that's the new one with
the *very* flexible config file).
Syslogd is essentially unchanged from the 4.3BSD, with the exception that
*nothing* is ever logged to the console (BAD thing to do on a UNIXpc). You
can configure it (via /etc/syslog.conf) to log messages in different
logfiles (depending upon the sender's facility code and the priority), log
to users' terminals (same dependancies), and if things get real bad, it can
do a wall (write-all; same dependancies).
Syslog is really only modified in that it uses UDP datagrams because I had
no luck at all using UNIX domain sockets on the 3B1. See syslog.h for
facility codes and priorities that can be used.
BUGS:
Messages from facilities LOG_KERN, LOG_USER, and LOG_PRT never can be
wall-ed, no matter how high the priority. I'm still trying to decide if
this is a bug or a feature. :-)
ALSO INCLUDED:
Syslog_test, sendlog (to use from shell scripts) and logger (for use in
shell script also).
NEEDED:
The resolver routines in libresolv.a are not needed, but allow you to log to
hosts not present in /etc/hosts and to accept logging from same.
-----------------------------------------------------------------------
Fixed up UNIX domain socket code, added Linux specific code to read messages
from the kernel.
The #ifdefs are now :-
SYSLOG_INET listen on a UDP socket (syslogd)
log via UDP (syslog library call)
SYSLOG_UNIXAF listen on a UNIX domain socker (syslogd)
log via UNIX domain (syslogd library)
SYSLOG_KERNEL fork a second copy to read kernel messages using
syslog system call.
syslogd should be built with one or more of these flags, libsyslog.a should
be built with SYSLOG_INET or SYSLOG_UNIXAF, SYSLOG_INET is used in preference
to SYSLOG_UNIXAF.
readlog is a program which reads from the kernel and records the messages
it finds in syslogd via the normal library call interface, it can be run
instead of building syslogd with SYSLOG_KERNEL.

View file

@ -0,0 +1,28 @@
This is the porting to Minix of the "syslogd" facility
available on many other *nix systems.
Since I' m still using an old 286 machine for my Minix
environment, I choosed to start from an old implementation
which has only the basic features. The result is a smaller
program, more suitable for 16 bits machines.
The file syslog.c should be included in C compiler library
(libc.a) or directly linked with prorams requiring syslog.
If you choose the former solution, you must recreate the
library. After having copied the file syslog.c to the
directory '/usr/src/libs/other' you have to modify the
Makefile in this directory adding syslog.c.
Then issue a 'make' command in the '/usr/src/libs' and wait
a while. Then issue 'make install' to install the new object.
NOTE: The network must be configured, up and running for
the package to work
Giovanni Falzoni <gfalzoni@inwind.it>
$Id$

188
commands/syslogd/logger.c Normal file
View file

@ -0,0 +1,188 @@
/* Copyright (c) 1983, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* #ifndef lint
* char copyright[] =
* "@(#) Copyright (c) 1983 Regents of the University of California.\n\
* All rights reserved.\n";
* #endif
*
* #ifndef lint
* static char sccsid[] = "@(#)logger.c 6.8 (Berkeley) 6/29/88";
* #endif
*
* Porting to Minix by G. Falzoni <gfalzoni@inwind.it>
* $Id$
*/
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
/*
** LOGGER -- read and log utility
**
** This program reads from an input and arranges to write the
** result on the system log, along with a useful tag.
*/
#define SYSLOG_NAMES
#include <syslog.h>
/*
** Name: void bailout(char *msg, char *arg);
** Function: Handles error exit.
*/
void bailout(const char *msg, const char *arg)
{
fprintf(stderr, "logger: %s %s\n", msg, arg);
exit(EXIT_FAILURE);
}
/*
** Name: int decode(char *name, struct code * codetab);
** Function: Decodes a name to the equivalent priority/facility.
*/
int decode(char *name, const struct _code * codetab)
{
const struct _code *c;
if (isdigit(*name)) return(atoi(name));
for (c = codetab; c->c_name; c++)
if (!strcasecmp(name, c->c_name)) return(c->c_val);
return(-1);
}
/*
** Name: int pencode(char *s);
** Function: Decode a symbolic name (facility/priority)
** to a numeric value.
*/
int pencode(char *s)
{
char *save;
int fac, lev;
for (save = s; *s && *s != '.'; ++s);
if (*s) {
*s = '\0';
fac = decode(save, FacNames);
if (fac < 0) bailout("unknown facility name:", save);
*s++ = '.';
} else {
fac = 0;
s = save;
}
lev = decode(s, PriNames);
if (lev < 0) bailout("unknown priority name:", save);
return((lev & LOG_PRIMASK) | (fac & LOG_FACMASK));
}
/*
** Name: int main(int argc, char **argv);
** Function: Main entry for logger.
*/
int main(int argc, char **argv)
{
int pri = LOG_NOTICE;
int ch, logflags = 0;
char *tag, buf[200];
static const char usage[] =
"[-i] [-f file] [-p pri] [-t tag] [ message ... ]";
tag = NULL;
while ((ch = getopt(argc, argv, "f:ip:t:")) != EOF) {
switch ((char) ch) {
case 'f': /* file to log */
if (freopen(optarg, "r", stdin) == NULL) {
bailout(strerror(errno), optarg);
}
break;
case 'i': /* log process id also */
logflags |= LOG_PID;
break;
case 'p': /* priority */
pri = pencode(optarg);
break;
case 't': /* tag */
tag = optarg;
break;
case '?':
default: bailout(usage, ""); break;
}
}
argc -= optind;
argv += optind;
/* Setup for logging */
openlog(tag ? tag : getlogin(), logflags, 0);
fclose(stdout);
if (argc > 0) { /* Log input line if appropriate */
char *p, *endp;
int len;
for (p = buf, endp = buf + sizeof(buf) - 1;;) {
len = strlen(*argv);
if (p + len < endp && p > buf) {
*--p = '\0';
syslog(pri, buf);
p = buf;
}
if (len > sizeof(buf) - 1) {
syslog(pri, *argv++);
if (!--argc) break;
} else {
memcpy(p, *argv++, len);
p += len;
if (!--argc) break;
*p++ = ' ';
*--p = '\0';
}
}
if (p != buf) {
*p = '\0';
syslog(pri, buf);
}
} else /* Main loop */
while (fgets(buf, sizeof(buf), stdin) != NULL) syslog(pri, buf);
return EXIT_SUCCESS;
}
/** logger.c **/

167
commands/syslogd/syslog.c Normal file
View file

@ -0,0 +1,167 @@
/* Copyright (c) 1983, 1988, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* #if defined(LIBC_SCCS) && !defined(lint)
* static char sccsid[] = "@(#)syslog.c 8.4 (Berkeley) 3/18/94";
* #endif
*
* Author: Eric Allman
* Modified to use UNIX domain IPC by Ralph Campbell
* Patched March 12, 1996 by A. Ian Vogelesang <vogelesang@hdshq.com>
* Rewritten by Martin Mares <mj@atrey.karlin.mff.cuni.cz> on May 14, 1997
* Rewritten by G. Falzoni <gfalzoni@inwind.it> for porting to Minix
*
* $Id$
*/
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <syslog.h>
#include <sys/ioctl.h>
#include <net/netlib.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/udp.h>
#include <net/gen/udp_io.h>
#include <net/gen/netdb.h>
#include <errno.h>
#include <net/gen/inet.h>
static int LogPid = (-1);
static int nfd = (-1);
static int LogFacility = LOG_USER;
static int LogFlags = 0;
static char TagBuffer[40] = "syslog";
/*
** OPENLOG -- open system log
** - establishes a channel to syslogd using UDP device
** (port 514 is used _ syslog/udp)
** - stores program tag (if not NULL) and other options
** for use by syslog
*/
void openlog(const char *ident, int option, int facility)
{
struct nwio_udpopt udpopt;
/* Stores logging flags */
LogFlags = option & (LOG_PID | LOG_PERROR | LOG_CONS);
/* Stores process id. if LOG_PID was specified */
if (option & LOG_PID) LogPid = getpid();
/* Stores the requested facility */
LogFacility = facility;
/* Stores log tag if supplied */
if (ident != NULL && *ident != '0' && ident != TagBuffer) {
strncpy(TagBuffer, ident, sizeof(TagBuffer));
TagBuffer[sizeof(TagBuffer) - 1] = '0';
}
/* Opens channel to syslog daemon via UDP device */
/* Static values used to minimize code */
if (option & LOG_NDELAY) {
/* Opens UDP device */
if ((nfd = open(UDP_DEVICE, O_RDWR)) < 0) {
/* Report error */ ;
}
/* Sets options for UDP device */
udpopt.nwuo_flags = NWUO_SHARED | NWUO_LP_SET | NWUO_DI_LOC |
NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET |
NWUO_RWDATONLY | NWUO_DI_IPOPT;
udpopt.nwuo_locaddr = udpopt.nwuo_remaddr = htonl(0x7F000001L);
udpopt.nwuo_locport = udpopt.nwuo_remport = htons(514);
if (ioctl(nfd, NWIOSUDPOPT, &udpopt) < 0 ||
ioctl(nfd, NWIOGUDPOPT, &udpopt) < 0) {
/* Report error */ ;
}
}
return;
}
/*
** SYSLOG -- print message on log file
**
** This routine looks a lot like printf, except that it outputs to the
** log file instead of the standard output. Also:
** - adds a timestamp,
** - prints the module name in front of the message,
** - has some other formatting types (or will sometime),
** - adds a newline on the end of the message.
**
** The output of this routine is intended to be read by syslogd(8).
*/
void syslog(int lprty, const char *msg,...)
{
time_t now;
char buff[512];
int len, rc;
va_list ap;
/* First log message open chnnel to syslog */
if (nfd < 0) openlog(TagBuffer, LogFlags | LOG_NDELAY, LogFacility);
time(&now);
len = sprintf(buff, "<%d>%.15s %s: ",
LogFacility | lprty, ctime(&now) + 4, TagBuffer);
if (LogFlags & LOG_PID) {
len -= 2;
len += sprintf(buff + len, "[%d]: ", LogPid);
}
va_start(ap, msg);
len += vsprintf(buff + len, msg, ap);
va_end(ap);
rc = write(nfd, buff, len);
if ((rc != len && LogFlags & LOG_CONS) || LogFlags & LOG_PERROR) {
write(STDERR_FILENO, buff, len);
write(STDERR_FILENO, "\n", 1);
}
return;
}
/*
** CLOSELOG -- close access to syslogd
** - closes UDP channel
** - restores default values
*/
void closelog(void)
{
close(nfd);
LogPid = nfd = -1;
LogFacility = LOG_USER;
LogFlags = 0;
return;
}
/** syslog.c **/

View file

@ -0,0 +1,30 @@
/*
** syslog_test
**
** Author: Giovanni Falzoni <gfalzoni@inwind.it>
** $Id$
*/
#include <sys/types.h>
#include <unistd.h>
#include <syslog.h>
/*
** SYSLOG TEST
** Very simple utility to test syslog facility.
*/
void main(void)
{
int ix;
openlog("syslog_test", LOG_PID | LOG_NDELAY | LOG_PERROR | LOG_CONS, LOG_DAEMON);
for (ix = LOG_EMERG; ix <= LOG_DEBUG; ix += 1) {
sleep(2);
syslog(ix, "message from test program - log level %d", ix);
}
closelog();
return;
}
/** syslog_test.c **/

924
commands/syslogd/syslogd.c Normal file
View file

@ -0,0 +1,924 @@
/*
** Copyright (c) 1983, 1988
** The Regents of the University of California. All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. All advertising materials mentioning features or use of this software
** must display the following acknowledgement:
** This product includes software developed by the University of
** California, Berkeley and its contributors.
** 4. Neither the name of the University nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
** ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
** SUCH DAMAGE.
**
** #ifndef lint
** char copyright2[] =
** "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
** All rights reserved.\n";
** #endif
**
** #ifndef lint
** static char sccsid[] = "@(#)syslogd.c 5.27 (Berkeley) 10/10/88";
** #endif
**
** -----------------------------------------------------------------------
**
** SYSLOGD -- log system messages
** This program implements a system log.
** It takes a series of lines and outputs them according to the setup
** defined in the configuration file.
** Each line may have a priority, signified as "<n>" as
** the first characters of the line. If this is
** not present, a default priority is used.
**
** To kill syslogd, send a signal 15 (terminate).
** A signal 1 (hup) will cause it to reread its configuration file.
**
** Defined Constants:
** MAXLINE -- the maximimum line length that can be handled.
** MAXSVLINE -- the length of saved messages (for filtering)
** DEFUPRI -- the default priority for user messages
** DEFSPRI -- the default priority for kernel messages
**
** Author: Eric Allman
** extensive changes by Ralph Campbell
** more extensive changes by Eric Allman (again)
** changes by Steve Lord
**
** Extensive rewriting by G. Falzoni <gfalzoni@inwind.it> for porting to Minix
**
** $Log$
** Revision 1.1 2006/04/03 13:07:42 beng
** Kick out usyslogd in favour of syslogd Giovanni's syslogd port
**
** Revision 1.3 2005/09/16 10:10:12 lsodgf0
** Rework for Minix 3. Adds kernel logs from /dev/klogd
**
** $Id$
*/
#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/select.h>
#include <sys/wait.h>
#include <net/netlib.h>
#include <net/hton.h>
#include <net/gen/in.h>
#include <net/gen/udp.h>
#include <net/gen/udp_io.h>
#include <net/gen/netdb.h>
#define SYSLOG_NAMES
#include <syslog.h>
#define KLOGD 1
/** Define following values to your requirements **/
#define MAXLINE 512 /* maximum line length */
#define MAXSVLINE 256 /* maximum saved line length */
#define DEFUPRI (LOG_USER|LOG_NOTICE)
#define DEFSPRI (LOG_KERN|LOG_CRIT)
/* Flags to logmsg() */
#define IGN_CONS 0x001 /* don't print on console */
#define SYNC_FILE 0x002 /* do fsync on file after printing */
#define ADDDATE 0x004 /* add a date to the message */
#define MARK 0x008 /* this message is a mark */
#define CTTY "/dev/log" /* Minix log device (console) */
#define dprintf if(DbgOpt!=0)printf
#if debug == 0
#define DEBUG(statement)
#else
#define DEBUG(statement) statement
#endif
#if !defined PIDFILE
#define PIDFILE "/var/run/syslogd.pid"
#endif
#define UNAMESZ 8 /* length of a login name */
#define MAXUNAMES 20 /* maximum number of user names */
#define MAXFNAME 200 /* max file pathname length */
#define MAXHOSTNAMELEN 64 /* max length of FQDN host name */
/* Intervals at which we flush out "message repeated" messages,
* in seconds after previous message is logged. After each flush,
* we move to the next interval until we reach the largest. */
#define TIMERINTVL 30 /* interval for checking flush, mark */
#define INTERVAL1 30
#define INTERVAL2 60
#define MAXREPEAT ((sizeof(repeatinterval)/sizeof(repeatinterval[0]))-1)
#define REPEATTIME(f) ((f)->f_time+repeatinterval[(f)->f_repeatcount])
#define BACKOFF(f) {if(++(f)->f_repeatcount>MAXREPEAT)(f)->f_repeatcount=MAXREPEAT;}
/* Values for f_type */
#define F_UNUSED 0 /* unused entry */
#define F_FILE 1 /* regular file */
#define F_TTY 2 /* terminal */
#define F_CONSOLE 3 /* console terminal */
#define F_FORW 4 /* remote machine */
#define F_USERS 5 /* list of users */
#define F_WALL 6 /* everyone logged on */
#define max(a,b) ((a)>=(b)?(a):(b))
/* This structure represents the files that will have log copies printed */
struct filed {
struct filed *f_next; /* next in linked list */
short f_type; /* entry type, see below */
short f_file; /* file descriptor */
time_t f_time; /* time this was last written */
char f_pmask[LOG_NFACILITIES + 1]; /* priority mask */
union {
char f_uname[MAXUNAMES][UNAMESZ + 1];
char f_fname[MAXFNAME];
} f_un;
char f_prevline[MAXSVLINE]; /* last message logged */
char f_lasttime[16]; /* time of last occurrence */
char f_prevhost[MAXHOSTNAMELEN + 1]; /* host from which recd. */
int f_prevpri; /* pri of f_prevline */
int f_prevlen; /* length of f_prevline */
int f_prevcount; /* repetition cnt of prevline */
int f_repeatcount; /* number of "repeated" msgs */
int f_flags; /* store some additional flags */
};
static const char *const TypeNames[] =
{
"UNUSED", "FILE", "TTY", "CONSOLE", "FORW", "USERS", "WALL", NULL,
};
static struct filed *Files = NULL;
static struct filed consfile;
static int DbgOpt = 0; /* debug flag */
static char LocalHostName[MAXHOSTNAMELEN + 1]; /* our hostname */
static int Initialized = 0; /* set when we have initialized ourselves */
static int MarkInterval = 20 * 60; /* interval between marks in seconds */
static int MarkSeq = 0; /* mark sequence number */
static time_t now;
static const char *ConfFile = "/etc/syslog.conf";
static const char *PidFile = PIDFILE; /* "/var/run/syslogd.pid" */
static const char ctty[] = CTTY;
static const char ProgName[] = "syslogd:";
static const char version[] = "1.3 (Minix)";
static const char usage[] =
/* */ "usage:\tsyslogd [-d] [-m markinterval] [-f conf-file]\n"
"\t\t[-p listeningport] [-v] [-?]\n" ;
static const int repeatinterval[] =
/* */ {INTERVAL1, INTERVAL2,}; /* # of secs before flush */
/*
** Name: void wallmsg(struct filed *fLog, char *message);
** Function: Write the specified message to either the entire
** world, or a list of approved users.
*/
void wallmsg(struct filed * fLog, char *message)
{
return;
}
/*
** Name: void fprintlog(struct filed *fLog, int flags, char *message);
** Function:
*/
void fprintlog(struct filed * fLog, int flags, char *message)
{
int len;
char line[MAXLINE + 1];
char repbuf[80];
if (message == NULL) {
if (fLog->f_prevcount > 1) {
sprintf(repbuf, "last message repeated %d times", fLog->f_prevcount);
message = repbuf;
} else
message = fLog->f_prevline;
}
sprintf(line, "%s %s %s", fLog->f_lasttime, fLog->f_prevhost, message);
DEBUG(dprintf("Logging to %s", TypeNames[fLog->f_type]);)
fLog->f_time = now;
switch (fLog->f_type) {
case F_UNUSED: /* */
DEBUG(dprintf("\n");)
break;
case F_CONSOLE:
if (flags & IGN_CONS) {
case F_FORW: /* */
DEBUG(dprintf(" (ignored)\n");)
break;
} /* else Fall Through */
case F_TTY:
case F_FILE:
DEBUG(dprintf(" %s\n", fLog->f_un.f_fname);)
strcat(line, fLog->f_type != F_FILE ? "\r\n" : "\n");
len = strlen(line);
if (write(fLog->f_file, line, len) != len) {
/* Handle errors */ ;
} else if (flags & SYNC_FILE)
sync();
break;
case F_USERS:
case F_WALL:
DEBUG(dprintf("\n");)
strcat(line, "\r\n");
wallmsg(fLog, line);
break;
}
fLog->f_prevcount = 0;
return;
}
/*
** Name: void logmsg(int pri, char *msg, char *from, int flags);
** Function: Log a message to the appropriate log files, users, etc.
** based on the priority.
*/
void logmsg(int pri, char *msg, char *from, int flags)
{
struct filed *f;
int fac, prilev;
int omask, msglen;
char *timestamp;
DEBUG(dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", pri, flags, from, msg);)
/*
omask = sigblock(__sigmask(SIGHUP) | __sigmask(SIGALRM));
*/
/* Check to see if msg looks non-standard. */
msglen = strlen(msg);
if (msglen < 16 || msg[3] != ' ' || msg[6] != ' ' ||
msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
flags |= ADDDATE;
time(&now);
if (flags & ADDDATE)
timestamp = ctime(&now) + 4;
else {
timestamp = msg;
msg += 16;
msglen -= 16;
}
/* Extract facility and priority level */
fac = (flags & MARK) ? LOG_NFACILITIES : LOG_FAC(pri);
prilev = LOG_PRI(pri);
/* Log the message to the particular outputs */
if (!Initialized) {
/* Not yet initialized. Every message goes to console */
f = &consfile;
f->f_file = open(ctty, O_WRONLY | O_NOCTTY);
if (f->f_file >= 0) {
if (!DbgOpt) setsid();
fprintlog(f, flags, msg);
close(f->f_file);
}
} else {
for (f = Files; f; f = f->f_next) {
/* Skip messages that are incorrect priority */
if (f->f_pmask[fac] < prilev || f->f_pmask[fac] == INTERNAL_NOPRI)
continue;
if (f->f_type == F_CONSOLE && (flags & IGN_CONS)) continue;
/* Don't output marks to recently written files */
if ((flags & MARK) && (now - f->f_time) < MarkInterval / 2)
continue;
/* Suppress duplicate lines to this file */
if ((flags & MARK) == 0 && msglen == f->f_prevlen &&
!strcmp(msg, f->f_prevline) &&
!strcmp(from, f->f_prevhost)) {
strncpy(f->f_lasttime, timestamp, 15);
f->f_prevcount += 1;
DEBUG(dprintf("msg repeated %d times, %ld sec of %d\n",
f->f_prevcount, now - f->f_time,
repeatinterval[f->f_repeatcount]);)
/* If domark would have logged this by now,
* flush it now (so we don't hold isolated
* messages), but back off so we'll flush
* less often in the future. */
if (now > REPEATTIME(f)) {
fprintlog(f, flags, (char *) NULL);
BACKOFF(f);
}
} else {
/* New line, save it */
if (f->f_prevcount) fprintlog(f, 0, (char *) NULL);
f->f_repeatcount = 0;
strncpy(f->f_lasttime, timestamp, 15);
strncpy(f->f_prevhost, from, sizeof(f->f_prevhost));
if (msglen < MAXSVLINE) {
f->f_prevlen = msglen;
f->f_prevpri = pri;
strcpy(f->f_prevline, msg);
fprintlog(f, flags, (char *) NULL);
} else {
f->f_prevline[0] = 0;
f->f_prevlen = 0;
fprintlog(f, flags, msg);
}
}
}
}
/*
sigsetmask(omask);
*/
return;
}
/*
** Name: void logerror(char *type);
** Function: Prints syslogd errors in some place.
*/
void logerror(char *type)
{
char buf[100];
if (errno == 0) sprintf(buf, "%s %s", ProgName, type);
else if (errno >= _NERROR)
sprintf(buf, "%s %s - error %d", ProgName, type, errno);
else
sprintf(buf, "%s %s - %s", ProgName, type, strerror(errno));
errno = 0;
dprintf("%s\n", buf);
logmsg(LOG_SYSLOG | LOG_ERR, buf, LocalHostName, ADDDATE);
return;
}
/*
** Name: void die(int sig);
** Function: Signal handler for kill signals.
*/
void die(int sig)
{
struct filed *f;
char buf[100];
for (f = Files; f != NULL; f = f->f_next) {
/* Flush any pending output */
if (f->f_prevcount) fprintlog(f, 0, NULL);
}
if (sig >= 0) {
DEBUG(dprintf("%s exiting on signal %d\n", ProgName, sig);)
sprintf(buf, "exiting on signal %d", sig);
errno = 0;
logerror(buf);
}
unlink(PidFile);
exit(sig == (-1) ? EXIT_FAILURE : EXIT_SUCCESS);
}
/*
** Name: void domark(int sig);
** Function: Signal handler for alarm.
** Used for messages filtering and mark facility.
*/
void domark(int sig)
{
struct filed *f;
now = time(NULL);
MarkSeq += TIMERINTVL;
if (MarkSeq >= MarkInterval) {
logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE | MARK);
MarkSeq = 0;
}
for (f = Files; f; f = f->f_next) {
if (f->f_prevcount && now >= REPEATTIME(f)) {
DEBUG(dprintf("flush %s: repeated %d times, %d sec.\n",
TypeNames[f->f_type], f->f_prevcount,
repeatinterval[f->f_repeatcount]);)
fprintlog(f, 0, NULL);
BACKOFF(f);
}
}
signal(SIGALRM, domark);
alarm(TIMERINTVL);
return;
}
/*
** Name: int decode(char *name, struct _code *codetab);
** Function: Decode a symbolic name to a numeric value
*/
int decode(char *name, const struct _code *codetab)
{
const struct _code *c;
char *p;
char buf[40];
DEBUG(dprintf("symbolic name: %s", name);)
if (isdigit(*name)) return (atoi(name));
strcpy(buf, name);
for (p = buf; *p; p += 1) {
if (isupper(*p)) *p = tolower(*p);
}
for (c = codetab; c->c_name; c += 1) {
if (!strcmp(buf, c->c_name)) {
DEBUG(dprintf(" ==> %d\n", c->c_val);)
return (c->c_val);
}
}
return (-1);
}
/*
** Name: void cfline(char *line, struct filed *f);
** Function: Parse a configuration file line
*/
void cfline(char *line, struct filed * fLog)
{
char *p, *q, *bp;
int ix, pri;
char buf[MAXLINE];
char xbuf[200];
DEBUG(dprintf("cfline(%s)\n", line);)
/* Keep sys_errlist stuff out of logerror messages */
errno = 0;
/* Clear out file entry */
memset(fLog, 0, sizeof(*fLog));
for (ix = 0; ix <= LOG_NFACILITIES; ix += 1) /* */
fLog->f_pmask[ix] = INTERNAL_NOPRI;
/* Scan through the list of selectors */
for (p = line; *p && *p != '\t';) {
/* Find the end of this facility name list */
for (q = p; *q && *q != '\t' && *q++ != '.';) continue;
/* Collect priority name */
for (bp = buf; *q && !strchr("\t,;", *q);) *bp++ = *q++;
*bp = '\0';
/* Skip cruft */
while (strchr(", ;", *q)) q++;
/* Decode priority name */
pri = decode(buf, PriNames);
if (pri < 0) {
sprintf(xbuf, "unknown priority name \"%s\"", buf);
logerror(xbuf);
return;
}
/* Scan facilities */
while (*p && !strchr("\t.;", *p)) {
for (bp = buf; *p && !strchr("\t,;.", *p);) *bp++ = *p++;
*bp = '\0';
if (*buf == '*') {
for (ix = 0; ix <= LOG_NFACILITIES; ix += 1)
if ((fLog->f_pmask[ix] < pri) ||
(fLog->f_pmask[ix] == INTERNAL_NOPRI)) {
fLog->f_pmask[ix] = pri;
}
} else {
ix = decode(buf, FacNames);
if (ix < 0) {
sprintf(xbuf, "unknown facility name \"%s\"", buf);
logerror(xbuf);
return;
}
if ((fLog->f_pmask[ix >> 3] < pri) ||
(fLog->f_pmask[ix >> 3] == INTERNAL_NOPRI)) {
fLog->f_pmask[ix >> 3] = pri;
}
}
while (*p == ',' || *p == ' ') p++;
}
p = q;
}
/* Skip to action part */
while (*p == '\t' || *p == ' ') p++;
DEBUG(dprintf("leading char in action: %c\n", *p);)
switch (*p) {
case '@': /* Logging to a remote host */
break; /* NOT IMPLEMENTED */
case '/': /* Logging to a local file/device */
strcpy(fLog->f_un.f_fname, p);
DEBUG(dprintf("filename: %s\n", p); /* ASP */)
if ((fLog->f_file = open(p, O_WRONLY | O_APPEND | O_CREAT | O_NOCTTY, 0644)) < 0) {
fLog->f_file = F_UNUSED;
sprintf(xbuf, "unknown file/device (%s)", p);
logerror(xbuf);
break;
}
if (isatty(fLog->f_file)) {
if (!DbgOpt) setsid();
fLog->f_type = F_TTY;
} else
fLog->f_type = F_FILE;
if (strcmp(p, ctty) == 0) fLog->f_type = F_CONSOLE;
break;
case '*': /* Logging to all users */
DEBUG(dprintf("write-all\n");)
fLog->f_type = F_WALL;
break;
default: /* Logging to selected users */
DEBUG(dprintf("users: %s\n", p); /* ASP */)
for (ix = 0; ix < MAXUNAMES && *p; ix += 1) {
for (q = p; *q && *q != ',';) q += 1;
strncpy(fLog->f_un.f_uname[ix], p, UNAMESZ);
if ((q - p) > UNAMESZ)
fLog->f_un.f_uname[ix][UNAMESZ] = '\0';
else
fLog->f_un.f_uname[ix][q - p] = '\0';
while (*q == ',' || *q == ' ') q++;
p = q;
}
fLog->f_type = F_USERS;
break;
}
}
/*
** Name: void printline(char *hname, char *msg);
** Function: Takes a raw input line, decodes the message and
** prints the message on the appropriate log files.
*/
void printline(char *hname, char *msg)
{
char line[MAXLINE + 1];
char *p = msg, *q = line;
int ch, pri = DEFUPRI;
/* Test for special codes */
if (*p == '<') {
pri = 0;
while (isdigit(*++p)) {
if ((*p - '0') < 8) {
/* Only 3 bits allocated for pri -- ASP */
pri = 10 * pri + (*p - '0');
} else
pri = 10 * pri + 7;
}
if (*p == '>') ++p;
}
if (pri & ~(LOG_FACMASK | LOG_PRIMASK)) pri = DEFUPRI;
/* Does not allow users to log kernel messages */
if (LOG_FAC(pri) == LOG_KERN) pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri));
/* Copies message to local buffer, translating control characters */
while ((ch = *p++ & 0177) != '\0' && q < &line[sizeof(line) - 1]) {
if (ch == '\n') /* Removes newlines */
*q++ = ' ';
else if (iscntrl(ch)) { /* Translates control characters */
*q++ = '^';
*q++ = ch ^ 0100;
} else
*q++ = ch;
}
*q = '\0';
logmsg(pri, line, hname, 0);
return;
}
/*
** Name: void printkline(char *hname, char *msg);
** Function: Takes a raw input line from kernel and
** prints the message on the appropriate log files.
*/
void printkline(char *hname, char *msg)
{
char line[MAXLINE + 1];
char *p = msg, *q = line;
int ch, pri = DEFUPRI;
/* Copies message to local buffer, adding source program tag */
sprintf(line, "kernel: %s", msg);
logmsg(LOG_KERN | LOG_INFO, line, hname, ADDDATE);
return;
}
/*
** Name: void init(int sig);
** Function: Initialize syslogd from configuration file.
** Used at startup or after a SIGHUP signal.
*/
void init(int sig)
{
int i;
FILE *cf;
struct filed *fLog, *next, **nextp;
char *p;
char cline[BUFSIZ];
DEBUG(dprintf("init\n");)
/* Close all open log files. */
Initialized = 0;
for (fLog = Files; fLog != NULL; fLog = next) {
/* Flush any pending output */
if (fLog->f_prevcount) fprintlog(fLog, 0, NULL);
switch (fLog->f_type) {
case F_FILE:
case F_TTY:
case F_CONSOLE: close(fLog->f_file); break;
}
next = fLog->f_next;
free((char *) fLog);
}
Files = NULL;
nextp = &Files;
/* Open the configuration file */
if ((cf = fopen(ConfFile, "r")) != NULL) {
/* Foreach line in the configuration table, open that file. */
fLog = NULL;
while (fgets(cline, sizeof(cline), cf) != NULL) {
/* Check for end-of-section, comments, strip off
* trailing spaces and newline character. */
for (p = cline; isspace(*p); p += 1);
if (*p == '\0' || *p == '#') continue;
for (p = strchr(cline, '\0'); isspace(*--p););
*++p = '\0';
fLog = (struct filed *) calloc(1, sizeof(*fLog));
*nextp = fLog;
nextp = &fLog->f_next;
cfline(cline, fLog);
}
/* Close the configuration file */
fclose(cf);
Initialized = 1;
DEBUG (
if (DbgOpt) {
for (fLog = Files; fLog; fLog = fLog->f_next) {
for (i = 0; i <= LOG_NFACILITIES; i += 1)
if (fLog->f_pmask[i] == INTERNAL_NOPRI)
printf("X ");
else
printf("%d ", fLog->f_pmask[i]);
printf("%s: ", TypeNames[fLog->f_type]);
switch (fLog->f_type) {
case F_FILE:
case F_TTY:
case F_CONSOLE:
printf("%s", fLog->f_un.f_fname);
break;
case F_FORW:
break;
case F_USERS:
for (i = 0; i < MAXUNAMES && *fLog->f_un.f_uname[i]; i += 1)
printf("%s, ", fLog->f_un.f_uname[i]);
break;
}
printf("\n");
}
}
)
logmsg(LOG_SYSLOG | LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
signal(SIGHUP, init);
DEBUG(dprintf("%s restarted\n", ProgName);)
} else {
DEBUG(dprintf("cannot open %s\n", ConfFile);)
*nextp = (struct filed *) calloc(1, sizeof(*fLog));
cfline("*.ERR\t" CTTY, *nextp);
(*nextp)->f_next = (struct filed *) calloc(1, sizeof(*fLog));
cfline("*.PANIC\t*", (*nextp)->f_next);
Initialized = 1;
}
return;
}
/*
** Name: void daemonize(char *line);
** Function: Clone itself and becomes a daemon releasing unnecessay resources.
*/
void daemonize(char *line)
{
int lfd, len, pid;
if ((lfd = open(PidFile, O_CREAT | O_RDWR, 0600)) > 0) {
len = read(lfd, line, 10);
line[len] = '\0';
close(lfd);
if ((kill(len = atoi(line), 0) < 0 && errno == ESRCH) || len == 0) {
if (!DbgOpt) {
/* Parent ends and child becomes a daemon */
if ((pid = fork()) > 0) {
/* Write process id. in pid file */
lfd = open(PidFile, O_TRUNC | O_WRONLY);
len = sprintf(line, "%5d", pid);
write(lfd, line, len);
close(lfd);
/* Wait for initialization to complete */
exit(EXIT_SUCCESS);
}
sleep(1);
setsid(); /* Set as session leader */
chdir("/"); /* Change to the root directory */
/* Get rid of all open files */
for (lfd = STDERR_FILENO + 1; lfd < OPEN_MAX; lfd += 1)
close(lfd);
}
} else {
fprintf(stderr, "\n%s already running\n", ProgName);
exit(EXIT_FAILURE);
}
} else {
fprintf(stderr, "\n%s can't open %s (%s)\n", ProgName, PidFile, strerror(errno));
exit(EXIT_FAILURE);
}
return;
}
/*
** Name: int main(int argc, char **argv);
** Function: Syslog daemon entry point
*/
int main(int argc, char **argv)
{
char *p, *udpdev, *eol;
int nfd, kfd, len, fdmax;
int ch, port = 0;
fd_set fdset;
struct nwio_udpopt udpopt;
struct servent *sp;
char line[MAXLINE + 1];
while ((ch = getopt(argc, argv, "df:m:p:v?")) != EOF) {
switch ((char) ch) {
case 'd': /* Debug */
DbgOpt += 1;
break;
case 'f': /* Set configuration file */
ConfFile = optarg;
break;
case 'm': /* Set mark interval */
MarkInterval = atoi(optarg) * 60;
break;
case 'p': /* Set listening port */
port = atoi(optarg);
break;
case 'v': /* Print version */
fprintf(stderr, "%s version %s\n", ProgName, version);
return EXIT_FAILURE;
case '?': /* Help */
default:
fprintf(stderr, usage);
return EXIT_FAILURE;
}
}
if (argc -= optind) {
fprintf(stderr, usage);
return EXIT_FAILURE;
}
daemonize(line);
/* Get the official name of local host. */
gethostname(LocalHostName, sizeof(LocalHostName) - 1);
if ((p = strchr(LocalHostName, '.'))) *p = '\0';
udpdev = (p = getenv("UDP_DEVICE")) ? p : UDP_DEVICE;
sp = getservbyname("syslog", "udp");
signal(SIGTERM, die);
signal(SIGINT, DbgOpt ? die : SIG_IGN);
signal(SIGQUIT, DbgOpt ? die : SIG_IGN);
signal(SIGALRM, domark);
alarm(TIMERINTVL);
/* Open UDP device */
if ((nfd = open(udpdev, O_NONBLOCK | O_RDONLY)) < 0) {
logerror("UDP device not open");
return EXIT_FAILURE;
}
/* Configures the UDP device */
udpopt.nwuo_flags = NWUO_SHARED | NWUO_LP_SET | NWUO_EN_LOC |
NWUO_DI_BROAD | NWUO_RP_SET | NWUO_RA_SET |
NWUO_RWDATONLY | NWUO_DI_IPOPT;
udpopt.nwuo_locport = udpopt.nwuo_remport =
port == 0 ? sp->s_port : htons(port);
udpopt.nwuo_remaddr = udpopt.nwuo_locaddr = htonl(0x7F000001L);
while (ioctl(nfd, NWIOSUDPOPT, &udpopt) < 0 ||
ioctl(nfd, NWIOGUDPOPT, &udpopt) < 0) {
if (errno == EAGAIN) {
sleep(1);
continue;
}
logerror("Set/Get UDP options failed");
return EXIT_FAILURE;
}
/* Open kernel log device */
if ((kfd = open("/dev/klog", O_NONBLOCK | O_RDONLY)) < 0) {
logerror("Open /dev/klog failed");
return EXIT_FAILURE;
}
fdmax = max(nfd, kfd) + 1;
DEBUG(dprintf("off & running....\n");)
init(-1); /* Initilizes log data structures */
for (;;) { /* Main loop */
FD_ZERO(&fdset); /* Setup descriptors for select */
FD_SET(nfd, &fdset);
FD_SET(kfd, &fdset);
if (select(fdmax, &fdset, NULL, NULL, NULL) <= 0) {
sleep(1);
continue;
}
if (FD_ISSET(nfd, &fdset)) {
/* Read a message from application programs */
len = read(nfd, line, MAXLINE);
if (len > 0) { /* Got a message */
line[len] = '\0';
dprintf("got a message (%d, %#x)\n", nfd, len);
printline(LocalHostName, line);
} else if (len < 0) { /* Got an error or signal while reading */
if (errno != EINTR) /* */
logerror("Receive error from UDP channel");
} else { /* (len == 0) Channel has been closed */
logerror("UDP channel has closed");
close(nfd);
die(-1);
}
}
if (FD_ISSET(kfd, &fdset)) {
static char linebuf[5*1024];
/* Read a message from kernel (klog) */
len = read(kfd, linebuf, sizeof(linebuf)-2);
dprintf("got a message (%d, %#x)\n", kfd, len);
for (ch = 0; ch < len; ch += 1)
if (linebuf[ch] == '\0') linebuf[ch] = ' ';
if (linebuf[len - 1] == '\n') len -= 1;
linebuf[len] = '\n';
linebuf[len + 1] = '\0';
p = linebuf;
while(eol = strchr(p, '\n')) {
*eol = '\0';
printkline(LocalHostName, p);
p = eol+1;
}
}
}
/* Control never gets here */
}
/** syslogd.c **/