1 /* 2 * Copyright (c) 1983, 1988 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that this notice is preserved and that due credit is given 7 * to the University of California at Berkeley. The name of the University 8 * may not be used to endorse or promote products derived from this 9 * software without specific prior written permission. This software 10 * is provided ``as is'' without express or implied warranty. 11 */ 12 13 #if defined(LIBC_SCCS) && !defined(lint) 14 static char sccsid[] = "@(#)syslog.c 5.13 (Berkeley) 03/24/88"; 15 #endif /* LIBC_SCCS and not lint */ 16 17 18 /* 19 * SYSLOG -- print message on log file 20 * 21 * This routine looks a lot like printf, except that it 22 * outputs to the log file instead of the standard output. 23 * Also: 24 * adds a timestamp, 25 * prints the module name in front of the message, 26 * has some other formatting types (or will sometime), 27 * adds a newline on the end of the message. 28 * 29 * The output of this routine is intended to be read by /etc/syslogd. 30 * 31 * Author: Eric Allman 32 * Modified to use UNIX domain IPC by Ralph Campbell 33 */ 34 35 #include <sys/types.h> 36 #include <sys/socket.h> 37 #include <sys/file.h> 38 #include <sys/signal.h> 39 #include <sys/syslog.h> 40 #include <netdb.h> 41 #include <strings.h> 42 43 #define MAXLINE 1024 /* max message size */ 44 #define NULL 0 /* manifest */ 45 46 #define PRIFAC(p) (((p) & LOG_FACMASK) >> 3) 47 /* XXX should be in <syslog.h> */ 48 #define IMPORTANT LOG_ERR 49 50 static char logname[] = "/dev/log"; 51 static char ctty[] = "/dev/console"; 52 53 static int LogFile = -1; /* fd for log */ 54 static int LogStat = 0; /* status bits, set by openlog() */ 55 static char *LogTag = "syslog"; /* string to tag the entry with */ 56 static int LogMask = 0xff; /* mask of priorities to be logged */ 57 static int LogFacility = LOG_USER; /* default facility code */ 58 59 static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */ 60 61 extern int errno, sys_nerr; 62 extern char *sys_errlist[]; 63 64 syslog(pri, fmt, p0, p1, p2, p3, p4) 65 int pri; 66 char *fmt; 67 { 68 char buf[MAXLINE + 1], outline[MAXLINE + 1]; 69 register char *b, *f, *o; 70 register int c; 71 long now; 72 int pid, olderrno = errno; 73 74 /* see if we should just throw out this message */ 75 if ((unsigned) PRIFAC(pri) >= LOG_NFACILITIES || 76 (LOG_MASK(pri & LOG_PRIMASK) & LogMask) == 0 || 77 (pri &~ (LOG_PRIMASK|LOG_PRIMASK)) != 0) 78 return; 79 if (LogFile < 0) 80 openlog(LogTag, LogStat | LOG_NDELAY, 0); 81 82 /* set default facility if none specified */ 83 if ((pri & LOG_FACMASK) == 0) 84 pri |= LogFacility; 85 86 /* build the message */ 87 o = outline; 88 (void)sprintf(o, "<%d>", pri); 89 o += strlen(o); 90 time(&now); 91 (void)sprintf(o, "%.15s ", ctime(&now) + 4); 92 o += strlen(o); 93 if (LogTag) { 94 strcpy(o, LogTag); 95 o += strlen(o); 96 } 97 if (LogStat & LOG_PID) { 98 (void)sprintf(o, "[%d]", getpid()); 99 o += strlen(o); 100 } 101 if (LogTag) { 102 strcpy(o, ": "); 103 o += 2; 104 } 105 106 b = buf; 107 f = fmt; 108 while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) { 109 if (c != '%') { 110 *b++ = c; 111 continue; 112 } 113 if ((c = *f++) != 'm') { 114 *b++ = '%'; 115 *b++ = c; 116 continue; 117 } 118 if ((unsigned)olderrno > sys_nerr) 119 (void)sprintf(b, "error %d", olderrno); 120 else 121 strcpy(b, sys_errlist[olderrno]); 122 b += strlen(b); 123 } 124 *b++ = '\n'; 125 *b = '\0'; 126 (void)sprintf(o, buf, p0, p1, p2, p3, p4); 127 c = strlen(outline); 128 if (c > MAXLINE) 129 c = MAXLINE; 130 131 /* output the message to the local logger */ 132 if (sendto(LogFile, outline, c, 0, &SyslogAddr, sizeof SyslogAddr) >= 0) 133 return; 134 if (!(LogStat & LOG_CONS)) 135 return; 136 137 /* output the message to the console */ 138 pid = vfork(); 139 if (pid == -1) 140 return; 141 if (pid == 0) { 142 int fd; 143 144 signal(SIGALRM, SIG_DFL); 145 sigsetmask(sigblock(0L) & ~sigmask(SIGALRM)); 146 alarm(5); 147 fd = open(ctty, O_WRONLY); 148 alarm(0); 149 strcat(o, "\r"); 150 o = index(outline, '>') + 1; 151 write(fd, o, c + 1 - (o - outline)); 152 close(fd); 153 _exit(0); 154 } 155 if (!(LogStat & LOG_NOWAIT)) 156 while ((c = wait((int *)0)) > 0 && c != pid) 157 ; 158 } 159 160 /* 161 * OPENLOG -- open system log 162 */ 163 164 openlog(ident, logstat, logfac) 165 char *ident; 166 int logstat, logfac; 167 { 168 if (ident != NULL) 169 LogTag = ident; 170 LogStat = logstat; 171 if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) 172 LogFacility = logfac; 173 if (LogFile >= 0) 174 return; 175 SyslogAddr.sa_family = AF_UNIX; 176 strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data); 177 if (LogStat & LOG_NDELAY) { 178 LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); 179 fcntl(LogFile, F_SETFD, 1); 180 } 181 } 182 183 /* 184 * CLOSELOG -- close the system log 185 */ 186 187 closelog() 188 { 189 190 (void) close(LogFile); 191 LogFile = -1; 192 } 193 194 /* 195 * SETLOGMASK -- set the log mask level 196 */ 197 setlogmask(pmask) 198 int pmask; 199 { 200 int omask; 201 202 omask = LogMask; 203 if (pmask != 0) 204 LogMask = pmask; 205 return (omask); 206 } 207