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