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 634821Sbostic * provided that the above copyright notice and this paragraph are 734821Sbostic * duplicated in all such forms and that any documentation, 834821Sbostic * advertising materials, and other materials related to such 934821Sbostic * distribution and use acknowledge that the software was developed 1034821Sbostic * by the University of California, Berkeley. The name of the 1134821Sbostic * University may not be used to endorse or promote products derived 1234821Sbostic * from this software without specific prior written permission. 1334821Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1434821Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1534821Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621362Sdist */ 1721362Sdist 1826602Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*42025Sbostic static char sccsid[] = "@(#)syslog.c 5.26 (Berkeley) 05/15/90"; 2033786Skarels #endif /* LIBC_SCCS and not lint */ 2112742Ssam 2212742Ssam /* 2312742Ssam * SYSLOG -- print message on log file 2412742Ssam * 2536440Sbostic * This routine looks a lot like printf, except that it outputs to the 2636440Sbostic * log file instead of the standard output. Also: 2716414Sralph * adds a timestamp, 2816414Sralph * prints the module name in front of the message, 2916414Sralph * has some other formatting types (or will sometime), 3016414Sralph * adds a newline on the end of the message. 3112742Ssam * 3236440Sbostic * The output of this routine is intended to be read by syslogd(8). 3316943Sralph * 3416943Sralph * Author: Eric Allman 3516943Sralph * Modified to use UNIX domain IPC by Ralph Campbell 3612742Ssam */ 3716414Sralph 3812742Ssam #include <sys/types.h> 3912742Ssam #include <sys/socket.h> 4016414Sralph #include <sys/file.h> 4126870Skarels #include <sys/signal.h> 4226870Skarels #include <sys/syslog.h> 4336792Sbostic #include <sys/uio.h> 4438557Sbostic #include <sys/wait.h> 4512742Ssam #include <netdb.h> 46*42025Sbostic #include <string.h> 4736442Sbostic #include <varargs.h> 4838557Sbostic #include <paths.h> 4936440Sbostic #include <stdio.h> 5012742Ssam 5138557Sbostic #define _PATH_LOGNAME "/dev/log" 5212742Ssam 5316414Sralph static int LogFile = -1; /* fd for log */ 5434563Skarels static int connected; /* have done connect */ 5536440Sbostic static int LogStat = 0; /* status bits, set by openlog() */ 5624846Seric static char *LogTag = "syslog"; /* string to tag the entry with */ 5724846Seric static int LogFacility = LOG_USER; /* default facility code */ 5812742Ssam 5936440Sbostic syslog(pri, fmt, args) 6036440Sbostic int pri, args; 6112742Ssam char *fmt; 6212742Ssam { 6336442Sbostic vsyslog(pri, fmt, &args); 6436442Sbostic } 6536442Sbostic 6636442Sbostic vsyslog(pri, fmt, ap) 6736442Sbostic int pri; 6836443Sbostic register char *fmt; 6936442Sbostic va_list ap; 7036442Sbostic { 7136443Sbostic extern int errno; 7236440Sbostic register int cnt; 7336440Sbostic register char *p; 7436440Sbostic time_t now, time(); 7538567Sbostic int fd, saved_errno; 7636792Sbostic char tbuf[2048], fmt_cpy[1024], *stdp, *ctime(); 7712742Ssam 7836443Sbostic saved_errno = errno; 7936443Sbostic 8012742Ssam /* see if we should just throw out this message */ 8139428Sbostic if (!LOG_MASK(LOG_PRI(pri)) || (pri &~ (LOG_PRIMASK|LOG_FACMASK))) 8212742Ssam return; 8334563Skarels if (LogFile < 0 || !connected) 8425187Seric openlog(LogTag, LogStat | LOG_NDELAY, 0); 8524846Seric 8624846Seric /* set default facility if none specified */ 8724846Seric if ((pri & LOG_FACMASK) == 0) 8824846Seric pri |= LogFacility; 8924846Seric 9024846Seric /* build the message */ 9136440Sbostic (void)time(&now); 9236440Sbostic (void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4); 9336440Sbostic for (p = tbuf; *p; ++p); 9436792Sbostic if (LogStat & LOG_PERROR) 9536792Sbostic stdp = p; 9616414Sralph if (LogTag) { 9736440Sbostic (void)strcpy(p, LogTag); 9836440Sbostic for (; *p; ++p); 9916414Sralph } 10016414Sralph if (LogStat & LOG_PID) { 10136440Sbostic (void)sprintf(p, "[%d]", getpid()); 10236440Sbostic for (; *p; ++p); 10316414Sralph } 10424846Seric if (LogTag) { 10536440Sbostic *p++ = ':'; 10636440Sbostic *p++ = ' '; 10724846Seric } 10812742Ssam 10936443Sbostic /* substitute error message for %m */ 11036443Sbostic { 11136443Sbostic register char ch, *t1, *t2; 11236443Sbostic char *strerror(); 11324846Seric 11436443Sbostic for (t1 = fmt_cpy; ch = *fmt; ++fmt) 11536443Sbostic if (ch == '%' && fmt[1] == 'm') { 11636443Sbostic ++fmt; 11736443Sbostic for (t2 = strerror(saved_errno); 11836443Sbostic *t1 = *t2++; ++t1); 11936443Sbostic } 12036443Sbostic else 12136443Sbostic *t1++ = ch; 12236583Sbostic *t1 = '\0'; 12336443Sbostic } 12436443Sbostic 12536443Sbostic (void)vsprintf(p, fmt_cpy, ap); 12636443Sbostic 12736792Sbostic cnt = strlen(tbuf); 12836792Sbostic 12936792Sbostic /* output to stderr if requested */ 13036792Sbostic if (LogStat & LOG_PERROR) { 13136792Sbostic struct iovec iov[2]; 13236792Sbostic register struct iovec *v = iov; 13336792Sbostic 13436792Sbostic v->iov_base = stdp; 13536792Sbostic v->iov_len = cnt - (stdp - tbuf); 13636792Sbostic ++v; 13736792Sbostic v->iov_base = "\n"; 13836792Sbostic v->iov_len = 1; 13936792Sbostic (void)writev(2, iov, 2); 14036792Sbostic } 14136792Sbostic 14224846Seric /* output the message to the local logger */ 14338557Sbostic if (send(LogFile, tbuf, cnt, 0) >= 0 || !(LogStat&LOG_CONS)) 14416414Sralph return; 14524846Seric 14638567Sbostic /* 14738567Sbostic * output the message to the console; don't worry about 14838567Sbostic * blocking, if console blocks everything will. 14938567Sbostic */ 15038567Sbostic if ((fd = open(_PATH_CONSOLE, O_WRONLY, 0)) < 0) 15116414Sralph return; 15238760Sbostic (void)strcat(tbuf, "\r\n"); 15338567Sbostic p = index(tbuf, '>') + 1; 15438567Sbostic (void)write(fd, p, cnt + 1 - (p - tbuf)); 15538567Sbostic (void)close(fd); 15612742Ssam } 15712742Ssam 15836440Sbostic static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */ 15912742Ssam /* 16012742Ssam * OPENLOG -- open system log 16112742Ssam */ 16224846Seric openlog(ident, logstat, logfac) 16312742Ssam char *ident; 16424846Seric int logstat, logfac; 16512742Ssam { 16624846Seric if (ident != NULL) 16724846Seric LogTag = ident; 16812742Ssam LogStat = logstat; 16933786Skarels if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) 17033786Skarels LogFacility = logfac; 17134563Skarels if (LogFile == -1) { 17234563Skarels SyslogAddr.sa_family = AF_UNIX; 17338557Sbostic strncpy(SyslogAddr.sa_data, _PATH_LOGNAME, 17438557Sbostic sizeof(SyslogAddr.sa_data)); 17534563Skarels if (LogStat & LOG_NDELAY) { 17634563Skarels LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); 17734563Skarels fcntl(LogFile, F_SETFD, 1); 17834563Skarels } 17917918Sralph } 18034563Skarels if (LogFile != -1 && !connected && 18134563Skarels connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) != -1) 18234563Skarels connected = 1; 18312742Ssam } 18412742Ssam 18512742Ssam /* 18612742Ssam * CLOSELOG -- close the system log 18712742Ssam */ 18812742Ssam closelog() 18912742Ssam { 19012742Ssam (void) close(LogFile); 19112742Ssam LogFile = -1; 19234563Skarels connected = 0; 19312742Ssam } 19416414Sralph 19536440Sbostic static int LogMask = 0xff; /* mask of priorities to be logged */ 19616414Sralph /* 19716414Sralph * SETLOGMASK -- set the log mask level 19816414Sralph */ 19917526Sralph setlogmask(pmask) 20017526Sralph int pmask; 20116414Sralph { 20217526Sralph int omask; 20316414Sralph 20417526Sralph omask = LogMask; 20517526Sralph if (pmask != 0) 20617526Sralph LogMask = pmask; 20717526Sralph return (omask); 20816414Sralph } 209