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