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: }