📄 syslog.c
字号:
#ifndef lintchar *sccsid = "@(#)syslog.c 4.2 (ULTRIX) 3/13/91";#endif/*** SYSLOG -- log system messages**** This program implements a system log, implemented as the** "/dev/log" mpx file on a pre-4.2bsd system or a port on** a post-4.2bsd system. This takes a series of lines.** Each line may have a priority, signified as "<n>" as** the first three characters of the line. If this is** not present, a default priority (DefPri) is used, which** starts out as LOG_ERROR. The default priority can get** changed using "<*>n".**** Timestamps are added if they are not already present.**** To kill syslog, send a signal 15 (terminate). In 30** seconds, syslog will go down. A signal 1 (hup) will** cause it to reread its configuration file.**** Defined Constants:** MAXLINE -- the maximimum line length that can be** handled.** NLOGS -- the maximum number of simultaneous log** files.** NUSERS -- the maximum number of people that can** be designated as "superusers" on your system.**** Author:** Eric Allman, UCB/INGRES and Britton-Lee.**** EDIT HISTORY:** 15-Dec-1986: 0001:** Marc Teitelbaum, DEC Ultrix Engineering.** Detach syslog from controlling tty. Establish** a new process group (the pid), so that opens** on tty devices don't establish themselves as** controlling terminals. Open tty logs per** message and close, otherwise vhangup will** dereference the descriptor on us when someone** logs out.** 7-Jan-1987: 0002:** Marc Teitelbaum, via help from puivax!ed** Move opening of tty to later when we are** committed to the write. Otherwise we open** ttys and never close them. (oops)*/# define NLOGS 10 /* max number of log files */# define NSUSERS 10 /* max number of special users */# define MAXLINE 4096 /* maximum line length */# define LOGHOSTNAME 1 /* log hostid on each line */# include <syslog.h># include <errno.h># include <stdio.h># include <utmp.h># include <ctype.h># include <sys/param.h># include <sys/stat.h># include <signal.h># include <sysexits.h># include <sys/ioctl.h># ifdef LOG_IPC# include <sys/socket.h>#ifndef LOG_OLDIPC# include <netinet/in.h># include <netdb.h>#else LOG_OLDIPC# include <net/in.h>#endif LOG_OLDIPC# else LOG_IPC# include <sys/mx.h># endif LOG_IPCtypedef char bool;# define TRUE 1# define FALSE 0# ifdef DEBUG # define dprintf if (Debug) printf# else# define dprintf if (0) printf# endifstatic char SccsId[] = "@(#)syslog.c 4.1 7/25/83";# define UNAMESZ 8 /* length of a login name *//*** This structure represents the files that will have log** copies printed.*/struct filed{ char f_pmask; /* priority mask */ bool f_mark; /* if set, output timing marks */ bool f_tty; /* if set, this is a tty */ FILE *f_file; /* file descriptor; NULL means unallocated */ long f_time; /* the last time anything was output to it */ char f_name[30]; /* filename */};struct filed Files[NLOGS];/* list of superusers */char Susers[NSUSERS][UNAMESZ+1];int ShutDown; /* set if going down */int DefPri = LOG_ERROR; /* the default priority for untagged msgs */int Debug; /* debug flag */int LogFile; /* log mx file descriptor */int MarkIntvl = 15; /* mark interval in minutes */char *ConfFile; /* configuration file */# ifdef LOG_IPC#ifndef LOG_OLDIPCstruct sockaddr_in SyslogAddr;#else LOG_OLDIPCstruct sockaddr_in SyslogAddr = { AF_INET, LOG_PORT };struct sockproto SyslogProto = { PF_INET, IPPROTO_UDP };#endif LOG_OLDIPC# endif LOG_IPCmain(argc, argv) int argc; char **argv;{ register int i; register char *p; extern shutdown(); extern int domark(); extern int errno; int errct = 0; FILE *fp; char *logname = "/dev/log";#ifndef LOG_OLDIPC#ifdef LOG_IPC auto int lenSyslogAddr; struct servent *sp; struct hostent *hp;#endif LOG_IPC#endif LOG_OLDIPC static char *defconf = "/etc/syslog.conf"; static char *defpid = "/etc/syslog.pid"; char line[300];#ifndef LOG_OLDIPC#ifdef LOG_IPC /* set up initial port assignment */ sp = getservbyname("syslog", "udp"); if (sp == NULL) { perror("Cannot get server"); exit(EX_OSFILE); } SyslogAddr.sin_family = AF_INET; SyslogAddr.sin_port = sp->s_port; SyslogAddr.sin_addr.s_addr = INADDR_ANY;#endif LOG_IPC#endif LOG_OLDIPC while (--argc > 0) { p = *++argv; if (p[0] == '-') { switch (p[1]) { case 'm': /* set mark interval */ MarkIntvl = atoi(&p[2]); if (MarkIntvl <= 0) MarkIntvl = 1; break; case 'f': /* configuration file */ if (p[2] != '\0') ConfFile = &p[2]; else ConfFile = defconf; break; case 'd': /* debug */ Debug++; if (ConfFile == NULL) ConfFile = "./syslog.conf"; break;# ifdef LOG_IPC case 'p': /* port */ SyslogAddr.sin_port = htons(atoi(&p[2])); break;# endif LOG_IPC } } } if (ConfFile == NULL) ConfFile = defconf; /* try to ignore all signals */ if (!Debug) { for (i = 1; i < NSIG; i++) signal(i, SIG_IGN); } else signal(SIGINT, shutdown); signal(SIGTERM, shutdown); /* close all files */ if (!Debug) for (i = 0; i < NOFILE; i++) close(i);# ifdef LOG_IPC logname = "IPC socket";#ifndef LOG_OLDIPC LogFile = socket(AF_INET, SOCK_DGRAM, 0, 0); if (LogFile >= 0 && bind(LogFile, &SyslogAddr, sizeof SyslogAddr, 0) < 0) { close(LogFile); LogFile = -1; }#else LOG_OLDIPC LogFile = socket(SOCK_DGRAM, &SyslogProto, &SyslogAddr, 0);#endif LOG_OLDIPC# else LOG_IPC /* create the "/dev/log" device */ if (Debug) logname = "log"; unlink(logname); LogFile = mpx(logname, 0222); chmod(logname, 0222);# endif LOG_IPC if (LogFile < 0) { fp = fopen("/dev/console", "w"); fprintf(fp, "\r\nsyslog: cannot create %s (%d)\r\n", logname, errno); dprintf("cannot create %s (%d)\n", logname, errno); exit(EX_OSFILE); } /* now we can run as daemon safely */ setuid(1); dprintf("off & running....\n"); if (!Debug) { int d; if (fork() == 0) { /* tuck my process id away */ fp = fopen(defpid, "w"); if (fp != NULL) { fprintf(fp, "%d\n", getpid()); fclose(fp); } } else exit(0); /* * 0001 - marc * * Disassociate controlling terminal and establish * new process group to prevent opens on tty devices * from sticking to us. * */ d = open("/dev/tty", 2); if (d >= 0 ) { ioctl(d, TIOCNOTTY, 0); close(d); } setpgrp(0, getpid()); } init(); signal(SIGALRM, domark); alarm(MarkIntvl*60); for (;;) {# ifdef LOG_IPC#ifndef LOG_OLDIPC lenSyslogAddr = sizeof SyslogAddr; i = recvfrom(LogFile, line, sizeof line, 0, &SyslogAddr, &lenSyslogAddr);#else LOG_OLDIPC i = receive(LogFile, &SyslogAddr, line, sizeof line);#endif LOG_OLDIPC# else LOG_IPC i = read(LogFile, line, sizeof line);# endif LOG_IPC if (i < 0) { if (errno == EINTR) continue; logerror("read"); errct++; if (errct > 1000) { logmsg(LOG_SALERT, "syslog: too many errors"); die(); } sleep(15); continue; }# ifdef LOG_IPC line[i] = '\0'; hp = gethostbyaddr(&SyslogAddr.sin_addr, sizeof (SyslogAddr.sin_addr), AF_INET); if (hp == 0) printline(line, inet_ntoa(SyslogAddr.sin_addr)); else printline(line, hp->h_name);# else LOG_IPC crack(line, i);# endif LOG_IPC }}/*** LOGERROR -- log an error on the log.**** Parameters:** type -- string to print as error type.**** Returns:** none.**** Side Effects:** outputs the error code in errno to someplace.*/logerror(type) char *type;{ char buf[50]; extern int errno; sprintf(buf, "log %s error %d\n", type, errno); errno = 0; logmsg(LOG_SALERT, buf);}# ifndef LOG_IPC/*** CRACK -- parse & handle a log line**** Parameters:** rec -- the input record.** bc -- the byte count for rec.**** Returns:** nothing**** Side Effects:** rec is output.*/# define skip(rec, n) ((struct rh *) (((char *) rec) + n))crack(rec, bc) register struct rh *rec; int bc;{ struct rh *endrec; endrec = skip(rec, bc); while (rec < endrec) { if (rec->count == 0) { /* control record from mpx file */ dprintf("%d byte control message\n", rec->ccount); control(rec); } else { /* data record -- process message */ messg(rec); } rec->count += rec->ccount; if (rec->count & 01) rec->count++; rec = skip(rec, rec->count + sizeof *rec); }}/*** CONTROL -- handle mpx control messages.**** Parameters:** rec -- control message.**** Returns:** none.**** Side Effects:** as necessary for that control message.*/short NoIoctl[] = { M_IOANS };control(rec) register struct rh *rec;{ register int cmd; register short val; register short *ap;# ifdef MPXDEBUG char dbbuf[100];# endif MPXDEBUG ap = (short *) (((char *) rec) + sizeof *rec); cmd = *ap++ & 0377; val = *ap++;# ifdef MPXDEBUG sprintf(dbbuf, "syslog: ctl ch=%x cmd=%d val=%d", rec->index, cmd, val); logmsg(LOG_DEBUG, dbbuf);# endif MPXDEBUG switch (cmd) { case M_WATCH: /* attempted connect; value is uid */ dprintf("WATCH, uid=%d\n", val); attach(rec->index, LogFile); break; case M_CLOSE: /* close channel; value is unused */ dprintf("CLOSE, val=%d\n", val); detach(rec->index, LogFile); break; case M_IOCTL: dprintf("IOCTL, val=%d\n", val); wmpxctl(rec->index, NoIoctl, sizeof NoIoctl); break; default: dprintf("unknown cmd %d, val=%d\n", cmd, val); break; }}/*** WMPXCTL -- write mpx control message**** Parameters:** index -- index to write to.** buf -- place to write.** len -- length to write.**** Returns:** none.**** Side Effects:** writes to LogFile.*/wmpxctl(index, buf, cnt) int index; char *buf; int cnt;{ struct wh wbuf; wbuf.index = index; wbuf.count = 0; wbuf.ccount = cnt; wbuf.data = buf; write(LogFile, &wbuf, sizeof wbuf);}/*** MESSG -- log message**** Parameters:** rec -- record of data.**** Returns:** nothing.**** Side Effects:** sends the record to the system log.*/messg(rec) register struct rh *rec;{ char endchar; char *endptr; register char *q; q = (char *) rec + sizeof *rec; endptr = &q[rec->count]; endchar = *endptr; *endptr = '\0'; printline(q, NULL); *endptr = endchar;}# endif LOG_IPC/*** PRINTLINE -- print one line**** This is really it -- we have one line -- we crack it and** and print it appropriately.**** Parameters:** q -- pointer to the line.** tag -- the name of the host this is from.**** Returns:** none.**** Side Effects:** q is broken up and printed.*/printline(q, tag) register char *q;{ register int i; static int pri; register char *p; static char buf[1000]; static char *bp = buf; dprintf("message = ``%s''\n", q); while (*q != '\0') { if (bp == buf) {# if LOGHOSTNAME > 0 if (tag != NULL) { strcpy(bp, tag); strcat(bp, ": "); bp += strlen(bp); }# endif LOGHOSTNAME /* test for special codes */ pri = DefPri; if (q[0] == '<' && q[2] == '>') { switch (q[1]) { case '*': /* reset default message priority */ dprintf("default priority = %c\n", q[3]); i = q[3] - '0'; if (i > 0 && i <= 9) DefPri = i; continue; case '$': /* reconfigure */ dprintf("reconfigure\n"); init(); continue; } q++; pri = *q++ - '0'; q++; if (pri < 0 || pri > 9) pri = DefPri; } else pri = DefPri; } while (*q != '\0' && *q != '\n') { if (*q != '\r') *bp++ = *q; q++; } if (*q == '\0') continue; *bp++ = '\0'; q++; bp = buf; /* output the line to all files */ logmsg(pri, bp); bp = buf; }}/*** SHUTDOWN -- shutdown the logger**** This should only be done when the system is going down.**** Parameters:** none**** Returns:** none**** Side Effects:** Starts up an alarm clock, to let other things** happen. Alarm clock will call "die".**** Called By:** main** signal 15 (terminate)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -