121362Sdist /* 233786Skarels * Copyright (c) 1983, 1988 Regents of the University of California. 333786Skarels * All rights reserved. 433786Skarels * 533786Skarels * Redistribution and use in source and binary forms are permitted 633786Skarels * provided that this notice is preserved and that due credit is given 733786Skarels * to the University of California at Berkeley. The name of the University 833786Skarels * may not be used to endorse or promote products derived from this 933786Skarels * software without specific prior written permission. This software 1033786Skarels * is provided ``as is'' without express or implied warranty. 1121362Sdist */ 1221362Sdist 1326602Sdonn #if defined(LIBC_SCCS) && !defined(lint) 14*34563Skarels static char sccsid[] = "@(#)syslog.c 5.15 (Berkeley) 05/31/88"; 1533786Skarels #endif /* LIBC_SCCS and not lint */ 1612742Ssam 1733786Skarels 1812742Ssam /* 1912742Ssam * SYSLOG -- print message on log file 2012742Ssam * 2112742Ssam * This routine looks a lot like printf, except that it 2212742Ssam * outputs to the log file instead of the standard output. 2316414Sralph * Also: 2416414Sralph * adds a timestamp, 2516414Sralph * prints the module name in front of the message, 2616414Sralph * has some other formatting types (or will sometime), 2716414Sralph * adds a newline on the end of the message. 2812742Ssam * 2916414Sralph * The output of this routine is intended to be read by /etc/syslogd. 3016943Sralph * 3116943Sralph * Author: Eric Allman 3216943Sralph * Modified to use UNIX domain IPC by Ralph Campbell 3312742Ssam */ 3416414Sralph 3512742Ssam #include <sys/types.h> 3612742Ssam #include <sys/socket.h> 3716414Sralph #include <sys/file.h> 3826870Skarels #include <sys/signal.h> 3926870Skarels #include <sys/syslog.h> 4012742Ssam #include <netdb.h> 4126870Skarels #include <strings.h> 4212742Ssam 4316414Sralph #define MAXLINE 1024 /* max message size */ 4416414Sralph #define NULL 0 /* manifest */ 4512742Ssam 4624846Seric #define IMPORTANT LOG_ERR 4717918Sralph 4816414Sralph static char logname[] = "/dev/log"; 4916414Sralph static char ctty[] = "/dev/console"; 5012742Ssam 5116414Sralph static int LogFile = -1; /* fd for log */ 52*34563Skarels static int connected; /* have done connect */ 5316414Sralph static int LogStat = 0; /* status bits, set by openlog() */ 5424846Seric static char *LogTag = "syslog"; /* string to tag the entry with */ 5524846Seric static int LogMask = 0xff; /* mask of priorities to be logged */ 5624846Seric static int LogFacility = LOG_USER; /* default facility code */ 5712742Ssam 5824846Seric static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */ 5916414Sralph 6012742Ssam extern int errno, sys_nerr; 6112742Ssam extern char *sys_errlist[]; 6212742Ssam 6312742Ssam syslog(pri, fmt, p0, p1, p2, p3, p4) 6412742Ssam int pri; 6512742Ssam char *fmt; 6612742Ssam { 6716414Sralph char buf[MAXLINE + 1], outline[MAXLINE + 1]; 6816414Sralph register char *b, *f, *o; 6916414Sralph register int c; 7016414Sralph long now; 7116943Sralph int pid, olderrno = errno; 7212742Ssam 7312742Ssam /* see if we should just throw out this message */ 74*34563Skarels if ((unsigned) LOG_FAC(pri) >= LOG_NFACILITIES || 75*34563Skarels LOG_MASK(LOG_PRI(pri)) == 0 || 7634392Skarels (pri &~ (LOG_PRIMASK|LOG_FACMASK)) != 0) 7712742Ssam return; 78*34563Skarels if (LogFile < 0 || !connected) 7925187Seric openlog(LogTag, LogStat | LOG_NDELAY, 0); 8024846Seric 8124846Seric /* set default facility if none specified */ 8224846Seric if ((pri & LOG_FACMASK) == 0) 8324846Seric pri |= LogFacility; 8424846Seric 8524846Seric /* build the message */ 8616414Sralph o = outline; 8732497Sbostic (void)sprintf(o, "<%d>", pri); 8816943Sralph o += strlen(o); 8924846Seric time(&now); 9032497Sbostic (void)sprintf(o, "%.15s ", ctime(&now) + 4); 9124846Seric o += strlen(o); 9216414Sralph if (LogTag) { 9316414Sralph strcpy(o, LogTag); 9416414Sralph o += strlen(o); 9516414Sralph } 9616414Sralph if (LogStat & LOG_PID) { 9732497Sbostic (void)sprintf(o, "[%d]", getpid()); 9816414Sralph o += strlen(o); 9916414Sralph } 10024846Seric if (LogTag) { 10124846Seric strcpy(o, ": "); 10224846Seric o += 2; 10324846Seric } 10412742Ssam 10516414Sralph b = buf; 10616414Sralph f = fmt; 10716414Sralph while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) { 10816414Sralph if (c != '%') { 10916414Sralph *b++ = c; 11016414Sralph continue; 11112742Ssam } 11216414Sralph if ((c = *f++) != 'm') { 11316414Sralph *b++ = '%'; 11416414Sralph *b++ = c; 11516414Sralph continue; 11612742Ssam } 11716943Sralph if ((unsigned)olderrno > sys_nerr) 11832497Sbostic (void)sprintf(b, "error %d", olderrno); 11912742Ssam else 12016943Sralph strcpy(b, sys_errlist[olderrno]); 12116414Sralph b += strlen(b); 12212742Ssam } 12316414Sralph *b++ = '\n'; 12416414Sralph *b = '\0'; 12532497Sbostic (void)sprintf(o, buf, p0, p1, p2, p3, p4); 12616414Sralph c = strlen(outline); 12716414Sralph if (c > MAXLINE) 12816414Sralph c = MAXLINE; 12924846Seric 13024846Seric /* output the message to the local logger */ 131*34563Skarels if (send(LogFile, outline, c, 0) >= 0) 13216414Sralph return; 13327343Skarels if (!(LogStat & LOG_CONS)) 13416414Sralph return; 13524846Seric 13624846Seric /* output the message to the console */ 13726508Skarels pid = vfork(); 13816414Sralph if (pid == -1) 13916414Sralph return; 14016414Sralph if (pid == 0) { 14127795Skarels int fd; 14227795Skarels 14324880Seric signal(SIGALRM, SIG_DFL); 14432303Sbostic sigsetmask(sigblock(0L) & ~sigmask(SIGALRM)); 14524880Seric alarm(5); 14627795Skarels fd = open(ctty, O_WRONLY); 14724880Seric alarm(0); 14817918Sralph strcat(o, "\r"); 14926870Skarels o = index(outline, '>') + 1; 15027795Skarels write(fd, o, c + 1 - (o - outline)); 15127795Skarels close(fd); 15227795Skarels _exit(0); 15316414Sralph } 15427343Skarels if (!(LogStat & LOG_NOWAIT)) 15527343Skarels while ((c = wait((int *)0)) > 0 && c != pid) 15627343Skarels ; 15712742Ssam } 15812742Ssam 15912742Ssam /* 16012742Ssam * OPENLOG -- open system log 16112742Ssam */ 16224846Seric 16324846Seric openlog(ident, logstat, logfac) 16412742Ssam char *ident; 16524846Seric int logstat, logfac; 16612742Ssam { 16724846Seric if (ident != NULL) 16824846Seric LogTag = ident; 16912742Ssam LogStat = logstat; 17033786Skarels if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) 17133786Skarels LogFacility = logfac; 172*34563Skarels if (LogFile == -1) { 173*34563Skarels SyslogAddr.sa_family = AF_UNIX; 174*34563Skarels strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data); 175*34563Skarels if (LogStat & LOG_NDELAY) { 176*34563Skarels LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); 177*34563Skarels fcntl(LogFile, F_SETFD, 1); 178*34563Skarels } 17917918Sralph } 180*34563Skarels if (LogFile != -1 && !connected && 181*34563Skarels connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) != -1) 182*34563Skarels connected = 1; 18312742Ssam } 18412742Ssam 18512742Ssam /* 18612742Ssam * CLOSELOG -- close the system log 18712742Ssam */ 18825187Seric 18912742Ssam closelog() 19012742Ssam { 19112742Ssam 19212742Ssam (void) close(LogFile); 19312742Ssam LogFile = -1; 194*34563Skarels connected = 0; 19512742Ssam } 19616414Sralph 19716414Sralph /* 19816414Sralph * SETLOGMASK -- set the log mask level 19916414Sralph */ 20017526Sralph setlogmask(pmask) 20117526Sralph int pmask; 20216414Sralph { 20317526Sralph int omask; 20416414Sralph 20517526Sralph omask = LogMask; 20617526Sralph if (pmask != 0) 20717526Sralph LogMask = pmask; 20817526Sralph return (omask); 20916414Sralph } 210