|
|
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.