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.4 (Berkeley) 10/13/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 <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 = fork(); 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 write(LogFile, outline, c+1); 139 close(LogFile); 140 exit(0); 141 } 142 while ((c = wait((int *)0)) > 0 && c != pid) 143 ; 144 } 145 146 /* 147 * OPENLOG -- open system log 148 */ 149 150 openlog(ident, logstat, logfac) 151 char *ident; 152 int logstat, logfac; 153 { 154 if (ident != NULL) 155 LogTag = ident; 156 LogStat = logstat; 157 if (logfac != 0) 158 LogFacility = logfac & LOG_FACMASK; 159 if (LogFile >= 0) 160 return; 161 SyslogAddr.sa_family = AF_UNIX; 162 strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data); 163 if (LogStat & LOG_NDELAY) { 164 LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); 165 fcntl(LogFile, F_SETFD, 1); 166 } 167 } 168 169 /* 170 * CLOSELOG -- close the system log 171 */ 172 173 closelog() 174 { 175 176 (void) close(LogFile); 177 LogFile = -1; 178 } 179 180 /* 181 * SETLOGMASK -- set the log mask level 182 */ 183 setlogmask(pmask) 184 int pmask; 185 { 186 int omask; 187 188 omask = LogMask; 189 if (pmask != 0) 190 LogMask = pmask; 191 return (omask); 192 } 193