xref: /csrg-svn/lib/libc/gen/syslog.c (revision 27343)
121362Sdist /*
221362Sdist  * Copyright (c) 1983 Regents of the University of California.
321362Sdist  * All rights reserved.  The Berkeley software License Agreement
421362Sdist  * specifies the terms and conditions for redistribution.
521362Sdist  */
621362Sdist 
726602Sdonn #if defined(LIBC_SCCS) && !defined(lint)
8*27343Skarels static char sccsid[] = "@(#)syslog.c	5.8 (Berkeley) 04/24/86";
926602Sdonn #endif LIBC_SCCS and not lint
1012742Ssam 
1112742Ssam /*
1212742Ssam  * SYSLOG -- print message on log file
1312742Ssam  *
1412742Ssam  * This routine looks a lot like printf, except that it
1512742Ssam  * outputs to the log file instead of the standard output.
1616414Sralph  * 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  *
2216414Sralph  * The output of this routine is intended to be read by /etc/syslogd.
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>
3312742Ssam #include <netdb.h>
3426870Skarels #include <strings.h>
3512742Ssam 
3616414Sralph #define	MAXLINE	1024			/* max message size */
3716414Sralph #define NULL	0			/* manifest */
3812742Ssam 
3924846Seric #define PRIMASK(p)	(1 << ((p) & LOG_PRIMASK))
4024846Seric #define PRIFAC(p)	(((p) & LOG_FACMASK) >> 3)
4124846Seric #define IMPORTANT 	LOG_ERR
4217918Sralph 
4316414Sralph static char	logname[] = "/dev/log";
4416414Sralph static char	ctty[] = "/dev/console";
4512742Ssam 
4616414Sralph static int	LogFile = -1;		/* fd for log */
4716414Sralph static int	LogStat	= 0;		/* status bits, set by openlog() */
4824846Seric static char	*LogTag = "syslog";	/* string to tag the entry with */
4924846Seric static int	LogMask = 0xff;		/* mask of priorities to be logged */
5024846Seric static int	LogFacility = LOG_USER;	/* default facility code */
5112742Ssam 
5224846Seric static struct sockaddr SyslogAddr;	/* AF_UNIX address of local logger */
5316414Sralph 
5412742Ssam extern	int errno, sys_nerr;
5512742Ssam extern	char *sys_errlist[];
5612742Ssam 
5712742Ssam syslog(pri, fmt, p0, p1, p2, p3, p4)
5812742Ssam 	int pri;
5912742Ssam 	char *fmt;
6012742Ssam {
6116414Sralph 	char buf[MAXLINE + 1], outline[MAXLINE + 1];
6216414Sralph 	register char *b, *f, *o;
6316414Sralph 	register int c;
6416414Sralph 	long now;
6516943Sralph 	int pid, olderrno = errno;
6612742Ssam 
6712742Ssam 	/* see if we should just throw out this message */
6824846Seric 	if (pri <= 0 || PRIFAC(pri) >= LOG_NFACILITIES || (PRIMASK(pri) & LogMask) == 0)
6912742Ssam 		return;
7016414Sralph 	if (LogFile < 0)
7125187Seric 		openlog(LogTag, LogStat | LOG_NDELAY, 0);
7224846Seric 
7324846Seric 	/* set default facility if none specified */
7424846Seric 	if ((pri & LOG_FACMASK) == 0)
7524846Seric 		pri |= LogFacility;
7624846Seric 
7724846Seric 	/* build the message */
7816414Sralph 	o = outline;
7916943Sralph 	sprintf(o, "<%d>", pri);
8016943Sralph 	o += strlen(o);
8124846Seric 	time(&now);
8224846Seric 	sprintf(o, "%.15s ", ctime(&now) + 4);
8324846Seric 	o += strlen(o);
8416414Sralph 	if (LogTag) {
8516414Sralph 		strcpy(o, LogTag);
8616414Sralph 		o += strlen(o);
8716414Sralph 	}
8816414Sralph 	if (LogStat & LOG_PID) {
8916943Sralph 		sprintf(o, "[%d]", getpid());
9016414Sralph 		o += strlen(o);
9116414Sralph 	}
9224846Seric 	if (LogTag) {
9324846Seric 		strcpy(o, ": ");
9424846Seric 		o += 2;
9524846Seric 	}
9612742Ssam 
9716414Sralph 	b = buf;
9816414Sralph 	f = fmt;
9916414Sralph 	while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) {
10016414Sralph 		if (c != '%') {
10116414Sralph 			*b++ = c;
10216414Sralph 			continue;
10312742Ssam 		}
10416414Sralph 		if ((c = *f++) != 'm') {
10516414Sralph 			*b++ = '%';
10616414Sralph 			*b++ = c;
10716414Sralph 			continue;
10812742Ssam 		}
10916943Sralph 		if ((unsigned)olderrno > sys_nerr)
11016943Sralph 			sprintf(b, "error %d", olderrno);
11112742Ssam 		else
11216943Sralph 			strcpy(b, sys_errlist[olderrno]);
11316414Sralph 		b += strlen(b);
11412742Ssam 	}
11516414Sralph 	*b++ = '\n';
11616414Sralph 	*b = '\0';
11716414Sralph 	sprintf(o, buf, p0, p1, p2, p3, p4);
11816414Sralph 	c = strlen(outline);
11916414Sralph 	if (c > MAXLINE)
12016414Sralph 		c = MAXLINE;
12124846Seric 
12224846Seric 	/* output the message to the local logger */
12316414Sralph 	if (sendto(LogFile, outline, c, 0, &SyslogAddr, sizeof SyslogAddr) >= 0)
12416414Sralph 		return;
125*27343Skarels 	if (!(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) {
13324880Seric 		signal(SIGALRM, SIG_DFL);
13424880Seric 		sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
13524880Seric 		alarm(5);
13624846Seric 		LogFile = open(ctty, O_WRONLY);
13724880Seric 		alarm(0);
13817918Sralph 		strcat(o, "\r");
13926870Skarels 		o = index(outline, '>') + 1;
140*27343Skarels 		write(LogFile, o, c + 1 - (o - outline));
14116414Sralph 		close(LogFile);
14216414Sralph 		exit(0);
14316414Sralph 	}
144*27343Skarels 	if (!(LogStat & LOG_NOWAIT))
145*27343Skarels 		while ((c = wait((int *)0)) > 0 && c != pid)
146*27343Skarels 			;
14712742Ssam }
14812742Ssam 
14912742Ssam /*
15012742Ssam  * OPENLOG -- open system log
15112742Ssam  */
15224846Seric 
15324846Seric openlog(ident, logstat, logfac)
15412742Ssam 	char *ident;
15524846Seric 	int logstat, logfac;
15612742Ssam {
15724846Seric 	if (ident != NULL)
15824846Seric 		LogTag = ident;
15912742Ssam 	LogStat = logstat;
16024846Seric 	if (logfac != 0)
16124846Seric 		LogFacility = logfac & LOG_FACMASK;
16212742Ssam 	if (LogFile >= 0)
16312742Ssam 		return;
16416414Sralph 	SyslogAddr.sa_family = AF_UNIX;
16516414Sralph 	strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data);
16625187Seric 	if (LogStat & LOG_NDELAY) {
16717918Sralph 		LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
16817918Sralph 		fcntl(LogFile, F_SETFD, 1);
16917918Sralph 	}
17012742Ssam }
17112742Ssam 
17212742Ssam /*
17312742Ssam  * CLOSELOG -- close the system log
17412742Ssam  */
17525187Seric 
17612742Ssam closelog()
17712742Ssam {
17812742Ssam 
17912742Ssam 	(void) close(LogFile);
18012742Ssam 	LogFile = -1;
18112742Ssam }
18216414Sralph 
18316414Sralph /*
18416414Sralph  * SETLOGMASK -- set the log mask level
18516414Sralph  */
18617526Sralph setlogmask(pmask)
18717526Sralph 	int pmask;
18816414Sralph {
18917526Sralph 	int omask;
19016414Sralph 
19117526Sralph 	omask = LogMask;
19217526Sralph 	if (pmask != 0)
19317526Sralph 		LogMask = pmask;
19417526Sralph 	return (omask);
19516414Sralph }
196