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.5 (Berkeley) 03/08/86"; 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 <signal.h> 32 #include <syslog.h> 33 #include <netdb.h> 34 35 #define MAXLINE 1024 /* max message size */ 36 #define NULL 0 /* manifest */ 37 38 #define PRIMASK(p) (1 << ((p) & LOG_PRIMASK)) 39 #define PRIFAC(p) (((p) & LOG_FACMASK) >> 3) 40 #define IMPORTANT LOG_ERR 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 = "syslog"; /* string to tag the entry with */ 48 static int LogMask = 0xff; /* mask of priorities to be logged */ 49 static int LogFacility = LOG_USER; /* default facility code */ 50 51 static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */ 52 53 extern int errno, sys_nerr; 54 extern char *sys_errlist[]; 55 56 syslog(pri, fmt, p0, p1, p2, p3, p4) 57 int pri; 58 char *fmt; 59 { 60 char buf[MAXLINE + 1], outline[MAXLINE + 1]; 61 register char *b, *f, *o; 62 register int c; 63 long now; 64 int pid, olderrno = errno; 65 66 /* see if we should just throw out this message */ 67 if (pri <= 0 || PRIFAC(pri) >= LOG_NFACILITIES || (PRIMASK(pri) & LogMask) == 0) 68 return; 69 if (LogFile < 0) 70 openlog(LogTag, LogStat | LOG_NDELAY, 0); 71 72 /* set default facility if none specified */ 73 if ((pri & LOG_FACMASK) == 0) 74 pri |= LogFacility; 75 76 /* build the message */ 77 o = outline; 78 sprintf(o, "<%d>", pri); 79 o += strlen(o); 80 time(&now); 81 sprintf(o, "%.15s ", ctime(&now) + 4); 82 o += strlen(o); 83 if (LogTag) { 84 strcpy(o, LogTag); 85 o += strlen(o); 86 } 87 if (LogStat & LOG_PID) { 88 sprintf(o, "[%d]", getpid()); 89 o += strlen(o); 90 } 91 if (LogTag) { 92 strcpy(o, ": "); 93 o += 2; 94 } 95 96 b = buf; 97 f = fmt; 98 while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) { 99 if (c != '%') { 100 *b++ = c; 101 continue; 102 } 103 if ((c = *f++) != 'm') { 104 *b++ = '%'; 105 *b++ = c; 106 continue; 107 } 108 if ((unsigned)olderrno > sys_nerr) 109 sprintf(b, "error %d", olderrno); 110 else 111 strcpy(b, sys_errlist[olderrno]); 112 b += strlen(b); 113 } 114 *b++ = '\n'; 115 *b = '\0'; 116 sprintf(o, buf, p0, p1, p2, p3, p4); 117 c = strlen(outline); 118 if (c > MAXLINE) 119 c = MAXLINE; 120 121 /* output the message to the local logger */ 122 if (sendto(LogFile, outline, c, 0, &SyslogAddr, sizeof SyslogAddr) >= 0) 123 return; 124 if (!(LogStat & LOG_CONS) && (pri & LOG_PRIMASK) <= LOG_ERR) 125 return; 126 127 /* output the message to the console */ 128 pid = vfork(); 129 if (pid == -1) 130 return; 131 if (pid == 0) { 132 signal(SIGALRM, SIG_DFL); 133 sigsetmask(sigblock(0) & ~sigmask(SIGALRM)); 134 alarm(5); 135 LogFile = open(ctty, O_WRONLY); 136 alarm(0); 137 strcat(o, "\r"); 138 o = outline + index(outline, '>') + 1; 139 write(LogFile, outline, c + 1 - (o - outline)); 140 close(LogFile); 141 exit(0); 142 } 143 while ((c = wait((int *)0)) > 0 && c != pid) 144 ; 145 } 146 147 /* 148 * OPENLOG -- open system log 149 */ 150 151 openlog(ident, logstat, logfac) 152 char *ident; 153 int logstat, logfac; 154 { 155 if (ident != NULL) 156 LogTag = ident; 157 LogStat = logstat; 158 if (logfac != 0) 159 LogFacility = logfac & LOG_FACMASK; 160 if (LogFile >= 0) 161 return; 162 SyslogAddr.sa_family = AF_UNIX; 163 strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data); 164 if (LogStat & LOG_NDELAY) { 165 LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); 166 fcntl(LogFile, F_SETFD, 1); 167 } 168 } 169 170 /* 171 * CLOSELOG -- close the system log 172 */ 173 174 closelog() 175 { 176 177 (void) close(LogFile); 178 LogFile = -1; 179 } 180 181 /* 182 * SETLOGMASK -- set the log mask level 183 */ 184 setlogmask(pmask) 185 int pmask; 186 { 187 int omask; 188 189 omask = LogMask; 190 if (pmask != 0) 191 LogMask = pmask; 192 return (omask); 193 } 194