diff options
Diffstat (limited to 'syslogd/syslogd.c')
-rw-r--r-- | syslogd/syslogd.c | 1406 |
1 files changed, 0 insertions, 1406 deletions
diff --git a/syslogd/syslogd.c b/syslogd/syslogd.c deleted file mode 100644 index 733e3a693..000000000 --- a/syslogd/syslogd.c +++ /dev/null @@ -1,1406 +0,0 @@ -/* - * Copyright (c) 1983, 1988 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. - * - * Wed Sep 14 21:56:59 1994: Applied patches from Alan Modra - * (alan@spri.levels.unisa.edu.au): - * 1) Add O_CREAT to open flags so that syslogd doesn't complain about - * non-existent files - * 2) Modified f_pmask initialisation and testing to allow logging of - * messages at a particular priority level, rather that all messages - * at or above a given priority level. - * - * Sat Jun 3 12:48:16 1995: Applied patches from - * Jochen.Hein@informatik.tu-clausthal.de to allow spaces *AND* tabs to - * separate the selector from the action. This means that no whitespace is - * allowed inside the selector. - * */ - -#ifndef lint -char copyright[] = -"@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ - All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)syslogd.c 5.45 (Berkeley) 3/2/91"; -#endif /* not lint */ - -/* - * syslogd -- log system messages - * - * This program implements a system log. It takes a series of lines. - * 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. - * 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) - * - * Modified, Sun Mar 7 15:21:13 1993, faith@cs.unc.edu for Linux: - * - * SUN_LEN_MISSING: struct sockaddr does not have sun_len - * SYSLOG_STREAM: syslog is implemented using stream sockets - * SYSLOG_INET: support inet logging - * KLOG_STREAM: kernel logging uses a stream device - * STATUS_BROKEN: use "int status" instead of "union wait status" - * RE_INSTALL_SIGNAL: signal() does *not* remain installed - * SYS_MSGBUF_H_MISSING: sys/msgbuf.h is missing - * FSYNC_MISSING: fsync() is missing - * KERNEL_NAME: what the kernel is usually called - * - * Original Linux version by Rik Faith <faith@cs.unc.edu> - * with changes by Rick Sladkey <jrs@world.std.com> and - * Rick <pclink@qus102.qld.npb.telecom.com.au>. Anyone else - * named Rick who wants to chip in? :-) - * More corrections by Neal Becker <neal@ctd.comsat.com> Sun Jan 16, 1994 - * Patches from Jochen Hein (Jochen.Hein@informatik.tu-clausthal.de) to treat - * spaces and tabs the same, applied Sat Mar 11 10:09:24 1995 - */ - -#ifdef __linux__ -#define SUN_LEN_MISSING -#define SYSLOG_STREAM -#define SYSLOG_INET -#define KLOG_STREAM -#undef STATUS_BROKEN -#define RE_INSTALL_SIGNAL -#define SYS_MSGBUF_H_MISSING -#undef FSYNC_MISSING -#define KERNEL_NAME "linux" -#endif - -#define MAXLINE 1024 /* maximum line length */ -#define MAXSVLINE 120 /* maximum saved line length */ -#define DEFUPRI (LOG_USER|LOG_NOTICE) -#define DEFSPRI (LOG_KERN|LOG_CRIT) -#define TIMERINTVL 30 /* interval for checking flush, mark */ - -#include <sys/param.h> -#include <sys/errno.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <sys/socket.h> -#include <sys/file.h> -#ifdef SYS_MSGBUF_H_MISSING -#define MSG_BSIZE (MAXLINE*2) -#else -#include <sys/msgbuf.h> -#endif -#include <sys/uio.h> -#include <sys/un.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/signal.h> - -#include <netinet/in.h> -#include <netdb.h> - -#include <utmp.h> -#include <setjmp.h> -#include <stdio.h> -#include <ctype.h> -#include <string.h> -#include <unistd.h> -#include <paths.h> - -#define SYSLOG_NAMES -#include <sys/syslog.h> - -char *LogName = _PATH_LOG; -char *ConfFile = _PATH_LOGCONF; - -#ifdef __linux__ -#define CONFORM_TO_FSSTND -#include "pathnames.h" -#endif - -#ifdef CONFORM_TO_FSSTND -char *PidFile = "/var/run/syslog.pid"; -#else -char *PidFile = _PATH_LOGPID; -#endif - -char ctty[] = _PATH_CONSOLE; - -#define FDMASK(fd) (1 << (fd)) - -#define dprintf if (Debug) printf - -#define MAXUNAMES 20 /* maximum number of user names */ - -/* - * 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 */ - -/* - * 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 */ - u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */ - union { - char f_uname[MAXUNAMES][UT_NAMESIZE+1]; - struct { - char f_hname[MAXHOSTNAMELEN+1]; - struct sockaddr_in f_addr; - } f_forw; /* forwarding address */ - char f_fname[MAXPATHLEN]; - } 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 */ -}; - -/* - * 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. - */ -int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */ -#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 */ - -char *TypeNames[7] = { - "UNUSED", "FILE", "TTY", "CONSOLE", - "FORW", "USERS", "WALL" -}; - -struct filed *Files; -struct filed consfile; - -int Debug; /* debug flag */ -char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */ -char *LocalDomain; /* our local domain name */ -int InetInuse = 0; /* non-zero if INET sockets are being used */ -#ifdef SYSLOG_INET -int finet; /* Internet datagram socket */ -#endif /* SYSLOG_INET */ -int LogPort; /* port number for INET connections */ -int Initialized = 0; /* set when we have initialized ourselves */ -int MarkInterval = 20 * 60; /* interval between marks in seconds */ -int MarkSeq = 0; /* mark sequence number */ - -extern int errno; -extern char *ctime(), *index(), *calloc(); - -main(argc, argv) - int argc; - char **argv; -{ - register int i; - register char *p; - int funix, fklog, len; - struct sockaddr_un sunx, fromunix; - struct sockaddr_in sin, frominet; - FILE *fp; - int ch; - char line[MSG_BSIZE + 1]; - extern int optind; - extern char *optarg; - void die(), domark(), init(), reapchild(); -#ifdef SYSLOG_STREAM - fd_set unixm; - int fd; -#endif /* SYSLOG_STREAM */ - - while ((ch = getopt(argc, argv, "df:m:p:")) != EOF) - switch((char)ch) { - case 'd': /* debug */ - Debug++; - break; - case 'f': /* configuration file */ - ConfFile = optarg; - break; - case 'm': /* mark interval */ - MarkInterval = atoi(optarg) * 60; - break; - case 'p': /* path */ - LogName = optarg; - break; - case '?': - default: - usage(); - } - if (argc -= optind) - usage(); - - if (!Debug) - daemon(0, 0); - else - setlinebuf(stdout); - - consfile.f_type = F_CONSOLE; - (void) strcpy(consfile.f_un.f_fname, ctty); - (void) gethostname(LocalHostName, sizeof LocalHostName); - if (p = index(LocalHostName, '.')) { - *p++ = '\0'; - LocalDomain = p; - } - else - LocalDomain = ""; - (void) signal(SIGTERM, die); - (void) signal(SIGINT, Debug ? die : SIG_IGN); - (void) signal(SIGQUIT, Debug ? die : SIG_IGN); - (void) signal(SIGCHLD, reapchild); - (void) signal(SIGALRM, domark); - (void) alarm(TIMERINTVL); - (void) unlink(LogName); - - bzero((char *)&sunx, sizeof(sunx)); - sunx.sun_family = AF_UNIX; - (void) strncpy(sunx.sun_path, LogName, sizeof sunx.sun_path); -#ifdef SYSLOG_STREAM - funix = socket(AF_UNIX, SOCK_STREAM, 0); - if (funix < 0 || bind(funix, (struct sockaddr *) &sunx, - sizeof(sunx)) < 0 || listen(funix, 5) < 0 || -#else /* !SYSLOG_STREAM */ - funix = socket(AF_UNIX, SOCK_DGRAM, 0); - if (funix < 0 || bind(funix, (struct sockaddr *) &sunx, - sizeof(sunx.sun_family)+sizeof(sunx.sun_len)+ - strlen(sunx.sun_path)) < 0 || -#endif /* !SYSLOG_STREAM */ - chmod(LogName, 0666) < 0) { - (void) sprintf(line, "cannot create %s", LogName); - logerror(line); - dprintf("cannot create %s (%d)\n", LogName, errno); - die(0); - } -#ifdef SYSLOG_INET - finet = socket(AF_INET, SOCK_DGRAM, 0); - if (finet >= 0) { - struct servent *sp; - - sp = getservbyname("syslog", "udp"); - if (sp == NULL) { - errno = 0; - logerror("syslog/udp: unknown service"); - } - else { - bzero((char *) &sin, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_port = LogPort = sp->s_port; - if (bind(finet, (struct sockaddr *) &sin, - sizeof(sin)) < 0) - logerror("bind"); - else - InetInuse = 1; - } - if (!InetInuse) - finet = -1; - } -#endif /* SYSLOG_INET */ - if ((fklog = open(_PATH_KLOG, O_RDONLY, 0)) < 0) - dprintf("can't open %s (%d)\n", _PATH_KLOG, errno); - - /* tuck my process id away */ - fp = fopen(PidFile, "w"); - if (fp != NULL) { - fprintf(fp, "%d\n", getpid()); - (void) fclose(fp); - } - - dprintf("off & running....\n"); - - init(); -#ifndef RE_INSTALL_SIGNAL /* init installs itself as the handler */ - (void) signal(SIGHUP, init); -#endif /* !RE_INSTALL_SIGNAL */ -#ifdef SYSLOG_STREAM - FD_ZERO(&unixm); -#endif /* SYSLOG_STREAM */ - - for (;;) { - int nfds; - fd_set readfds; - -#ifdef SYSLOG_STREAM - readfds = unixm; -#else /* !SYSLOG_STREAM */ - FD_ZERO(&readfds); -#endif /* !SYSLOG_STREAM */ - if (funix >= 0) - FD_SET(funix, &readfds); - if (fklog >= 0) - FD_SET(fklog, &readfds); -#ifdef SYSLOG_INET - if (finet >= 0) - FD_SET(finet, &readfds); -#endif /* SYSLOG_INET */ - - errno = 0; - dprintf("readfds = %#x\n", *((long *)&readfds)); - nfds = select(FD_SETSIZE, &readfds, (fd_set *) NULL, - (fd_set *) NULL, (struct timeval *) NULL); - if (nfds == 0) - continue; - if (nfds < 0) { - if (errno != EINTR) - logerror("select"); - continue; - } - dprintf("got a message (%d, %#x)\n", nfds, *((long *)&readfds)); - -#ifdef KLOG_STREAM - if (FD_ISSET(fklog, &readfds)) { - nfds--; - for (;;) { - i = klogread(fklog, line, sizeof(line) - 1); - if (i > 0) { - line[i] = '\0'; - printsys(line); - } - else { - if (i < 0 && errno != EINTR) { - logerror("klog"); - fklog = -1; - } - break; - } - } - } -#else /* !KLOG_STREAM */ - if (FD_ISSET(fklog, &readfds)) { - nfds--; - i = read(fklog, line, sizeof(line) - 1); - if (i > 0) { - line[i] = '\0'; - printsys(line); - } else if (i < 0 && errno != EINTR) { - logerror("klog"); - fklog = -1; - } - } -#endif /* !KLOG_STREAM */ - -#ifdef SYSLOG_STREAM - /* Accept a new unix connection. */ - if (FD_ISSET(funix, &readfds)) { - nfds--; - len = sizeof fromunix; - if ((fd = accept(funix, (struct sockaddr *) &fromunix, - &len)) >= 0) { - FD_SET(fd, &unixm); - dprintf("new stream connect (%d)\n", fd); - } - else - logerror("accept"); - } - /* Recv from existing connections. */ - for (fd = 0; nfds > 0 && fd < FD_SETSIZE; fd++) { - if (FD_ISSET(fd, &unixm) && FD_ISSET(fd, &readfds)) { - nfds--; - dprintf("message from stream (%d)\n", fd); - i = read(fd, line, MAXLINE); - if (i > 0) { - line[i] = '\0'; - printmulti(LocalHostName, line, i); - } - else if (i == 0) { - dprintf("stream closed (%d)\n", fd); - close(fd); - FD_CLR(fd, &unixm); - } - else if (i < 0 && errno != EINTR) { - logerror("recv stream"); - close(fd); - FD_CLR(fd, &unixm); - } - } - } -#else /* !SYSLOG_STREAM */ - if (FD_ISSET(funix, &readfds)) { - nfds--; - len = sizeof fromunix; - i = recvfrom(funix, line, MAXLINE, 0, - (struct sockaddr *) &fromunix, &len); - if (i > 0) { - line[i] = '\0'; - printmulti(LocalHostName, line,i); - } else if (i < 0 && errno != EINTR) - logerror("recvfrom unix"); - } -#endif /* !SYSLOG_STREAM */ - -#ifdef SYSLOG_INET - if (FD_ISSET(finet, &readfds)) { - nfds--; - len = sizeof frominet; - i = recvfrom(finet, line, MAXLINE, 0, - (struct sockaddr *) &frominet, &len); - if (i > 0) { - extern char *cvthname(); - - line[i] = '\0'; - printmulti(cvthname(&frominet), line,i); - } else if (i < 0 && errno != EINTR) - logerror("recvfrom inet"); - } -#endif /* SYSLOG_INET */ - if (nfds != 0) - logerror("loose cannon"); - } -} - -usage() -{ - (void) fprintf(stderr, - "usage: syslogd [-f conffile] [-m markinterval] [-p logpath]\n"); - exit(1); -} - -/* - * Break up null terminated lines for printline. - */ - -printmulti(hname, msg, len) - char *hname; - char *msg; - int len; -{ - int i; - char *pt; - - dprintf("strlen = %d, len = %d\n", strlen(msg), len ); - for (pt = msg, i = 0; i < len; i++) { - if (msg[i] == '\0') { - printline(hname,pt); - pt = &msg[i+1]; - } - } -} - -/* - * Take a raw input line, decode the message, and print the message - * on the appropriate log files. - */ - -printline(hname, msg) - char *hname; - char *msg; -{ - register char *p, *q; - register int c; - char line[MAXLINE + 1]; - int pri; - - /* test for special codes */ - pri = DEFUPRI; - p = msg; - if (*p == '<') { - pri = 0; - while (isdigit(*++p)) - pri = 10 * pri + (*p - '0'); - if (*p == '>') - ++p; - } - if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) - pri = DEFUPRI; - - /* don't allow users to log kernel messages */ - if (LOG_FAC(pri) == LOG_KERN) - pri = LOG_MAKEPRI(LOG_USER, LOG_PRI(pri)); - - q = line; - - while ((c = *p++ & 0177) != '\0' && - q < &line[sizeof(line) - 1]) - if (iscntrl(c)) { - if (c == '\n') - *q++ = ' '; - else if (c == '\r') - *q++ = ' '; - else if (c == '\t') - *q++ = '\t'; - else { - *q++ = '^'; - *q++ = c ^ 0100; - } - } - else - *q++ = c; - *q = '\0'; - - logmsg(pri, line, hname, 0); -} - -/* - * Take a raw input line from /dev/klog, split and format similar to syslog(). - */ - -printsys(msg) - char *msg; -{ - register char *p, *q; - register int c; - char line[MAXLINE + 1]; - int pri, flags; - char *lp; - -#ifdef KERNEL_NAME - (void) sprintf(line, "%s: ", KERNEL_NAME); -#else /* !KERNEL_NAME */ - (void) strcpy(line, "vmunix: "); -#endif /* !KERNEL_NAME */ - - lp = line + strlen(line); - for (p = msg; *p != '\0'; ) { - flags = SYNC_FILE | ADDDATE; /* fsync file after write */ - pri = DEFSPRI; - if (*p == '<') { - pri = 0; - while (isdigit(*++p)) - pri = 10 * pri + (*p - '0'); - if (*p == '>') - ++p; - } else { - /* kernel printf's come out on console */ - flags |= IGN_CONS; - } - if (pri &~ (LOG_FACMASK|LOG_PRIMASK)) - pri = DEFSPRI; - q = lp; - while (*p != '\0' && (c = *p++) != '\n' && - q < &line[MAXLINE]) - if (iscntrl(c)) { - if (c == '\n') - *q++ = ' '; - else if (c == '\r') - *q++ = ' '; - else if (c == '\t') - *q++ = '\t'; - else { - *q++ = '^'; - *q++ = c ^ 0100; - } - } - else - *q++ = c; - *q = '\0'; - logmsg(pri, line, LocalHostName, flags); - } -} - -time_t now; - -/* - * Log a message to the appropriate log files, users, etc. based on - * the priority. - */ - -logmsg(pri, msg, from, flags) - int pri; - char *msg, *from; - int flags; -{ - register struct filed *f; - int fac, prilev; - int omask, msglen; - char *timestamp; - time_t time(); - - 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; - - (void) time(&now); - if (flags & ADDDATE) - timestamp = ctime(&now) + 4; - else { - timestamp = msg; - msg += 16; - msglen -= 16; - } - - /* extract facility and priority level */ - if (flags & MARK) - fac = LOG_NFACILITIES; - else - fac = LOG_FAC(pri); - prilev = 1 << (LOG_PRIMASK - LOG_PRI(pri)); - - /* log the message to the particular outputs */ - if (!Initialized) { - f = &consfile; -#ifdef O_NOCTTY - f->f_file = open(ctty, O_WRONLY|O_NOCTTY, 0); -#else /* !O_NOCTTY */ - f->f_file = open(ctty, O_WRONLY, 0); -#endif /* !O_NOCTTY */ - - if (f->f_file >= 0) { - fprintlog(f, flags, msg); - (void) close(f->f_file); - } - (void) sigsetmask(omask); - return; - } - for (f = Files; f; f = f->f_next) { - /* skip messages that are incorrect priority */ - if (!(f->f_pmask[fac] & prilev)) - 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)) { - (void) strncpy(f->f_lasttime, timestamp, 15); - f->f_prevcount++; - 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; - (void) strncpy(f->f_lasttime, timestamp, 15); - (void) strncpy(f->f_prevhost, from, - sizeof(f->f_prevhost)); - if (msglen < MAXSVLINE) { - f->f_prevlen = msglen; - f->f_prevpri = pri; - (void) strcpy(f->f_prevline, msg); - fprintlog(f, flags, (char *)NULL); - } else { - f->f_prevline[0] = 0; - f->f_prevlen = 0; - fprintlog(f, flags, msg); - } - } - } - (void) sigsetmask(omask); -} - -fprintlog(f, flags, msg) - register struct filed *f; - int flags; - char *msg; -{ - struct iovec iov[6]; - register struct iovec *v; - register int l; - char line[MAXLINE + 1], repbuf[80], greetings[200]; - - v = iov; - if (f->f_type == F_WALL) { - v->iov_base = greetings; - v->iov_len = sprintf(greetings, - "\r\n\7Message from syslogd@%s at %.24s ...\r\n", - f->f_prevhost, ctime(&now)); - v++; - v->iov_base = ""; - v->iov_len = 0; - v++; - } else { - v->iov_base = f->f_lasttime; - v->iov_len = 15; - v++; - v->iov_base = " "; - v->iov_len = 1; - v++; - } - v->iov_base = f->f_prevhost; - v->iov_len = strlen(v->iov_base); - v++; - v->iov_base = " "; - v->iov_len = 1; - v++; - - if (msg) { - v->iov_base = msg; - v->iov_len = strlen(msg); - } else if (f->f_prevcount > 1) { - v->iov_base = repbuf; - v->iov_len = sprintf(repbuf, "last message repeated %d times", - f->f_prevcount); - } else { - v->iov_base = f->f_prevline; - v->iov_len = f->f_prevlen; - } - v++; - - dprintf("Logging to %s", TypeNames[f->f_type]); - f->f_time = now; - - switch (f->f_type) { - case F_UNUSED: - dprintf("\n"); - break; - - case F_FORW: - dprintf(" %s\n", f->f_un.f_forw.f_hname); - l = sprintf(line, "<%d>%.15s %s", f->f_prevpri, - iov[0].iov_base, iov[4].iov_base); - if (l > MAXLINE) - l = MAXLINE; - if (sendto(finet, line, l, 0, - (struct sockaddr *)&f->f_un.f_forw.f_addr, - sizeof f->f_un.f_forw.f_addr) != l) { - int e = errno; - (void) close(f->f_file); - f->f_type = F_UNUSED; - errno = e; - logerror("sendto"); - } - break; - - case F_CONSOLE: - if (flags & IGN_CONS) { - dprintf(" (ignored)\n"); - break; - } - /* FALLTHROUGH */ - - case F_TTY: - case F_FILE: - dprintf(" %s\n", f->f_un.f_fname); - if (f->f_type != F_FILE) { - v->iov_base = "\r\n"; - v->iov_len = 2; - } else { - v->iov_base = "\n"; - v->iov_len = 1; - } - again: - if (writev(f->f_file, iov, 6) < 0) { - int e = errno; - (void) close(f->f_file); - /* - * Check for errors on TTY's due to loss of tty - */ - if ((e == EIO || e == EBADF) && f->f_type != F_FILE) { - f->f_file = open(f->f_un.f_fname, - O_WRONLY|O_APPEND, 0); - if (f->f_file < 0) { - f->f_type = F_UNUSED; - logerror(f->f_un.f_fname); - } else - goto again; - } else { - f->f_type = F_UNUSED; - errno = e; - logerror(f->f_un.f_fname); - } - } -#ifdef FSYNC_MISSING - else if (flags & SYNC_FILE) - (void) sync(); -#else - else if (flags & SYNC_FILE) - (void) fsync(f->f_file); -#endif - break; - - case F_USERS: - case F_WALL: - dprintf("\n"); - v->iov_base = "\r\n"; - v->iov_len = 2; - wallmsg(f, iov); - break; - } - f->f_prevcount = 0; -} - -/* - * WALLMSG -- Write a message to the world at large - * - * Write the specified message to either the entire - * world, or a list of approved users. - */ - -wallmsg(f, iov) - register struct filed *f; - struct iovec *iov; -{ - static int reenter; /* avoid calling ourselves */ - register FILE *uf; - register int i; - struct utmp ut; - char *p, *ttymsg(); - - if (reenter++) - return; - if ((uf = fopen(_PATH_UTMP, "r")) == NULL) { - logerror(_PATH_UTMP); - reenter = 0; - return; - } - /* NOSTRICT */ - while (fread((char *) &ut, sizeof ut, 1, uf) == 1) { - if (ut.ut_name[0] == '\0') - continue; -#ifdef USER_PROCESS - if (ut.ut_type != USER_PROCESS) - continue; -#endif - if (f->f_type == F_WALL) { - if (p = ttymsg(iov, 6, ut.ut_line, 1)) { - errno = 0; /* already in msg */ - logerror(p); - } - continue; - } - /* should we send the message to this user? */ - for (i = 0; i < MAXUNAMES; i++) { - if (!f->f_un.f_uname[i][0]) - break; - if (!strncmp(f->f_un.f_uname[i], ut.ut_name, - UT_NAMESIZE)) { - if (p = ttymsg(iov, 6, ut.ut_line, 1)) { - errno = 0; /* already in msg */ - logerror(p); - } - break; - } - } - } - (void) fclose(uf); - reenter = 0; -} - -void -reapchild() -{ -#ifdef STATUS_BROKEN - int status; -#else - union wait status; -#endif - - while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0) - ; -} - -/* - * Return a printable representation of a host address. - */ -char * -cvthname(f) - struct sockaddr_in *f; -{ - struct hostent *hp; - register char *p; - extern char *inet_ntoa(); - - dprintf("cvthname(%s)\n", inet_ntoa(f->sin_addr)); - - if (f->sin_family != AF_INET) { - dprintf("Malformed from address\n"); - return ("???"); - } - hp = gethostbyaddr((char *)&f->sin_addr, - sizeof(struct in_addr), f->sin_family); - if (hp == 0) { - dprintf("Host name for your address (%s) unknown\n", - inet_ntoa(f->sin_addr)); - return (inet_ntoa(f->sin_addr)); - } - if ((p = index(hp->h_name, '.')) && strcmp(p + 1, LocalDomain) == 0) - *p = '\0'; - return ((char *) hp->h_name); -} - -void -domark() -{ - register struct filed *f; - time_t time(); - - now = time((time_t *)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)) { - dprintf("flush %s: repeated %d times, %d sec.\n", - TypeNames[f->f_type], f->f_prevcount, - repeatinterval[f->f_repeatcount]); - fprintlog(f, 0, (char *)NULL); - BACKOFF(f); - } - } -#ifdef RE_INSTALL_SIGNAL - (void) signal(SIGALRM, domark); -#endif - (void) alarm(TIMERINTVL); -} - -/* - * Print syslogd errors some place. - */ -logerror(type) - char *type; -{ - char buf[100], *strerror(); - - if (errno) - (void) sprintf(buf, "syslogd: %s: %s", type, strerror(errno)); - else - (void) sprintf(buf, "syslogd: %s", type); - errno = 0; - dprintf("%s\n", buf); - logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE); -} - -void -die(sig) -{ - register 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, (char *)NULL); - } - if (sig) { - dprintf("syslogd: exiting on signal %d\n", sig); - (void) sprintf(buf, "exiting on signal %d", sig); - errno = 0; - logerror(buf); - } - (void) unlink(LogName); - exit(0); -} - -/* - * INIT -- Initialize syslogd from configuration table - */ - -void -init() -{ - register int i; - register FILE *cf; - register struct filed *f, *next, **nextp; - register char *p; - char cline[BUFSIZ]; - - dprintf("init\n"); - - /* - * Close all open log files. - */ - Initialized = 0; - for (f = Files; f != NULL; f = next) { - /* flush any pending output */ - if (f->f_prevcount) - fprintlog(f, 0, (char *)NULL); - - switch (f->f_type) { - case F_FILE: - case F_TTY: - case F_CONSOLE: - case F_FORW: - (void) close(f->f_file); - break; - } - next = f->f_next; - free((char *) f); - } - Files = NULL; - nextp = &Files; - - /* open the configuration file */ - if ((cf = fopen(ConfFile, "r")) == NULL) { - dprintf("cannot open %s\n", ConfFile); - *nextp = (struct filed *)calloc(1, sizeof(*f)); - cfline("*.ERR\t/dev/console", *nextp); - (*nextp)->f_next = (struct filed *)calloc(1, sizeof(*f)); - cfline("*.PANIC\t*", (*nextp)->f_next); - Initialized = 1; - return; - } - - /* - * Foreach line in the conf table, open that file. - */ - f = 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); - if (*p == '\0' || *p == '#') - continue; - for (p = index(cline, '\0'); isspace(*--p);); - *++p = '\0'; - f = (struct filed *)calloc(1, sizeof(*f)); - *nextp = f; - nextp = &f->f_next; - cfline(cline, f); - } - - /* close the configuration file */ - (void) fclose(cf); - - Initialized = 1; - - if (Debug) { - for (f = Files; f; f = f->f_next) { - for (i = 0; i <= LOG_NFACILITIES; i++) - if (f->f_pmask[i] == 0) - printf("X "); - else - printf("0x%02x ", f->f_pmask[i]); - printf("%s: ", TypeNames[f->f_type]); - switch (f->f_type) { - case F_FILE: - case F_TTY: - case F_CONSOLE: - printf("%s", f->f_un.f_fname); - break; - - case F_FORW: - printf("%s", f->f_un.f_forw.f_hname); - break; - - case F_USERS: - for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++) - printf("%s, ", f->f_un.f_uname[i]); - break; - } - printf("\n"); - } - } - - logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE); - dprintf("syslogd: restarted\n"); -#ifdef RE_INSTALL_SIGNAL - (void) signal(SIGHUP, init); -#endif /* RE_INSTALL_SIGNAL */ -} - -/* - * Crack a configuration file line - */ - -cfline(line, f) - char *line; - register struct filed *f; -{ - register char *p; - register char *q; - register int i; - char *bp; - int pri; - struct hostent *hp; - char buf[MAXLINE], ebuf[100]; - - dprintf("cfline(%s)\n", line); - - errno = 0; /* keep strerror() stuff out of logerror messages */ - - /* clear out file entry */ - bzero((char *) f, sizeof *f); - for (i = 0; i <= LOG_NFACILITIES; i++) - f->f_pmask[i] = 0; - - /* scan through the list of selectors */ - for (p = line; *p && *p != '\t' && *p != ' ';) { - - /* find the end of this facility name list */ - for (q = p; *q && *q != '\t' && *q != ' ' && *q++ != '.'; ) - continue; - - /* collect priority name */ - for (bp = buf; *q && !index("\t,; ", *q); ) - *bp++ = *q++; - *bp = '\0'; - - /* skip cruft */ - while (index(",;", *q)) /* spaces no longer allowed! */ - q++; - - /* decode priority name */ - if (*buf == '*') - pri = -1; - else { - pri = decode(*buf == '=' ? buf+1 : buf, prioritynames); - if (pri == INTERNAL_NOPRI) - pri = 0; - else if (pri < 0 || pri > LOG_PRIMASK) { - (void) sprintf(ebuf, - "unknown priority name \"%s\"", buf); - logerror(ebuf); - return; - } - else - pri = (*buf == '=' ? 1 : -1) << (LOG_PRIMASK - pri); - - } - - /* scan facilities */ - while (*p && !index("\t.; ", *p)) { - for (bp = buf; *p && !index("\t,;. ", *p); ) - *bp++ = *p++; - *bp = '\0'; - if (*buf == '*') - for (i = 0; i < LOG_NFACILITIES; i++) - if (pri == 0) - f->f_pmask[i] = pri; - else - f->f_pmask[i] |= pri; - else { - i = decode(buf, facilitynames); - if (i < 0) { - (void) sprintf(ebuf, - "unknown facility name \"%s\"", - buf); - logerror(ebuf); - return; - } - if (pri == 0) - f->f_pmask[i >> 3] = pri; - else - f->f_pmask[i >> 3] |= pri; - } - while (*p == ',' || *p == ' ') - p++; - } - - p = q; - } - - /* skip to action part */ - while (*p == '\t' || *p == ' ') - p++; - - switch (*p) - { - case '@': - if (!InetInuse) - break; - (void) strcpy(f->f_un.f_forw.f_hname, ++p); - hp = gethostbyname(p); - if (hp == NULL) { - extern int h_errno, h_nerr; - extern char **h_errlist; - - logerror((u_int)h_errno < h_nerr ? - h_errlist[h_errno] : "Unknown error"); - break; - } - bzero((char *) &f->f_un.f_forw.f_addr, - sizeof f->f_un.f_forw.f_addr); - f->f_un.f_forw.f_addr.sin_family = AF_INET; - f->f_un.f_forw.f_addr.sin_port = LogPort; - bcopy(hp->h_addr, (char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_length); - f->f_type = F_FORW; - break; - - case '/': - (void) strcpy(f->f_un.f_fname, p); -#ifdef O_NOCTTY - if ((f->f_file = open(p, - O_CREAT|O_WRONLY|O_APPEND|O_NOCTTY, - 0644)) < 0) { -#else /* !O_NOCTTY */ - if ((f->f_file = open(p, - O_CREAT|O_WRONLY|O_APPEND, 0644)) < 0) { -#endif /* !O_NOCTTY */ - f->f_file = F_UNUSED; - logerror(p); - break; - } - if (isatty(f->f_file)) - f->f_type = F_TTY; - else - f->f_type = F_FILE; - if (strcmp(p, ctty) == 0) - f->f_type = F_CONSOLE; - break; - - case '*': - f->f_type = F_WALL; - break; - - default: - for (i = 0; i < MAXUNAMES && *p; i++) { - for (q = p; *q && *q != ','; ) - q++; - (void) strncpy(f->f_un.f_uname[i], p, UT_NAMESIZE); - if ((q - p) > UT_NAMESIZE) - f->f_un.f_uname[i][UT_NAMESIZE] = '\0'; - else - f->f_un.f_uname[i][q - p] = '\0'; - while (*q == ',' || *q == ' ') - q++; - p = q; - } - f->f_type = F_USERS; - break; - } -} - - -/* - * Decode a symbolic name to a numeric value - */ - -decode(name, codetab) - char *name; - CODE *codetab; -{ - register CODE *c; - register char *p; - char buf[40]; - - if (isdigit(*name)) - return (atoi(name)); - - (void) strcpy(buf, name); - for (p = buf; *p; p++) - if (isupper(*p)) - *p = tolower(*p); - for (c = codetab; c->c_name; c++) - if (!strcmp(buf, c->c_name)) - return (c->c_val); - - return (-1); -} - -#ifdef KLOG_STREAM - -int klogread(fd, buf, size) - int fd; - char *buf; - int size; -{ - static char line[MAXLINE]; - static char *pos = line; - - int i; - char *obuf = buf; - char *s; - char *end; - *pos = '\0'; - if (!(end = strchr(line, '\n'))) { - struct timeval tv; - fd_set readfds; - - tv.tv_sec = tv.tv_usec = 0; - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - i = select(fd + 1, (fd_set *) &readfds, (fd_set *) NULL, - (fd_set *) NULL, &tv); - if (i <= 0) - return i; - i = read(fd, pos, sizeof(line) - 1 - (pos - line)); - if (i <= 0) - return i; - pos += i; - *pos = '\0'; - if (!(end = strchr(line, '\n'))) - return 0; - } - for (s = line; s < end; s++) - if (*s != '\r') - *buf++ = *s; - end++; - for (s = line; end < pos; s++) - *s = *end++; - pos = s; - return (buf - obuf); -} - -#endif /* KLOG_STREAM */ |