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*36443Sbostic static char sccsid[] = "@(#)syslog.c 5.19 (Berkeley) 12/19/88"; 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> 4312742Ssam #include <netdb.h> 4426870Skarels #include <strings.h> 4536442Sbostic #include <varargs.h> 4636440Sbostic #include <stdio.h> 4712742Ssam 4836440Sbostic #define LOGNAME "/dev/log" 4936440Sbostic #define CONSOLE "/dev/console" 5012742Ssam 5116414Sralph static int LogFile = -1; /* fd for log */ 5234563Skarels static int connected; /* have done connect */ 5336440Sbostic static int LogStat = 0; /* status bits, set by openlog() */ 5424846Seric static char *LogTag = "syslog"; /* string to tag the entry with */ 5524846Seric static int LogFacility = LOG_USER; /* default facility code */ 5612742Ssam 5736440Sbostic syslog(pri, fmt, args) 5836440Sbostic int pri, args; 5912742Ssam char *fmt; 6012742Ssam { 6136442Sbostic vsyslog(pri, fmt, &args); 6236442Sbostic } 6336442Sbostic 6436442Sbostic vsyslog(pri, fmt, ap) 6536442Sbostic int pri; 66*36443Sbostic register char *fmt; 6736442Sbostic va_list ap; 6836442Sbostic { 69*36443Sbostic extern int errno; 7036440Sbostic register int cnt; 7136440Sbostic register char *p; 7236440Sbostic time_t now, time(); 73*36443Sbostic int pid, saved_errno; 74*36443Sbostic char tbuf[2048], fmt_cpy[1024], *ctime(); 7512742Ssam 76*36443Sbostic saved_errno = errno; 77*36443Sbostic 7812742Ssam /* see if we should just throw out this message */ 7936440Sbostic if ((u_int)LOG_FAC(pri) >= LOG_NFACILITIES || 8036440Sbostic !LOG_MASK(LOG_PRI(pri)) || (pri &~ (LOG_PRIMASK|LOG_FACMASK))) 8112742Ssam return; 8234563Skarels if (LogFile < 0 || !connected) 8325187Seric openlog(LogTag, LogStat | LOG_NDELAY, 0); 8424846Seric 8524846Seric /* set default facility if none specified */ 8624846Seric if ((pri & LOG_FACMASK) == 0) 8724846Seric pri |= LogFacility; 8824846Seric 8924846Seric /* build the message */ 9036440Sbostic (void)time(&now); 9136440Sbostic (void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4); 9236440Sbostic for (p = tbuf; *p; ++p); 9316414Sralph if (LogTag) { 9436440Sbostic (void)strcpy(p, LogTag); 9536440Sbostic for (; *p; ++p); 9616414Sralph } 9716414Sralph if (LogStat & LOG_PID) { 9836440Sbostic (void)sprintf(p, "[%d]", getpid()); 9936440Sbostic for (; *p; ++p); 10016414Sralph } 10124846Seric if (LogTag) { 10236440Sbostic *p++ = ':'; 10336440Sbostic *p++ = ' '; 10424846Seric } 10512742Ssam 106*36443Sbostic /* substitute error message for %m */ 107*36443Sbostic { 108*36443Sbostic register char ch, *t1, *t2; 109*36443Sbostic char *strerror(); 11024846Seric 111*36443Sbostic for (t1 = fmt_cpy; ch = *fmt; ++fmt) 112*36443Sbostic if (ch == '%' && fmt[1] == 'm') { 113*36443Sbostic ++fmt; 114*36443Sbostic for (t2 = strerror(saved_errno); 115*36443Sbostic *t1 = *t2++; ++t1); 116*36443Sbostic } 117*36443Sbostic else 118*36443Sbostic *t1++ = ch; 119*36443Sbostic } 120*36443Sbostic 121*36443Sbostic (void)vsprintf(p, fmt_cpy, ap); 122*36443Sbostic 12324846Seric /* output the message to the local logger */ 12436440Sbostic if (send(LogFile, tbuf, cnt = strlen(tbuf), 0) >= 0 || 12536440Sbostic !(LogStat&LOG_CONS)) 12616414Sralph return; 12724846Seric 12824846Seric /* output the message to the console */ 12926508Skarels pid = vfork(); 13016414Sralph if (pid == -1) 13116414Sralph return; 13216414Sralph if (pid == 0) { 13327795Skarels int fd; 13436440Sbostic long sigsetmask(); 13527795Skarels 13636440Sbostic (void)signal(SIGALRM, SIG_DFL); 13736440Sbostic sigsetmask((long)~sigmask(SIGALRM)); 13836440Sbostic (void)alarm((u_int)5); 13936440Sbostic if ((fd = open(CONSOLE, O_WRONLY, 0)) < 0) 14036440Sbostic return; 14136440Sbostic (void)alarm((u_int)0); 14236440Sbostic (void)strcat(tbuf, "\r"); 14336440Sbostic p = index(tbuf, '>') + 1; 14436440Sbostic (void)write(fd, p, cnt + 1 - (p - tbuf)); 14536440Sbostic (void)close(fd); 14627795Skarels _exit(0); 14716414Sralph } 14827343Skarels if (!(LogStat & LOG_NOWAIT)) 14936440Sbostic while ((cnt = wait((int *)0)) > 0 && cnt != pid); 15012742Ssam } 15112742Ssam 15236440Sbostic static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */ 15312742Ssam /* 15412742Ssam * OPENLOG -- open system log 15512742Ssam */ 15624846Seric openlog(ident, logstat, logfac) 15712742Ssam char *ident; 15824846Seric int logstat, logfac; 15912742Ssam { 16024846Seric if (ident != NULL) 16124846Seric LogTag = ident; 16212742Ssam LogStat = logstat; 16333786Skarels if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) 16433786Skarels LogFacility = logfac; 16534563Skarels if (LogFile == -1) { 16634563Skarels SyslogAddr.sa_family = AF_UNIX; 16736440Sbostic strncpy(SyslogAddr.sa_data, LOGNAME, sizeof SyslogAddr.sa_data); 16834563Skarels if (LogStat & LOG_NDELAY) { 16934563Skarels LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); 17034563Skarels fcntl(LogFile, F_SETFD, 1); 17134563Skarels } 17217918Sralph } 17334563Skarels if (LogFile != -1 && !connected && 17434563Skarels connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) != -1) 17534563Skarels connected = 1; 17612742Ssam } 17712742Ssam 17812742Ssam /* 17912742Ssam * CLOSELOG -- close the system log 18012742Ssam */ 18112742Ssam closelog() 18212742Ssam { 18312742Ssam (void) close(LogFile); 18412742Ssam LogFile = -1; 18534563Skarels connected = 0; 18612742Ssam } 18716414Sralph 18836440Sbostic static int LogMask = 0xff; /* mask of priorities to be logged */ 18916414Sralph /* 19016414Sralph * SETLOGMASK -- set the log mask level 19116414Sralph */ 19217526Sralph setlogmask(pmask) 19317526Sralph int pmask; 19416414Sralph { 19517526Sralph int omask; 19616414Sralph 19717526Sralph omask = LogMask; 19817526Sralph if (pmask != 0) 19917526Sralph LogMask = pmask; 20017526Sralph return (omask); 20116414Sralph } 202