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 6*34821Sbostic * provided that the above copyright notice and this paragraph are 7*34821Sbostic * duplicated in all such forms and that any documentation, 8*34821Sbostic * advertising materials, and other materials related to such 9*34821Sbostic * distribution and use acknowledge that the software was developed 10*34821Sbostic * by the University of California, Berkeley. The name of the 11*34821Sbostic * University may not be used to endorse or promote products derived 12*34821Sbostic * from this software without specific prior written permission. 13*34821Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*34821Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*34821Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621362Sdist */ 1721362Sdist 1826602Sdonn #if defined(LIBC_SCCS) && !defined(lint) 19*34821Sbostic static char sccsid[] = "@(#)syslog.c 5.16 (Berkeley) 06/27/88"; 2033786Skarels #endif /* LIBC_SCCS and not lint */ 2112742Ssam 2212742Ssam /* 2312742Ssam * SYSLOG -- print message on log file 2412742Ssam * 2512742Ssam * This routine looks a lot like printf, except that it 2612742Ssam * outputs to the log file instead of the standard output. 2716414Sralph * Also: 2816414Sralph * adds a timestamp, 2916414Sralph * prints the module name in front of the message, 3016414Sralph * has some other formatting types (or will sometime), 3116414Sralph * adds a newline on the end of the message. 3212742Ssam * 3316414Sralph * The output of this routine is intended to be read by /etc/syslogd. 3416943Sralph * 3516943Sralph * Author: Eric Allman 3616943Sralph * Modified to use UNIX domain IPC by Ralph Campbell 3712742Ssam */ 3816414Sralph 3912742Ssam #include <sys/types.h> 4012742Ssam #include <sys/socket.h> 4116414Sralph #include <sys/file.h> 4226870Skarels #include <sys/signal.h> 4326870Skarels #include <sys/syslog.h> 4412742Ssam #include <netdb.h> 4526870Skarels #include <strings.h> 4612742Ssam 4716414Sralph #define MAXLINE 1024 /* max message size */ 4816414Sralph #define NULL 0 /* manifest */ 4912742Ssam 5024846Seric #define IMPORTANT LOG_ERR 5117918Sralph 5216414Sralph static char logname[] = "/dev/log"; 5316414Sralph static char ctty[] = "/dev/console"; 5412742Ssam 5516414Sralph static int LogFile = -1; /* fd for log */ 5634563Skarels static int connected; /* have done connect */ 5716414Sralph static int LogStat = 0; /* status bits, set by openlog() */ 5824846Seric static char *LogTag = "syslog"; /* string to tag the entry with */ 5924846Seric static int LogMask = 0xff; /* mask of priorities to be logged */ 6024846Seric static int LogFacility = LOG_USER; /* default facility code */ 6112742Ssam 6224846Seric static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */ 6316414Sralph 6412742Ssam extern int errno, sys_nerr; 6512742Ssam extern char *sys_errlist[]; 6612742Ssam 6712742Ssam syslog(pri, fmt, p0, p1, p2, p3, p4) 6812742Ssam int pri; 6912742Ssam char *fmt; 7012742Ssam { 7116414Sralph char buf[MAXLINE + 1], outline[MAXLINE + 1]; 7216414Sralph register char *b, *f, *o; 7316414Sralph register int c; 7416414Sralph long now; 7516943Sralph int pid, olderrno = errno; 7612742Ssam 7712742Ssam /* see if we should just throw out this message */ 7834563Skarels if ((unsigned) LOG_FAC(pri) >= LOG_NFACILITIES || 7934563Skarels LOG_MASK(LOG_PRI(pri)) == 0 || 8034392Skarels (pri &~ (LOG_PRIMASK|LOG_FACMASK)) != 0) 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 */ 9016414Sralph o = outline; 9132497Sbostic (void)sprintf(o, "<%d>", pri); 9216943Sralph o += strlen(o); 9324846Seric time(&now); 9432497Sbostic (void)sprintf(o, "%.15s ", ctime(&now) + 4); 9524846Seric o += strlen(o); 9616414Sralph if (LogTag) { 9716414Sralph strcpy(o, LogTag); 9816414Sralph o += strlen(o); 9916414Sralph } 10016414Sralph if (LogStat & LOG_PID) { 10132497Sbostic (void)sprintf(o, "[%d]", getpid()); 10216414Sralph o += strlen(o); 10316414Sralph } 10424846Seric if (LogTag) { 10524846Seric strcpy(o, ": "); 10624846Seric o += 2; 10724846Seric } 10812742Ssam 10916414Sralph b = buf; 11016414Sralph f = fmt; 11116414Sralph while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) { 11216414Sralph if (c != '%') { 11316414Sralph *b++ = c; 11416414Sralph continue; 11512742Ssam } 11616414Sralph if ((c = *f++) != 'm') { 11716414Sralph *b++ = '%'; 11816414Sralph *b++ = c; 11916414Sralph continue; 12012742Ssam } 12116943Sralph if ((unsigned)olderrno > sys_nerr) 12232497Sbostic (void)sprintf(b, "error %d", olderrno); 12312742Ssam else 12416943Sralph strcpy(b, sys_errlist[olderrno]); 12516414Sralph b += strlen(b); 12612742Ssam } 12716414Sralph *b++ = '\n'; 12816414Sralph *b = '\0'; 12932497Sbostic (void)sprintf(o, buf, p0, p1, p2, p3, p4); 13016414Sralph c = strlen(outline); 13116414Sralph if (c > MAXLINE) 13216414Sralph c = MAXLINE; 13324846Seric 13424846Seric /* output the message to the local logger */ 13534563Skarels if (send(LogFile, outline, c, 0) >= 0) 13616414Sralph return; 13727343Skarels if (!(LogStat & LOG_CONS)) 13816414Sralph return; 13924846Seric 14024846Seric /* output the message to the console */ 14126508Skarels pid = vfork(); 14216414Sralph if (pid == -1) 14316414Sralph return; 14416414Sralph if (pid == 0) { 14527795Skarels int fd; 14627795Skarels 14724880Seric signal(SIGALRM, SIG_DFL); 14832303Sbostic sigsetmask(sigblock(0L) & ~sigmask(SIGALRM)); 14924880Seric alarm(5); 15027795Skarels fd = open(ctty, O_WRONLY); 15124880Seric alarm(0); 15217918Sralph strcat(o, "\r"); 15326870Skarels o = index(outline, '>') + 1; 15427795Skarels write(fd, o, c + 1 - (o - outline)); 15527795Skarels close(fd); 15627795Skarels _exit(0); 15716414Sralph } 15827343Skarels if (!(LogStat & LOG_NOWAIT)) 15927343Skarels while ((c = wait((int *)0)) > 0 && c != pid) 16027343Skarels ; 16112742Ssam } 16212742Ssam 16312742Ssam /* 16412742Ssam * OPENLOG -- open system log 16512742Ssam */ 16624846Seric 16724846Seric openlog(ident, logstat, logfac) 16812742Ssam char *ident; 16924846Seric int logstat, logfac; 17012742Ssam { 17124846Seric if (ident != NULL) 17224846Seric LogTag = ident; 17312742Ssam LogStat = logstat; 17433786Skarels if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0) 17533786Skarels LogFacility = logfac; 17634563Skarels if (LogFile == -1) { 17734563Skarels SyslogAddr.sa_family = AF_UNIX; 17834563Skarels strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data); 17934563Skarels if (LogStat & LOG_NDELAY) { 18034563Skarels LogFile = socket(AF_UNIX, SOCK_DGRAM, 0); 18134563Skarels fcntl(LogFile, F_SETFD, 1); 18234563Skarels } 18317918Sralph } 18434563Skarels if (LogFile != -1 && !connected && 18534563Skarels connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) != -1) 18634563Skarels connected = 1; 18712742Ssam } 18812742Ssam 18912742Ssam /* 19012742Ssam * CLOSELOG -- close the system log 19112742Ssam */ 19225187Seric 19312742Ssam closelog() 19412742Ssam { 19512742Ssam 19612742Ssam (void) close(LogFile); 19712742Ssam LogFile = -1; 19834563Skarels connected = 0; 19912742Ssam } 20016414Sralph 20116414Sralph /* 20216414Sralph * SETLOGMASK -- set the log mask level 20316414Sralph */ 20417526Sralph setlogmask(pmask) 20517526Sralph int pmask; 20616414Sralph { 20717526Sralph int omask; 20816414Sralph 20917526Sralph omask = LogMask; 21017526Sralph if (pmask != 0) 21117526Sralph LogMask = pmask; 21217526Sralph return (omask); 21316414Sralph } 214