📄 syslog.c
字号:
*/shutdown(){ extern die(); logmsg(LOG_CRIT, "syslog: shutdown within 30 seconds\n"); ShutDown++; signal(SIGALRM, die); alarm(30); signal(SIGTERM, die); if (Debug) signal(SIGINT, die);}/*** DIE -- really die.**** Parameters:** none**** Returns:** never**** Side Effects:** Syslog dies.**** Requires:** exit (sys)**** Called By:** alarm clock (signal 14)*/die(){ alarm(0); logmsg(LOG_CRIT, "syslog: down\n"); sleep(2); /* wait for output to drain */# ifndef LOG_IPC if (!Debug) unlink("/dev/log");# endif LOG_IPC sync(); /* This sync is ok. */ exit(0);}/*** STAMPED -- tell if line is already time stamped.**** Accepts time stamps of the form "Sep 13 00:15:17".** Currently just looks for blanks and colons.**** Parameters:** l -- the line to check.**** Returns:** nonzero -- if the line is time stamped.** zero -- otherwise.**** Side Effects:** none.*/stamped(l)register char *l;{ register int i; /* timestamps are at least 15 bytes long */ for (i = 0; i < 15; i++) if (l[i] == '\0') return (0); /* and they have blanks & colons in well-known places */ if (l[3] != ' ' || l[6] != ' ' || l[9] != ':' || l[12] != ':') return (0); return (1);}/*** LOGMSG -- log a message to the outputs**** Arranges to get the message to the correct places** based on the priority of the message. A timestamp** is prepended to the message if one does not already** exist.**** Parameters:** pri -- the message priority.** msg -- the message to be logged.**** Returns:** none**** Side Effects:** possibly messages to all users, or just specific** users.*/char buf[MAXLINE+2];logmsg(pri, msg) int pri; char *msg;{ register char *m; register char *p; register struct filed *f; register int l; register int i; auto int st; auto long now; extern char *ctime(); extern int errno; p = buf; l = MAXLINE; /* output a time stamp if one is not already there */ time(&now); if (!stamped(msg)) { m = &ctime(&now)[4]; for (i = 16; i > 0; i--) *p++ = *m++; l -= 16; } /* find the end of the message */ for (m = msg; *m != '\0' &&l -- >= 0; ) *p++ = *m++; if (*--m != '\n') *p++ = '\n'; /* log the message to the particular outputs */ for (i = 0; i < NLOGS; i++) { f = &Files[i]; /* 0002 - puivax!ed */ /* if it isn't a tty and the file descriptor is NULL do nothing */ /* if it is a tty then keep going, ttys should always be closed */ if ( ! f->f_tty && f->f_file == NULL) continue; if (pri < 0) { if (!f->f_mark || f->f_time + MarkIntvl*60 > now) continue; } else if (f->f_pmask < pri) continue; /* 0002 - puivax!ed moved from 10 lines above */ /* we've decided to really write this message to the file so... */ /* ttys are opened and closed for each write 0001 */ if (f->f_tty && f->f_file == NULL) if ((f->f_file = fopen(f->f_name, "a")) == NULL) continue; fseek(f->f_file, 0L, 2); errno = 0; fwrite(buf, p - buf, 1, f->f_file); if (f->f_tty) fwrite("\r", 1, 1, f->f_file); f->f_time = now; fflush(f->f_file); if (ferror(f->f_file)) { char namebuf[40]; fclose(f->f_file); f->f_file = NULL; f->f_tty = 0; /* otherwise would reopen */ sprintf(namebuf, "write %s", f->f_name); logerror(namebuf); } if (f->f_tty) { fclose(f->f_file); f->f_file = NULL; } } /* let's be paranoid.... *//* aps. * sync(); */ /* ** Output alert and subalert priority messages to terminals. ** ** We double fork here so that we can continue. Our ** child will fork again and die; we wait for him. ** Then process one inherits our grandchildren, we ** can run off and have a good time. Our grandchild ** actually tries to do the writing (by calling ** wallmsg). ** ** Anything go wrong? -- just give up. */ if (pri <= LOG_SALERT && pri > 0) { if (fork() == 0) { if (fork() == 0) { wallmsg(pri == LOG_ALERT, buf, p - buf); exit(0); } else exit(0); } else while (wait(&st) >= 0) continue; }}/*** INIT -- Initialize syslog from configuration table**** The configuration table consists of a series of lines** broken into two sections by a blank line. The first** section gives a list of files to log on. The first** character is a digit which is the priority mask for** that file. If the second digit is an asterisk, then** syslog arranges for something to be printed every fifteen** minutes (even if only a null line), so that crashes and** other events can be localized. The rest of the line is** the pathname of the log file. The second section is** a list of user names; these people are all notified** when subalert messages occur (if they are logged on).**** The configuration table will be reread by this routine** if a signal 1 occurs; for that reason, it is tricky** about not re-opening files and closing files it will** not be using.**** Parameters:** none**** Returns:** none**** Side Effects:** 'Files' and 'Susers' are (re)initialized.*/init(){ register int i; register FILE *cf; char cline[40]; register struct filed *f; register char *p; int mark; int pmask; dprintf("init\n"); /* ignore interrupts during this routine */ signal(SIGHUP, SIG_IGN); logmsg(LOG_INFO, "reinitializing\n"); /* open the configuration file */ if ((cf = fopen(ConfFile, "r")) == NULL) { dprintf("cannot open %s\n", ConfFile); return; } /* ** Close all open files. */ for (f = Files; f < &Files[NLOGS]; f++) { if (f->f_file != NULL) fclose(f->f_file); f->f_file = NULL; } /* ** Foreach line in the conf table, open that file. */ f = Files; while (fgets(cline, sizeof cline, cf) != NULL) { dprintf("F: got line >%s<\n", cline, 0); /* check for end-of-section */ if (cline[0] == '\n') break; /* strip off possible newline character */ for (p = cline; *p != '\0' && *p != '\n'; p++) continue; *p = '\0'; /* extract priority mask and mark flag */ p = cline; mark = FALSE; pmask = *p++ - '0'; if (*p == '*') { p++; mark = TRUE; } /* insure that it is null-terminated */ p[sizeof Files[0].f_name - 1] = '\0'; if (f >= &Files[NLOGS]) continue; /* mark entry as used and update flags */ strcpy(f->f_name, p); f->f_file = fopen(p, "a"); f->f_time = 0; f->f_pmask = pmask; f->f_mark = mark; f->f_tty = (f->f_file ? isatty(fileno(f->f_file)) : 0); /* * tty lines have to be opened and closed for each message. * * 0001 */ if (f->f_tty) { fclose(f->f_file); f->f_file = NULL; } dprintf("File %s pmask %d mark %d tty %d\n", p, pmask, mark, f->f_tty); f++; } /* ** Read the list of users. ** ** Anyone in this list is informed directly if s/he ** is logged in when a "subalert" or higher priority ** message comes through. ** ** Out with the old order, in with the new. */ for (i = 0; i < NSUSERS && fgets(cline, sizeof cline, cf) != NULL; i++) { /* strip off newline */ for (p = cline; *p != '\0' && *p != '\n'; p++) continue; *p = '\0'; cline[8] = '\0'; strcpy(Susers[i], cline, 8); } /* zero the rest of the old superusers */ for (; i < NSUSERS; i++) Susers[i][0] = '\0'; /* close the configuration file */ fclose(cf); logmsg(LOG_INFO, "syslog restart\n"); /* arrange for signal 1 to reconfigure */ signal(SIGHUP, init);}/*** WALLMSG -- Write a message to the world at large**** This writes the specified message to either the entire** world, or at least a list of approved users.**** It scans the utmp file. For each user logged in, it** checks to see if the user is on the approved list, or if** this is an "alert" priority message. In either case,** it opens a line to that typewriter (unless mesg permission** is denied) and outputs the message to that terminal.**** Parameters:** toall -- if non-zero, writes the message to everyone.** msg -- the message to write.** len -- the length of the message.**** Returns:** none**** Side Effects:** none**** Requires:** open(sys)** read(sys)** write(sys)** fstat(sys)** strcmp(sys)** fork(sys)** sleep(sys)** exit(sys)** close(sys)**** Called By:** logmsg*/wallmsg(toall, msg, len) int toall; char *msg; int len;{ struct utmp ut; register int i; register char *p; int uf; struct stat statbuf; auto long t; extern char *ctime(); char sbuf[1024];#ifdef LOG_IPC extern char *gethostname(); char hbuf[32]; auto int hlen;#endif LOG_IPC /* open the user login file */ uf = open("/etc/utmp", 0); if (uf < 0) return; /* scan the user login file */ while (read(uf, &ut, sizeof ut) == sizeof ut) { /* is this slot used? */ if (ut.ut_name[0] == '\0') continue; /* if not "alert", check if this user is super */ if (!toall) { for (i = 0; i < NSUSERS; i++) { if (namecheck(Susers[i], ut.ut_name)) break; } if (i >= NSUSERS) { /* nope, just a serf */ continue; } } /* fork so that the open can't hang us */ if (fork() != 0) continue; sleep(1); /* compute the device name */# ifdef V6 p = "/dev/ttyx"; p[8] = ut.ut_tty;# else p = "/dev/12345678"; strcpyn(&p[5], ut.ut_line, 8);# endif /* open the terminal */ i = open(p, 1); if (i < 0) exit(1); /* does he have write permission? */ if (fstat(i, &statbuf) < 0 || (statbuf.st_mode & 02) == 0) { /* no, just pass him by */ dprintf("Drop user, mode=%o\n", statbuf.st_mode, 0); close(i); exit(0); } /* yes, output the message */ time(&t); strcpy(sbuf, "\r\n\007Broadcast message from ");#ifdef LOG_IPC strcat(sbuf, "syslog@"); hlen = sizeof hbuf; gethostname(hbuf, &hlen); strcat(sbuf, hbuf);#else LOG_IPC strcat(sbuf, sysname); strcat(sbuf, "!syslog");#endif LOG_IPC strcat(sbuf, " at "); strncat(sbuf, ctime(&t), 24); strcat(sbuf, "...\r\n"); write(i, sbuf, strlen(sbuf)); p = sbuf; while (len-- > 0) { *msg &= 0177; if (iscntrl(*msg)) { *p++ = '^'; *p++ = *msg++ ^ 0100; } else *p++ = *msg++; } strcpy(p, "\r\n"); write(i, sbuf, strlen(sbuf)); /* all finished! go away */ exit(0); } /* close the user login file */ close(uf);}/*** CHECKNAME -- Do an equality comparison on names.**** Does right blank padding.**** Parameters:** a, b -- pointers to the names to check.**** Returns:** 1 if equal** 0 otherwise.**** Side Effects:** none**** Requires:** none**** Called By:** wallmsg*/namecheck(a, b)register char *a, *b;{ register int i; for (i = 0; i < 8; i++) { if (*a != *b) { if (!((*a == ' ' && *b == '\0') || (*a == '\0' && *b == ' '))) return (0); } if (*a != ' ' && *a != '\0') a++; if (*b != ' ' && *b != '\0') b++; } return (1);}/*** DOMARK -- Make sure every marked file gets output every 15 minutes**** Just calls "logmsg" with a negative priority every time it** gets called.**** Algorithm:** create timestamp.** call logmsg.**** Parameters:** none**** Returns:** none**** Side Effects:** sets the alarm clock to call itself after MarkIntvl** minutes.**** Requires:** logmsg**** Called By:** system alarm clock.** init*/domark(){ auto long t; extern char *ctime(); register char *p; register char *q; char buf[40]; alarm(0); dprintf("domark\n"); time(&t); q = buf; for (p = " --- MARK --- "; (*q++ = *p++) != '\0'; ) continue; q--; for (p = ctime(&t); (*q++ = *p++) != '\0'; ) continue; logmsg(-1, buf); signal(SIGALRM, domark); alarm(MarkIntvl*60);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -