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