|
|
1.1 root 1: /*
2: * Copyright (c) 1983 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: char copyright[] =
9: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
10: All rights reserved.\n";
11: #endif not lint
12:
13: #ifndef lint
14: static char sccsid[] = "@(#)syslogd.c 5.13 (Berkeley) 5/26/86";
15: #endif not lint
16:
17: /*
18: * syslogd -- log system messages
19: *
20: * This program implements a system log. It takes a series of lines.
21: * Each line may have a priority, signified as "<n>" as
22: * the first characters of the line. If this is
23: * not present, a default priority is used.
24: *
25: * To kill syslogd, send a signal 15 (terminate). A signal 1 (hup) will
26: * cause it to reread its configuration file.
27: *
28: * Defined Constants:
29: *
30: * MAXLINE -- the maximimum line length that can be handled.
31: * NLOGS -- the maximum number of simultaneous log files.
32: * DEFUPRI -- the default priority for user messages
33: * DEFSPRI -- the default priority for kernel messages
34: *
35: * Author: Eric Allman
36: * extensive changes by Ralph Campbell
37: */
38:
39: #define NLOGS 20 /* max number of log files */
40: #define MAXLINE 1024 /* maximum line length */
41: #define DEFUPRI (LOG_USER|LOG_NOTICE)
42: #define DEFSPRI (LOG_KERN|LOG_CRIT)
43: #define MARKCOUNT 10 /* ratio of minor to major marks */
44:
45: #include <errno.h>
46: #include <stdio.h>
47: #include <utmp.h>
48: #include <ctype.h>
49: #include <signal.h>
50: #include <sysexits.h>
51: #include <strings.h>
52:
53: #include <sys/syslog.h>
54: #include <sys/types.h>
55: #include <sys/param.h>
56: #include <sys/ioctl.h>
57: #include <sys/stat.h>
58: #include <sys/wait.h>
59: #include <sys/socket.h>
60: #include <sys/file.h>
61: #include <sys/msgbuf.h>
62: #include <sys/uio.h>
63: #include <sys/un.h>
64: #include <sys/time.h>
65: #include <sys/resource.h>
66:
67: #include <netinet/in.h>
68: #include <netdb.h>
69:
70: char *LogName = "/dev/log";
71: char *ConfFile = "/etc/syslog.conf";
72: char *PidFile = "/etc/syslog.pid";
73: char ctty[] = "/dev/console";
74:
75: #define FDMASK(fd) (1 << (fd))
76:
77: #define dprintf if (Debug) printf
78:
79: #define UNAMESZ 8 /* length of a login name */
80: #define MAXUNAMES 20 /* maximum number of user names */
81: #define MAXFNAME 200 /* max file pathname length */
82:
83: #define NOPRI 0x10 /* the "no priority" priority */
84: #define LOG_MARK (LOG_NFACILITIES << 3) /* mark "facility" */
85:
86: /*
87: * Flags to logmsg().
88: */
89:
90: #define IGN_CONS 0x001 /* don't print on console */
91: #define SYNC_FILE 0x002 /* do fsync on file after printing */
92: #define NOCOPY 0x004 /* don't suppress duplicate messages */
93: #define ADDDATE 0x008 /* add a date to the message */
94: #define MARK 0x010 /* this message is a mark */
95:
96: /*
97: * This structure represents the files that will have log
98: * copies printed.
99: */
100:
101: struct filed {
102: short f_type; /* entry type, see below */
103: short f_file; /* file descriptor */
104: time_t f_time; /* time this was last written */
105: u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
106: union {
107: char f_uname[MAXUNAMES][UNAMESZ+1];
108: struct {
109: char f_hname[MAXHOSTNAMELEN+1];
110: struct sockaddr_in f_addr;
111: } f_forw; /* forwarding address */
112: char f_fname[MAXFNAME];
113: } f_un;
114: };
115:
116: /* values for f_type */
117: #define F_UNUSED 0 /* unused entry */
118: #define F_FILE 1 /* regular file */
119: #define F_TTY 2 /* terminal */
120: #define F_CONSOLE 3 /* console terminal */
121: #define F_FORW 4 /* remote machine */
122: #define F_USERS 5 /* list of users */
123: #define F_WALL 6 /* everyone logged on */
124:
125: char *TypeNames[7] = {
126: "UNUSED", "FILE", "TTY", "CONSOLE",
127: "FORW", "USERS", "WALL"
128: };
129:
130: struct filed Files[NLOGS];
131:
132: int Debug; /* debug flag */
133: char LocalHostName[MAXHOSTNAMELEN+1]; /* our hostname */
134: char *LocalDomain; /* our local domain name */
135: int InetInuse = 0; /* non-zero if INET sockets are being used */
136: int LogPort; /* port number for INET connections */
137: char PrevLine[MAXLINE + 1]; /* copy of last line to supress repeats */
138: char PrevHost[MAXHOSTNAMELEN+1]; /* previous host */
139: int PrevFlags;
140: int PrevPri;
141: int PrevCount = 0; /* number of times seen */
142: int Initialized = 0; /* set when we have initialized ourselves */
143: int MarkInterval = 20; /* interval between marks in minutes */
144: int MarkSeq = 0; /* mark sequence number */
145:
146: extern int errno, sys_nerr;
147: extern char *sys_errlist[];
148: extern char *ctime(), *index();
149:
150: main(argc, argv)
151: int argc;
152: char **argv;
153: {
154: register int i;
155: register char *p;
156: int funix, finet, inetm, fklog, klogm, len;
157: struct sockaddr_un sun, fromunix;
158: struct sockaddr_in sin, frominet;
159: FILE *fp;
160: char line[MSG_BSIZE + 1];
161: extern int die(), domark(), reapchild();
162:
163: while (--argc > 0) {
164: p = *++argv;
165: if (p[0] != '-')
166: usage();
167: switch (p[1]) {
168: case 'f': /* configuration file */
169: if (p[2] != '\0')
170: ConfFile = &p[2];
171: break;
172:
173: case 'd': /* debug */
174: Debug++;
175: break;
176:
177: case 'p': /* path */
178: if (p[2] != '\0')
179: LogName = &p[2];
180: break;
181:
182: case 'm': /* mark interval */
183: if (p[2] != '\0')
184: MarkInterval = atoi(&p[2]);
185: break;
186:
187: default:
188: usage();
189: }
190: }
191:
192: if (!Debug) {
193: if (fork())
194: exit(0);
195: for (i = 0; i < 10; i++)
196: (void) close(i);
197: (void) open("/", 0);
198: (void) dup2(0, 1);
199: (void) dup2(0, 2);
200: untty();
201: } else
202: setlinebuf(stdout);
203:
204: (void) gethostname(LocalHostName, sizeof LocalHostName);
205: if (p = index(LocalHostName, '.')) {
206: *p++ = '\0';
207: LocalDomain = p;
208: }
209: else
210: LocalDomain = "";
211: (void) signal(SIGTERM, die);
212: (void) signal(SIGINT, Debug ? die : SIG_IGN);
213: (void) signal(SIGQUIT, Debug ? die : SIG_IGN);
214: (void) signal(SIGCHLD, reapchild);
215: (void) signal(SIGALRM, domark);
216: (void) alarm(MarkInterval * 60 / MARKCOUNT);
217: (void) unlink(LogName);
218:
219: sun.sun_family = AF_UNIX;
220: (void) strncpy(sun.sun_path, LogName, sizeof sun.sun_path);
221: funix = socket(AF_UNIX, SOCK_DGRAM, 0);
222: if (funix < 0 || bind(funix, (struct sockaddr *) &sun,
223: sizeof(sun.sun_family)+strlen(sun.sun_path)) < 0 ||
224: chmod(LogName, 0666) < 0) {
225: (void) sprintf(line, "cannot create %s", LogName);
226: logerror(line);
227: dprintf("cannot create %s (%d)\n", LogName, errno);
228: die(0);
229: }
230: finet = socket(AF_INET, SOCK_DGRAM, 0);
231: if (finet >= 0) {
232: struct servent *sp;
233:
234: sp = getservbyname("syslog", "udp");
235: if (sp == NULL) {
236: errno = 0;
237: logerror("syslog/udp: unknown service");
238: die(0);
239: }
240: sin.sin_family = AF_INET;
241: sin.sin_port = LogPort = sp->s_port;
242: if (bind(finet, &sin, sizeof(sin)) < 0) {
243: logerror("bind");
244: if (!Debug)
245: die(0);
246: } else {
247: inetm = FDMASK(finet);
248: InetInuse = 1;
249: }
250: }
251: if ((fklog = open("/dev/klog", O_RDONLY)) >= 0)
252: klogm = FDMASK(fklog);
253: else {
254: dprintf("can't open /dev/klog (%d)\n", errno);
255: klogm = 0;
256: }
257:
258: /* tuck my process id away */
259: fp = fopen(PidFile, "w");
260: if (fp != NULL) {
261: fprintf(fp, "%d\n", getpid());
262: (void) fclose(fp);
263: }
264:
265: dprintf("off & running....\n");
266:
267: init();
268: (void) signal(SIGHUP, init);
269:
270: for (;;) {
271: int nfds, readfds = FDMASK(funix) | inetm | klogm;
272:
273: errno = 0;
274: dprintf("readfds = %#x\n", readfds, funix, finet, fklog);
275: nfds = select(20, (fd_set *) &readfds, (fd_set *) NULL,
276: (fd_set *) NULL, (struct timeval *) NULL);
277: dprintf("got a message (%d, %#x)\n", nfds, readfds);
278: if (nfds == 0)
279: continue;
280: if (nfds < 0) {
281: if (errno != EINTR)
282: logerror("select");
283: continue;
284: }
285: if (readfds & klogm) {
286: i = read(fklog, line, sizeof(line) - 1);
287: if (i > 0) {
288: line[i] = '\0';
289: printsys(line);
290: } else if (i < 0 && errno != EINTR) {
291: logerror("klog");
292: fklog = -1;
293: klogm = 0;
294: }
295: }
296: if (readfds & FDMASK(funix)) {
297: len = sizeof fromunix;
298: i = recvfrom(funix, line, MAXLINE, 0,
299: (struct sockaddr *) &fromunix, &len);
300: if (i > 0) {
301: line[i] = '\0';
302: printline(LocalHostName, line);
303: } else if (i < 0 && errno != EINTR)
304: logerror("recvfrom unix");
305: }
306: if (readfds & inetm) {
307: len = sizeof frominet;
308: i = recvfrom(finet, line, MAXLINE, 0, &frominet, &len);
309: if (i > 0) {
310: extern char *cvthname();
311:
312: line[i] = '\0';
313: printline(cvthname(&frominet), line);
314: } else if (i < 0 && errno != EINTR)
315: logerror("recvfrom inet");
316: }
317: }
318: }
319:
320: usage()
321: {
322: fprintf(stderr, "usage: syslogd [-d] [-mmarkinterval] [-ppath] [-fconffile]\n");
323: exit(1);
324: }
325:
326: untty()
327: {
328: int i;
329:
330: if (!Debug) {
331: i = open("/dev/tty", O_RDWR);
332: if (i >= 0) {
333: (void) ioctl(i, (int) TIOCNOTTY, (char *)0);
334: (void) close(i);
335: }
336: }
337: }
338:
339: /*
340: * Take a raw input line, decode the message, and print the message
341: * on the appropriate log files.
342: */
343:
344: printline(hname, msg)
345: char *hname;
346: char *msg;
347: {
348: register char *p, *q;
349: register int c;
350: char line[MAXLINE + 1];
351: int pri;
352:
353: /* test for special codes */
354: pri = DEFUPRI;
355: p = msg;
356: if (*p == '<') {
357: pri = 0;
358: while (isdigit(*++p))
359: pri = 10 * pri + (*p - '0');
360: if (*p == '>')
361: ++p;
362: if (pri <= 0 || pri >= (LOG_NFACILITIES << 3))
363: pri = DEFUPRI;
364: }
365:
366: /* don't allow users to log kernel messages */
367: if ((pri & LOG_PRIMASK) == LOG_KERN)
368: pri |= LOG_USER;
369:
370: q = line;
371:
372: while ((c = *p++ & 0177) != '\0' && c != '\n' &&
373: q < &line[sizeof(line) - 1]) {
374: if (iscntrl(c)) {
375: *q++ = '^';
376: *q++ = c ^ 0100;
377: } else
378: *q++ = c;
379: }
380: *q = '\0';
381:
382: logmsg(pri, line, hname, 0);
383: }
384:
385: /*
386: * Take a raw input line from /dev/klog, split and format similar to syslog().
387: */
388:
389: printsys(msg)
390: char *msg;
391: {
392: register char *p, *q;
393: register int c;
394: char line[MAXLINE + 1];
395: int pri, flags;
396: char *lp;
397: time_t now;
398:
399: (void) time(&now);
400: (void) sprintf(line, "%.15s vmunix: ", ctime(&now) + 4);
401: lp = line + strlen(line);
402: for (p = msg; *p != '\0'; ) {
403: flags = SYNC_FILE; /* fsync file after write */
404: pri = DEFSPRI;
405: if (*p == '<') {
406: pri = 0;
407: while (isdigit(*++p))
408: pri = 10 * pri + (*p - '0');
409: if (*p == '>')
410: ++p;
411: if (pri <= 0 || pri >= (LOG_NFACILITIES << 3))
412: pri = DEFSPRI;
413: } else {
414: /* kernel printf's come out on console */
415: flags |= IGN_CONS;
416: }
417: q = lp;
418: while (*p != '\0' && (c = *p++) != '\n' &&
419: q < &line[MAXLINE])
420: *q++ = c;
421: *q = '\0';
422: logmsg(pri, line, LocalHostName, flags);
423: }
424: }
425:
426: /*
427: * Log a message to the appropriate log files, users, etc. based on
428: * the priority.
429: */
430:
431: logmsg(pri, msg, from, flags)
432: int pri;
433: char *msg, *from;
434: int flags;
435: {
436: register struct filed *f;
437: register int l;
438: int fac, prilev;
439: time_t now;
440: int omask;
441: struct iovec iov[6];
442: register struct iovec *v = iov;
443: char line[MAXLINE + 1];
444:
445: dprintf("logmsg: pri %o, flags %x, from %s, msg %s\n", pri, flags, from, msg);
446:
447: omask = sigblock(sigmask(SIGHUP)|sigmask(SIGALRM));
448:
449: /*
450: * Check to see if msg looks non-standard.
451: */
452: if (strlen(msg) < 16 || msg[3] != ' ' || msg[6] != ' ' ||
453: msg[9] != ':' || msg[12] != ':' || msg[15] != ' ')
454: flags |= ADDDATE;
455:
456: if (!(flags & NOCOPY)) {
457: if (flags & (ADDDATE|MARK))
458: flushmsg();
459: else if (!strcmp(msg + 16, PrevLine + 16)) {
460: /* we found a match, update the time */
461: (void) strncpy(PrevLine, msg, 15);
462: PrevCount++;
463: (void) sigsetmask(omask);
464: return;
465: } else {
466: /* new line, save it */
467: flushmsg();
468: (void) strcpy(PrevLine, msg);
469: (void) strcpy(PrevHost, from);
470: PrevFlags = flags;
471: PrevPri = pri;
472: }
473: }
474:
475: (void) time(&now);
476: if (flags & ADDDATE)
477: v->iov_base = ctime(&now) + 4;
478: else
479: v->iov_base = msg;
480: v->iov_len = 15;
481: v++;
482: v->iov_base = " ";
483: v->iov_len = 1;
484: v++;
485: v->iov_base = from;
486: v->iov_len = strlen(v->iov_base);
487: v++;
488: v->iov_base = " ";
489: v->iov_len = 1;
490: v++;
491: if (flags & ADDDATE)
492: v->iov_base = msg;
493: else
494: v->iov_base = msg + 16;
495: v->iov_len = strlen(v->iov_base);
496: v++;
497:
498: /* extract facility and priority level */
499: fac = (pri & LOG_FACMASK) >> 3;
500: if (flags & MARK)
501: fac = LOG_NFACILITIES;
502: prilev = pri & LOG_PRIMASK;
503:
504: /* log the message to the particular outputs */
505: if (!Initialized) {
506: int cfd = open(ctty, O_WRONLY);
507:
508: if (cfd >= 0) {
509: v->iov_base = "\r\n";
510: v->iov_len = 2;
511: (void) writev(cfd, iov, 6);
512: (void) close(cfd);
513: }
514: untty();
515: (void) sigsetmask(omask);
516: return;
517: }
518: for (f = Files; f < &Files[NLOGS]; f++) {
519: /* skip messages that are incorrect priority */
520: if (f->f_pmask[fac] < prilev || f->f_pmask[fac] == NOPRI)
521: continue;
522:
523: /* don't output marks to recently written files */
524: if ((flags & MARK) && (now - f->f_time) < (MarkInterval * 60 / 2))
525: continue;
526:
527: dprintf("Logging to %s", TypeNames[f->f_type]);
528: f->f_time = now;
529: switch (f->f_type) {
530: case F_UNUSED:
531: dprintf("\n");
532: break;
533:
534: case F_FORW:
535: dprintf(" %s\n", f->f_un.f_forw.f_hname);
536: (void) sprintf(line, "<%d>%.15s %s", pri,
537: iov[0].iov_base, iov[4].iov_base);
538: l = strlen(line);
539: if (l > MAXLINE)
540: l = MAXLINE;
541: if (sendto(f->f_file, line, l, 0,
542: &f->f_un.f_forw.f_addr,
543: sizeof f->f_un.f_forw.f_addr) != l) {
544: int e = errno;
545: (void) close(f->f_file);
546: f->f_type = F_UNUSED;
547: errno = e;
548: logerror("sendto");
549: }
550: break;
551:
552: case F_CONSOLE:
553: if (flags & IGN_CONS) {
554: dprintf(" (ignored)\n");
555: break;
556: }
557:
558: case F_TTY:
559: case F_FILE:
560: dprintf(" %s\n", f->f_un.f_fname);
561: if (f->f_type != F_FILE) {
562: v->iov_base = "\r\n";
563: v->iov_len = 2;
564: } else {
565: v->iov_base = "\n";
566: v->iov_len = 1;
567: }
568: if (writev(f->f_file, iov, 6) < 0) {
569: int e = errno;
570: (void) close(f->f_file);
571: /*
572: * Check for EBADF on TTY's due to vhangup() XXX
573: */
574: if (e == EBADF && f->f_type != F_FILE) {
575: f->f_file = open(f->f_un.f_fname, O_WRONLY|O_APPEND);
576: if (f->f_file < 0) {
577: f->f_type = F_UNUSED;
578: logerror(f->f_un.f_fname);
579: }
580: } else {
581: f->f_type = F_UNUSED;
582: errno = e;
583: logerror(f->f_un.f_fname);
584: }
585: } else if (flags & SYNC_FILE)
586: (void) fsync(f->f_file);
587: break;
588:
589: case F_USERS:
590: case F_WALL:
591: dprintf("\n");
592: v->iov_base = "\r\n";
593: v->iov_len = 2;
594: wallmsg(f, iov);
595: break;
596: }
597: }
598:
599: (void) sigsetmask(omask);
600: }
601:
602:
603: /*
604: * WALLMSG -- Write a message to the world at large
605: *
606: * Write the specified message to either the entire
607: * world, or a list of approved users.
608: */
609:
610: wallmsg(f, iov)
611: register struct filed *f;
612: struct iovec *iov;
613: {
614: register char *p;
615: register int i;
616: int ttyf, len;
617: FILE *uf;
618: static int reenter = 0;
619: struct utmp ut;
620: time_t now;
621: char greetings[200];
622:
623: if (reenter++)
624: return;
625:
626: /* open the user login file */
627: if ((uf = fopen("/etc/utmp", "r")) == NULL) {
628: logerror("/etc/utmp");
629: reenter = 0;
630: return;
631: }
632:
633: (void) time(&now);
634: (void) sprintf(greetings,
635: "\r\n\7Message from syslogd@%s at %.24s ...\r\n",
636: iov[2].iov_base, ctime(&now));
637: len = strlen(greetings);
638:
639: /* scan the user login file */
640: while (fread((char *) &ut, sizeof ut, 1, uf) == 1) {
641: /* is this slot used? */
642: if (ut.ut_name[0] == '\0')
643: continue;
644:
645: /* should we send the message to this user? */
646: if (f->f_type == F_USERS) {
647: for (i = 0; i < MAXUNAMES; i++) {
648: if (!f->f_un.f_uname[i][0]) {
649: i = MAXUNAMES;
650: break;
651: }
652: if (strncmp(f->f_un.f_uname[i], ut.ut_name,
653: UNAMESZ) == 0)
654: break;
655: }
656: if (i >= MAXUNAMES)
657: continue;
658: }
659:
660: /* compute the device name */
661: p = "/dev/12345678";
662: strcpyn(&p[5], ut.ut_line, UNAMESZ);
663:
664: /*
665: * Might as well fork instead of using nonblocking I/O
666: * and doing notty().
667: */
668: if (fork() == 0) {
669: if (f->f_type == F_WALL) {
670: iov[0].iov_base = greetings;
671: iov[0].iov_len = len;
672: iov[1].iov_len = 0;
673: }
674: (void) signal(SIGALRM, SIG_DFL);
675: (void) alarm(30);
676: /* open the terminal */
677: ttyf = open(p, O_WRONLY);
678: if (ttyf >= 0)
679: (void) writev(ttyf, iov, 6);
680: exit(0);
681: }
682: }
683: /* close the user login file */
684: (void) fclose(uf);
685: reenter = 0;
686: }
687:
688: reapchild()
689: {
690: union wait status;
691:
692: while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0)
693: ;
694: }
695:
696: /*
697: * Return a printable representation of a host address.
698: */
699: char *
700: cvthname(f)
701: struct sockaddr_in *f;
702: {
703: struct hostent *hp;
704: register char *p;
705: extern char *inet_ntoa();
706:
707: dprintf("cvthname(%s)\n", inet_ntoa(f->sin_addr));
708:
709: if (f->sin_family != AF_INET) {
710: dprintf("Malformed from address\n");
711: return ("???");
712: }
713: hp = gethostbyaddr(&f->sin_addr, sizeof(struct in_addr), f->sin_family);
714: if (hp == 0) {
715: dprintf("Host name for your address (%s) unknown\n",
716: inet_ntoa(f->sin_addr));
717: return (inet_ntoa(f->sin_addr));
718: }
719: if ((p = index(hp->h_name, '.')) && strcmp(p + 1, LocalDomain) == 0)
720: *p = '\0';
721: return (hp->h_name);
722: }
723:
724: domark()
725: {
726: int pri;
727:
728: if ((++MarkSeq % MARKCOUNT) == 0)
729: logmsg(LOG_INFO, "-- MARK --", LocalHostName, ADDDATE|MARK);
730: else
731: flushmsg();
732: alarm(MarkInterval * 60 / MARKCOUNT);
733: }
734:
735: flushmsg()
736: {
737: if (PrevCount == 0)
738: return;
739: if (PrevCount > 1)
740: (void) sprintf(PrevLine+16, "last message repeated %d times", PrevCount);
741: PrevCount = 0;
742: logmsg(PrevPri, PrevLine, PrevHost, PrevFlags|NOCOPY);
743: PrevLine[0] = '\0';
744: }
745:
746: /*
747: * Print syslogd errors some place.
748: */
749: logerror(type)
750: char *type;
751: {
752: char buf[100];
753:
754: if (errno == 0)
755: (void) sprintf(buf, "syslogd: %s", type);
756: else if ((unsigned) errno > sys_nerr)
757: (void) sprintf(buf, "syslogd: %s: error %d", type, errno);
758: else
759: (void) sprintf(buf, "syslogd: %s: %s", type, sys_errlist[errno]);
760: errno = 0;
761: dprintf("%s\n", buf);
762: logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
763: }
764:
765: die(sig)
766: {
767: char buf[100];
768:
769: if (sig) {
770: dprintf("syslogd: going down on signal %d\n", sig);
771: flushmsg();
772: (void) sprintf(buf, "going down on signal %d", sig);
773: logerror(buf);
774: }
775: (void) unlink(LogName);
776: exit(0);
777: }
778:
779: /*
780: * INIT -- Initialize syslogd from configuration table
781: */
782:
783: init()
784: {
785: register int i;
786: register FILE *cf;
787: register struct filed *f;
788: register char *p;
789: char cline[BUFSIZ];
790:
791: dprintf("init\n");
792:
793: /* flush any pending output */
794: flushmsg();
795:
796: /*
797: * Close all open log files.
798: */
799: for (f = Files; f < &Files[NLOGS]; f++) {
800: if (f->f_type == F_FILE || f->f_type == F_TTY)
801: (void) close(f->f_file);
802: f->f_type = F_UNUSED;
803: }
804:
805: /* open the configuration file */
806: if ((cf = fopen(ConfFile, "r")) == NULL) {
807: dprintf("cannot open %s\n", ConfFile);
808: cfline("*.ERR\t/dev/console", &Files[0]);
809: cfline("*.PANIC\t*", &Files[1]);
810: return;
811: }
812:
813: /*
814: * Foreach line in the conf table, open that file.
815: */
816: f = Files;
817: while (fgets(cline, sizeof cline, cf) != NULL && f < &Files[NLOGS]) {
818: /* check for end-of-section */
819: if (cline[0] == '\n' || cline[0] == '#')
820: continue;
821:
822: /* strip off newline character */
823: p = index(cline, '\n');
824: if (p)
825: *p = '\0';
826:
827: cfline(cline, f++);
828: }
829:
830: /* close the configuration file */
831: (void) fclose(cf);
832:
833: Initialized = 1;
834:
835: if (Debug) {
836: for (f = Files; f < &Files[NLOGS]; f++) {
837: for (i = 0; i <= LOG_NFACILITIES; i++)
838: if (f->f_pmask[i] == NOPRI)
839: printf("X ");
840: else
841: printf("%d ", f->f_pmask[i]);
842: printf("%s: ", TypeNames[f->f_type]);
843: switch (f->f_type) {
844: case F_FILE:
845: case F_TTY:
846: case F_CONSOLE:
847: printf("%s", f->f_un.f_fname);
848: break;
849:
850: case F_FORW:
851: printf("%s", f->f_un.f_forw.f_hname);
852: break;
853:
854: case F_USERS:
855: for (i = 0; i < MAXUNAMES && *f->f_un.f_uname[i]; i++)
856: printf("%s, ", f->f_un.f_uname[i]);
857: break;
858: }
859: printf("\n");
860: }
861: }
862:
863: logmsg(LOG_SYSLOG|LOG_INFO, "syslogd: restart", LocalHostName, ADDDATE);
864: dprintf("syslogd: restarted\n");
865: }
866:
867: /*
868: * Crack a configuration file line
869: */
870:
871: struct code {
872: char *c_name;
873: int c_val;
874: };
875:
876: struct code PriNames[] = {
877: "panic", LOG_EMERG,
878: "emerg", LOG_EMERG,
879: "alert", LOG_ALERT,
880: "crit", LOG_CRIT,
881: "err", LOG_ERR,
882: "error", LOG_ERR,
883: "warn", LOG_WARNING,
884: "warning", LOG_WARNING,
885: "notice", LOG_NOTICE,
886: "info", LOG_INFO,
887: "debug", LOG_DEBUG,
888: "none", NOPRI,
889: NULL, -1
890: };
891:
892: struct code FacNames[] = {
893: "kern", LOG_KERN,
894: "user", LOG_USER,
895: "mail", LOG_MAIL,
896: "daemon", LOG_DAEMON,
897: "auth", LOG_AUTH,
898: "security", LOG_AUTH,
899: "mark", LOG_MARK,
900: "syslog", LOG_SYSLOG,
901: "lpr", LOG_LPR,
902: "local0", LOG_LOCAL0,
903: "local1", LOG_LOCAL1,
904: "local2", LOG_LOCAL2,
905: "local3", LOG_LOCAL3,
906: "local4", LOG_LOCAL4,
907: "local5", LOG_LOCAL5,
908: "local6", LOG_LOCAL6,
909: "local7", LOG_LOCAL7,
910: NULL, -1
911: };
912:
913: cfline(line, f)
914: char *line;
915: register struct filed *f;
916: {
917: register char *p;
918: register char *q;
919: register int i;
920: char *bp;
921: int pri;
922: struct hostent *hp;
923: char buf[MAXLINE];
924:
925: dprintf("cfline(%s)\n", line);
926:
927: /* clear out file entry */
928: bzero((char *) f, sizeof *f);
929: for (i = 0; i <= LOG_NFACILITIES; i++)
930: f->f_pmask[i] = NOPRI;
931:
932: /* scan through the list of selectors */
933: for (p = line; *p && *p != '\t';) {
934:
935: /* find the end of this facility name list */
936: for (q = p; *q && *q != '\t' && *q++ != '.'; )
937: continue;
938:
939: /* collect priority name */
940: for (bp = buf; *q && !index("\t,;", *q); )
941: *bp++ = *q++;
942: *bp = '\0';
943:
944: /* skip cruft */
945: while (index(", ;", *q))
946: q++;
947:
948: /* decode priority name */
949: pri = decode(buf, PriNames);
950: if (pri < 0) {
951: char xbuf[200];
952:
953: (void) sprintf(xbuf, "unknown priority name \"%s\"", buf);
954: logerror(xbuf);
955: return;
956: }
957:
958: /* scan facilities */
959: while (*p && !index("\t.;", *p)) {
960: int i;
961:
962: for (bp = buf; *p && !index("\t,;.", *p); )
963: *bp++ = *p++;
964: *bp = '\0';
965: if (*buf == '*')
966: for (i = 0; i < LOG_NFACILITIES; i++)
967: f->f_pmask[i] = pri;
968: else {
969: i = decode(buf, FacNames);
970: if (i < 0) {
971: char xbuf[200];
972:
973: (void) sprintf(xbuf, "unknown facility name \"%s\"", buf);
974: logerror(xbuf);
975: return;
976: }
977: f->f_pmask[i >> 3] = pri;
978: }
979: while (*p == ',' || *p == ' ')
980: p++;
981: }
982:
983: p = q;
984: }
985:
986: /* skip to action part */
987: while (*p == '\t')
988: p++;
989:
990: switch (*p)
991: {
992: case '@':
993: if (!InetInuse)
994: break;
995: (void) strcpy(f->f_un.f_forw.f_hname, ++p);
996: hp = gethostbyname(p);
997: if (hp == NULL) {
998: char buf[100];
999:
1000: (void) sprintf(buf, "unknown host %s", p);
1001: errno = 0;
1002: logerror(buf);
1003: break;
1004: }
1005: bzero((char *) &f->f_un.f_forw.f_addr,
1006: sizeof f->f_un.f_forw.f_addr);
1007: f->f_un.f_forw.f_addr.sin_family = AF_INET;
1008: f->f_un.f_forw.f_addr.sin_port = LogPort;
1009: bcopy(hp->h_addr, (char *) &f->f_un.f_forw.f_addr.sin_addr, hp->h_length);
1010: f->f_file = socket(AF_INET, SOCK_DGRAM, 0);
1011: if (f->f_file < 0) {
1012: logerror("socket");
1013: break;
1014: }
1015: f->f_type = F_FORW;
1016: break;
1017:
1018: case '/':
1019: (void) strcpy(f->f_un.f_fname, p);
1020: if ((f->f_file = open(p, O_WRONLY|O_APPEND)) < 0) {
1021: logerror(p);
1022: break;
1023: }
1024: if (isatty(f->f_file)) {
1025: f->f_type = F_TTY;
1026: untty();
1027: }
1028: else
1029: f->f_type = F_FILE;
1030: if (strcmp(p, ctty) == 0)
1031: f->f_type = F_CONSOLE;
1032: break;
1033:
1034: case '*':
1035: f->f_type = F_WALL;
1036: break;
1037:
1038: default:
1039: for (i = 0; i < MAXUNAMES && *p; i++) {
1040: for (q = p; *q && *q != ','; )
1041: q++;
1042: (void) strncpy(f->f_un.f_uname[i], p, UNAMESZ);
1043: if ((q - p) > UNAMESZ)
1044: f->f_un.f_uname[i][UNAMESZ] = '\0';
1045: else
1046: f->f_un.f_uname[i][q - p] = '\0';
1047: while (*q == ',' || *q == ' ')
1048: q++;
1049: p = q;
1050: }
1051: f->f_type = F_USERS;
1052: break;
1053: }
1054: }
1055:
1056:
1057: /*
1058: * Decode a symbolic name to a numeric value
1059: */
1060:
1061: decode(name, codetab)
1062: char *name;
1063: struct code *codetab;
1064: {
1065: register struct code *c;
1066: register char *p;
1067: char buf[40];
1068:
1069: if (isdigit(*name))
1070: return (atoi(name));
1071:
1072: (void) strcpy(buf, name);
1073: for (p = buf; *p; p++)
1074: if (isupper(*p))
1075: *p = tolower(*p);
1076: for (c = codetab; c->c_name; c++)
1077: if (!strcmp(buf, c->c_name))
1078: return (c->c_val);
1079:
1080: return (-1);
1081: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.