121362Sdist /* 233786Skarels * Copyright (c) 1983, 1988 Regents of the University of California. 333786Skarels * All rights reserved. 433786Skarels * 5*42626Sbostic * %sccs.include.redist.c% 621362Sdist */ 721362Sdist 826602Sdonn #if defined(LIBC_SCCS) && !defined(lint) 9*42626Sbostic static char sccsid[] = "@(#)syslog.c 5.27 (Berkeley) 06/01/90"; 1033786Skarels #endif /* LIBC_SCCS and not lint */ 1112742Ssam 1212742Ssam /* 1312742Ssam * SYSLOG -- print message on log file 1412742Ssam * 1536440Sbostic * This routine looks a lot like printf, except that it outputs to the 1636440Sbostic * log file instead of the standard output. Also: 1716414Sralph * adds a timestamp, 1816414Sralph * prints the module name in front of the message, 1916414Sralph * has some other formatting types (or will sometime), 2016414Sralph * adds a newline on the end of the message. 2112742Ssam * 2236440Sbostic * The output of this routine is intended to be read by syslogd(8). 2316943Sralph * 2416943Sralph * Author: Eric Allman 2516943Sralph * Modified to use UNIX domain IPC by Ralph Campbell 2612742Ssam */ 2716414Sralph 2812742Ssam #include <sys/types.h> 2912742Ssam #include <sys/socket.h> 3016414Sralph #include <sys/file.h> 3126870Skarels #include <sys/signal.h> 3226870Skarels #include <sys/syslog.h> 3336792Sbostic #include <sys/uio.h> 3438557Sbostic #include <sys/wait.h> 3512742Ssam #include <netdb.h> 3642025Sbostic #include <string.h> 3736442Sbostic #include <varargs.h> 3838557Sbostic #include <paths.h> 3936440Sbostic #include <stdio.h> 4012742Ssam 4138557Sbostic #define _PATH_LOGNAME "/dev/log" 4212742Ssam 4316414Sralph static int LogFile = -1; /* fd for log */ 4434563Skarels static int connected; /* have done connect */ 4536440Sbostic static int LogStat = 0; /* status bits, set by openlog() */ 4624846Seric static char *LogTag = "syslog"; /* string to tag the entry with */ 4724846Seric static int LogFacility = LOG_USER; /* default facility code */ 4812742Ssam 4936440Sbostic syslog(pri, fmt, args) 5036440Sbostic int pri, args; 5112742Ssam char *fmt; 5212742Ssam { 5336442Sbostic vsyslog(pri, fmt, &args); 5436442Sbostic } 5536442Sbostic 5636442Sbostic vsyslog(pri, fmt, ap) 5736442Sbostic int pri; 5836443Sbostic register char *fmt; 5936442Sbostic va_list ap; 6036442Sbostic { 6136443Sbostic extern int errno; 6236440Sbostic register int cnt; 6336440Sbostic register char *p; 6436440Sbostic time_t now, time(); 6538567Sbostic int fd, saved_errno; 6636792Sbostic char tbuf[2048], fmt_cpy[1024], *stdp, *ctime(); 6712742Ssam 6836443Sbostic saved_errno = errno; 6936443Sbostic 7012742Ssam /* see if we should just throw out this message */ 7139428Sbostic if (!LOG_MASK(LOG_PRI(pri)) || (pri &~ (LOG_PRIMASK|LOG_FACMASK))) 7212742Ssam return; 7334563Skarels if (LogFile < 0 || !connected) 7425187Seric openlog(LogTag, LogStat | LOG_NDELAY, 0); 7524846Seric 7624846Seric /* set default facility if none specified */ 7724846Seric if ((pri & LOG_FACMASK) == 0) 7824846Seric pri |= LogFacility; 7924846Seric 8024846Seric /* build the message */ 8136440Sbostic (void)time(&now); 8236440Sbostic (void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4); 8336440Sbostic for (p = tbuf; *p; ++p); 8436792Sbostic if (LogStat & LOG_PERROR) 8536792Sbostic stdp = p; 8616414Sralph if (LogTag) { 8736440Sbostic (void)strcpy(p, LogTag); 8836440Sbostic for (; *p; ++p); 8916414Sralph } 9016414Sralph if (LogStat & LOG_PID) { 9136440Sbostic (void)sprintf(p, "[%d]", getpid()); 9236440Sbostic for (; *p; ++p); 9316414Sralph } 9424846Seric if (LogTag) { 9536440Sbostic *p++ = ':'; 9636440Sbostic *p++ = ' '; 9724846Seric } 9812742Ssam 9936443Sbostic /* substitute error message for %m */ 10036443Sbostic { 10136443Sbostic register char ch, *t1, *t2; 10236443Sbostic char *strerror(); 10324846Seric 10436443Sbostic for (t1 = fmt_cpy; ch = *fmt; ++fmt) 10536443Sbostic if (ch == '%' && fmt[1] == 'm') { 10636443Sbostic ++fmt; 10736443Sbostic for (t2 = strerror(saved_errno); 10836443Sbostic *t1 = *t2++; ++t1); 10936443Sbostic } 11036443Sbostic else 11136443Sbostic *t1++ = ch; 11236583Sbostic *t1 = '\0'; 11336443Sbostic } 11436443Sbostic 11536443Sbostic (void)vsprintf(p, fmt_cpy, ap); 11636443Sbostic 11736792Sbostic cnt = strlen(tbuf); 11836792Sbostic 11936792Sbostic /* output to stderr if requested */ 12036792Sbostic if (LogStat & LOG_PERROR) { 12136792Sbostic struct iovec iov[2]; 12236792Sbostic register struct iovec *v = iov; 12336792Sbostic 12436792Sbostic v->iov_base = stdp; 12536792Sbostic v->iov_len = cnt - (stdp - tbuf); 12636792Sbostic ++v; 12736792Sbostic v->iov_base = "\n"; 12836792Sbostic v->iov_len = 1; 12936792Sbostic (void)writev(2, iov, 2); 13036792Sbostic } 13136792Sbostic 13224846Seric /* output the message to the local logger */ 13338557Sbostic if (send(LogFile, tbuf, cnt, 0) >= 0 || !(LogStat&LOG_CONS)) 13416414Sralph return; 13524846Seric 13638567Sbostic /* 13738567Sbostic * output the message to the console; don't worry about 13838567Sbostic * blocking, if console blocks everything will. 13938567Sbostic */ 14038567Sbostic if ((fd = open(_PATH_CONSOLE, O_WRONLY, 0)) < 0) 14116414Sralph return; 14238760Sbostic (void)strcat(tbuf, "\r\n"); 14338567Sbostic p = index(tbuf, '>') + 1; 14438567Sbostic (void)write(fd, p, cnt + 1 - (p - tbuf)); 14538567Sbostic (void)close(fd); 14612742Ssam } 14712742Ssam 14836440Sbostic static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */ 14912742Ssam /* 15012742Ssam * OPENLOG -- open system log 15112742Ssam */ 15224846Seric openlog(ident, logstat, logfac) 15312742Ssam char *ident; 15424846Seric int logstat, logfac; 15512742Ssam { 15624846Seric if (ident != NULL) 15724846Seric LogTag = ident; 15812742Ssam LogStat = logstat; 15933786Skarels if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) 16033786Skarels LogFacility = logfac; 16134563Skarels if (LogFile == -1) { 16234563Skarels SyslogAddr.sa_family = AF_UNIX; 16338557Sbostic strncpy(SyslogAddr.sa_data, _PATH_LOGNAME, 16438557Sbostic sizeof(SyslogAddr.sa_data)); 16534563Skarels if (LogStat & LOG_NDELAY) { 16634563Skarels LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); 16734563Skarels fcntl(LogFile, F_SETFD, 1); 16834563Skarels } 16917918Sralph } 17034563Skarels if (LogFile != -1 && !connected && 17134563Skarels connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) != -1) 17234563Skarels connected = 1; 17312742Ssam } 17412742Ssam 17512742Ssam /* 17612742Ssam * CLOSELOG -- close the system log 17712742Ssam */ 17812742Ssam closelog() 17912742Ssam { 18012742Ssam (void) close(LogFile); 18112742Ssam LogFile = -1; 18234563Skarels connected = 0; 18312742Ssam } 18416414Sralph 18536440Sbostic static int LogMask = 0xff; /* mask of priorities to be logged */ 18616414Sralph /* 18716414Sralph * SETLOGMASK -- set the log mask level 18816414Sralph */ 18917526Sralph setlogmask(pmask) 19017526Sralph int pmask; 19116414Sralph { 19217526Sralph int omask; 19316414Sralph 19417526Sralph omask = LogMask; 19517526Sralph if (pmask != 0) 19617526Sralph LogMask = pmask; 19717526Sralph return (omask); 19816414Sralph } 199