xref: /csrg-svn/lib/libc/gen/syslog.c (revision 34563)
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
633786Skarels  * provided that this notice is preserved and that due credit is given
733786Skarels  * to the University of California at Berkeley. The name of the University
833786Skarels  * may not be used to endorse or promote products derived from this
933786Skarels  * software without specific prior written permission. This software
1033786Skarels  * is provided ``as is'' without express or implied warranty.
1121362Sdist  */
1221362Sdist 
1326602Sdonn #if defined(LIBC_SCCS) && !defined(lint)
14*34563Skarels static char sccsid[] = "@(#)syslog.c	5.15 (Berkeley) 05/31/88";
1533786Skarels #endif /* LIBC_SCCS and not lint */
1612742Ssam 
1733786Skarels 
1812742Ssam /*
1912742Ssam  * SYSLOG -- print message on log file
2012742Ssam  *
2112742Ssam  * This routine looks a lot like printf, except that it
2212742Ssam  * outputs to the log file instead of the standard output.
2316414Sralph  * Also:
2416414Sralph  *	adds a timestamp,
2516414Sralph  *	prints the module name in front of the message,
2616414Sralph  *	has some other formatting types (or will sometime),
2716414Sralph  *	adds a newline on the end of the message.
2812742Ssam  *
2916414Sralph  * The output of this routine is intended to be read by /etc/syslogd.
3016943Sralph  *
3116943Sralph  * Author: Eric Allman
3216943Sralph  * Modified to use UNIX domain IPC by Ralph Campbell
3312742Ssam  */
3416414Sralph 
3512742Ssam #include <sys/types.h>
3612742Ssam #include <sys/socket.h>
3716414Sralph #include <sys/file.h>
3826870Skarels #include <sys/signal.h>
3926870Skarels #include <sys/syslog.h>
4012742Ssam #include <netdb.h>
4126870Skarels #include <strings.h>
4212742Ssam 
4316414Sralph #define	MAXLINE	1024			/* max message size */
4416414Sralph #define NULL	0			/* manifest */
4512742Ssam 
4624846Seric #define IMPORTANT 	LOG_ERR
4717918Sralph 
4816414Sralph static char	logname[] = "/dev/log";
4916414Sralph static char	ctty[] = "/dev/console";
5012742Ssam 
5116414Sralph static int	LogFile = -1;		/* fd for log */
52*34563Skarels static int	connected;		/* have done connect */
5316414Sralph static int	LogStat	= 0;		/* status bits, set by openlog() */
5424846Seric static char	*LogTag = "syslog";	/* string to tag the entry with */
5524846Seric static int	LogMask = 0xff;		/* mask of priorities to be logged */
5624846Seric static int	LogFacility = LOG_USER;	/* default facility code */
5712742Ssam 
5824846Seric static struct sockaddr SyslogAddr;	/* AF_UNIX address of local logger */
5916414Sralph 
6012742Ssam extern	int errno, sys_nerr;
6112742Ssam extern	char *sys_errlist[];
6212742Ssam 
6312742Ssam syslog(pri, fmt, p0, p1, p2, p3, p4)
6412742Ssam 	int pri;
6512742Ssam 	char *fmt;
6612742Ssam {
6716414Sralph 	char buf[MAXLINE + 1], outline[MAXLINE + 1];
6816414Sralph 	register char *b, *f, *o;
6916414Sralph 	register int c;
7016414Sralph 	long now;
7116943Sralph 	int pid, olderrno = errno;
7212742Ssam 
7312742Ssam 	/* see if we should just throw out this message */
74*34563Skarels 	if ((unsigned) LOG_FAC(pri) >= LOG_NFACILITIES ||
75*34563Skarels 	    LOG_MASK(LOG_PRI(pri)) == 0 ||
7634392Skarels 	    (pri &~ (LOG_PRIMASK|LOG_FACMASK)) != 0)
7712742Ssam 		return;
78*34563Skarels 	if (LogFile < 0 || !connected)
7925187Seric 		openlog(LogTag, LogStat | LOG_NDELAY, 0);
8024846Seric 
8124846Seric 	/* set default facility if none specified */
8224846Seric 	if ((pri & LOG_FACMASK) == 0)
8324846Seric 		pri |= LogFacility;
8424846Seric 
8524846Seric 	/* build the message */
8616414Sralph 	o = outline;
8732497Sbostic 	(void)sprintf(o, "<%d>", pri);
8816943Sralph 	o += strlen(o);
8924846Seric 	time(&now);
9032497Sbostic 	(void)sprintf(o, "%.15s ", ctime(&now) + 4);
9124846Seric 	o += strlen(o);
9216414Sralph 	if (LogTag) {
9316414Sralph 		strcpy(o, LogTag);
9416414Sralph 		o += strlen(o);
9516414Sralph 	}
9616414Sralph 	if (LogStat & LOG_PID) {
9732497Sbostic 		(void)sprintf(o, "[%d]", getpid());
9816414Sralph 		o += strlen(o);
9916414Sralph 	}
10024846Seric 	if (LogTag) {
10124846Seric 		strcpy(o, ": ");
10224846Seric 		o += 2;
10324846Seric 	}
10412742Ssam 
10516414Sralph 	b = buf;
10616414Sralph 	f = fmt;
10716414Sralph 	while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) {
10816414Sralph 		if (c != '%') {
10916414Sralph 			*b++ = c;
11016414Sralph 			continue;
11112742Ssam 		}
11216414Sralph 		if ((c = *f++) != 'm') {
11316414Sralph 			*b++ = '%';
11416414Sralph 			*b++ = c;
11516414Sralph 			continue;
11612742Ssam 		}
11716943Sralph 		if ((unsigned)olderrno > sys_nerr)
11832497Sbostic 			(void)sprintf(b, "error %d", olderrno);
11912742Ssam 		else
12016943Sralph 			strcpy(b, sys_errlist[olderrno]);
12116414Sralph 		b += strlen(b);
12212742Ssam 	}
12316414Sralph 	*b++ = '\n';
12416414Sralph 	*b = '\0';
12532497Sbostic 	(void)sprintf(o, buf, p0, p1, p2, p3, p4);
12616414Sralph 	c = strlen(outline);
12716414Sralph 	if (c > MAXLINE)
12816414Sralph 		c = MAXLINE;
12924846Seric 
13024846Seric 	/* output the message to the local logger */
131*34563Skarels 	if (send(LogFile, outline, c, 0) >= 0)
13216414Sralph 		return;
13327343Skarels 	if (!(LogStat & LOG_CONS))
13416414Sralph 		return;
13524846Seric 
13624846Seric 	/* output the message to the console */
13726508Skarels 	pid = vfork();
13816414Sralph 	if (pid == -1)
13916414Sralph 		return;
14016414Sralph 	if (pid == 0) {
14127795Skarels 		int fd;
14227795Skarels 
14324880Seric 		signal(SIGALRM, SIG_DFL);
14432303Sbostic 		sigsetmask(sigblock(0L) & ~sigmask(SIGALRM));
14524880Seric 		alarm(5);
14627795Skarels 		fd = open(ctty, O_WRONLY);
14724880Seric 		alarm(0);
14817918Sralph 		strcat(o, "\r");
14926870Skarels 		o = index(outline, '>') + 1;
15027795Skarels 		write(fd, o, c + 1 - (o - outline));
15127795Skarels 		close(fd);
15227795Skarels 		_exit(0);
15316414Sralph 	}
15427343Skarels 	if (!(LogStat & LOG_NOWAIT))
15527343Skarels 		while ((c = wait((int *)0)) > 0 && c != pid)
15627343Skarels 			;
15712742Ssam }
15812742Ssam 
15912742Ssam /*
16012742Ssam  * OPENLOG -- open system log
16112742Ssam  */
16224846Seric 
16324846Seric openlog(ident, logstat, logfac)
16412742Ssam 	char *ident;
16524846Seric 	int logstat, logfac;
16612742Ssam {
16724846Seric 	if (ident != NULL)
16824846Seric 		LogTag = ident;
16912742Ssam 	LogStat = logstat;
17033786Skarels 	if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
17133786Skarels 		LogFacility = logfac;
172*34563Skarels 	if (LogFile == -1) {
173*34563Skarels 		SyslogAddr.sa_family = AF_UNIX;
174*34563Skarels 		strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data);
175*34563Skarels 		if (LogStat & LOG_NDELAY) {
176*34563Skarels 			LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
177*34563Skarels 			fcntl(LogFile, F_SETFD, 1);
178*34563Skarels 		}
17917918Sralph 	}
180*34563Skarels 	if (LogFile != -1 && !connected &&
181*34563Skarels 	    connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) != -1)
182*34563Skarels 		connected = 1;
18312742Ssam }
18412742Ssam 
18512742Ssam /*
18612742Ssam  * CLOSELOG -- close the system log
18712742Ssam  */
18825187Seric 
18912742Ssam closelog()
19012742Ssam {
19112742Ssam 
19212742Ssam 	(void) close(LogFile);
19312742Ssam 	LogFile = -1;
194*34563Skarels 	connected = 0;
19512742Ssam }
19616414Sralph 
19716414Sralph /*
19816414Sralph  * SETLOGMASK -- set the log mask level
19916414Sralph  */
20017526Sralph setlogmask(pmask)
20117526Sralph 	int pmask;
20216414Sralph {
20317526Sralph 	int omask;
20416414Sralph 
20517526Sralph 	omask = LogMask;
20617526Sralph 	if (pmask != 0)
20717526Sralph 		LogMask = pmask;
20817526Sralph 	return (omask);
20916414Sralph }
210