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 static char sccsid[] = "@(#)syslog.c 5.1 (Berkeley) 05/30/85"; 9 #endif not lint 10 11 /* 12 * SYSLOG -- print message on log file 13 * 14 * This routine looks a lot like printf, except that it 15 * outputs to the log file instead of the standard output. 16 * Also: 17 * adds a timestamp, 18 * prints the module name in front of the message, 19 * has some other formatting types (or will sometime), 20 * adds a newline on the end of the message. 21 * 22 * The output of this routine is intended to be read by /etc/syslogd. 23 * 24 * Author: Eric Allman 25 * Modified to use UNIX domain IPC by Ralph Campbell 26 */ 27 28 #include <sys/types.h> 29 #include <sys/socket.h> 30 #include <sys/file.h> 31 #include <syslog.h> 32 #include <netdb.h> 33 34 #define MAXLINE 1024 /* max message size */ 35 #define NULL 0 /* manifest */ 36 37 #define mask(p) (1 << (p)) 38 #define IMPORTANT (mask(KERN_EMERG)|mask(KERN_ALERT)|mask(KERN_ERR)|mask(KERN_FAIL)\ 39 |mask(KERN_RECOV)|mask(KERN_INFO)|mask(LOG_EMERG)|mask(LOG_ALERT)\ 40 |mask(LOG_CRIT)|mask(LOG_ERR)|mask(LOG_FAIL)) 41 42 static char logname[] = "/dev/log"; 43 static char ctty[] = "/dev/console"; 44 45 static int LogFile = -1; /* fd for log */ 46 static int LogStat = 0; /* status bits, set by openlog() */ 47 static char *LogTag = NULL; /* string to tag the entry with */ 48 /* mask of priorities to be logged */ 49 static int LogMask = ~(mask(KERN_EMERG)|mask(KERN_ALERT)|mask(KERN_ERR)| 50 mask(KERN_FAIL)|mask(KERN_RECOV)|mask(KERN_INFO)); 51 52 static struct sockaddr SyslogAddr; 53 54 extern int errno, sys_nerr; 55 extern char *sys_errlist[]; 56 57 syslog(pri, fmt, p0, p1, p2, p3, p4) 58 int pri; 59 char *fmt; 60 { 61 char buf[MAXLINE + 1], outline[MAXLINE + 1]; 62 register char *b, *f, *o; 63 register int c; 64 long now; 65 int pid, olderrno = errno; 66 67 /* see if we should just throw out this message */ 68 if (pri <= 0 || pri >= 32 || (mask(pri) & LogMask) == 0) 69 return; 70 if (LogFile < 0) 71 openlog(LogTag, LogStat & ~LOG_ODELAY, 0); 72 o = outline; 73 sprintf(o, "<%d>", pri); 74 o += strlen(o); 75 if (LogTag) { 76 strcpy(o, LogTag); 77 o += strlen(o); 78 } 79 if (LogStat & LOG_PID) { 80 sprintf(o, "[%d]", getpid()); 81 o += strlen(o); 82 } 83 time(&now); 84 sprintf(o, ": %.15s-- ", ctime(&now) + 4); 85 o += strlen(o); 86 87 b = buf; 88 f = fmt; 89 while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) { 90 if (c != '%') { 91 *b++ = c; 92 continue; 93 } 94 if ((c = *f++) != 'm') { 95 *b++ = '%'; 96 *b++ = c; 97 continue; 98 } 99 if ((unsigned)olderrno > sys_nerr) 100 sprintf(b, "error %d", olderrno); 101 else 102 strcpy(b, sys_errlist[olderrno]); 103 b += strlen(b); 104 } 105 *b++ = '\n'; 106 *b = '\0'; 107 sprintf(o, buf, p0, p1, p2, p3, p4); 108 c = strlen(outline); 109 if (c > MAXLINE) 110 c = MAXLINE; 111 if (sendto(LogFile, outline, c, 0, &SyslogAddr, sizeof SyslogAddr) >= 0) 112 return; 113 if (!(LogStat & LOG_CONS) && !(mask(pri) & IMPORTANT)) 114 return; 115 pid = fork(); 116 if (pid == -1) 117 return; 118 if (pid == 0) { 119 LogFile = open(ctty, O_RDWR); 120 strcat(o, "\r"); 121 write(LogFile, outline, c+1); 122 close(LogFile); 123 exit(0); 124 } 125 while ((c = wait((int *)0)) > 0 && c != pid) 126 ; 127 } 128 129 /* 130 * OPENLOG -- open system log 131 */ 132 openlog(ident, logstat, logmask) 133 char *ident; 134 int logstat, logmask; 135 { 136 137 LogTag = (ident != NULL) ? ident : "syslog"; 138 LogStat = logstat; 139 if (logmask != 0) 140 LogMask = logmask; 141 if (LogFile >= 0) 142 return; 143 SyslogAddr.sa_family = AF_UNIX; 144 strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data); 145 if (!(LogStat & LOG_ODELAY)) { 146 LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); 147 fcntl(LogFile, F_SETFD, 1); 148 } 149 } 150 151 /* 152 * CLOSELOG -- close the system log 153 */ 154 closelog() 155 { 156 157 (void) close(LogFile); 158 LogFile = -1; 159 } 160 161 /* 162 * SETLOGMASK -- set the log mask level 163 */ 164 setlogmask(pmask) 165 int pmask; 166 { 167 int omask; 168 169 omask = LogMask; 170 if (pmask != 0) 171 LogMask = pmask; 172 return (omask); 173 } 174