xref: /csrg-svn/lib/libc/gen/syslog.c (revision 33786)
121362Sdist /*
2*33786Skarels  * Copyright (c) 1983, 1988 Regents of the University of California.
3*33786Skarels  * All rights reserved.
4*33786Skarels  *
5*33786Skarels  * Redistribution and use in source and binary forms are permitted
6*33786Skarels  * provided that this notice is preserved and that due credit is given
7*33786Skarels  * to the University of California at Berkeley. The name of the University
8*33786Skarels  * may not be used to endorse or promote products derived from this
9*33786Skarels  * software without specific prior written permission. This software
10*33786Skarels  * is provided ``as is'' without express or implied warranty.
1121362Sdist  */
1221362Sdist 
1326602Sdonn #if defined(LIBC_SCCS) && !defined(lint)
14*33786Skarels static char sccsid[] = "@(#)syslog.c	5.13 (Berkeley) 03/24/88";
15*33786Skarels #endif /* LIBC_SCCS and not lint */
1612742Ssam 
17*33786Skarels 
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 PRIFAC(p)	(((p) & LOG_FACMASK) >> 3)
47*33786Skarels 					/* XXX should be in <syslog.h> */
4824846Seric #define IMPORTANT 	LOG_ERR
4917918Sralph 
5016414Sralph static char	logname[] = "/dev/log";
5116414Sralph static char	ctty[] = "/dev/console";
5212742Ssam 
5316414Sralph static int	LogFile = -1;		/* fd for log */
5416414Sralph static int	LogStat	= 0;		/* status bits, set by openlog() */
5524846Seric static char	*LogTag = "syslog";	/* string to tag the entry with */
5624846Seric static int	LogMask = 0xff;		/* mask of priorities to be logged */
5724846Seric static int	LogFacility = LOG_USER;	/* default facility code */
5812742Ssam 
5924846Seric static struct sockaddr SyslogAddr;	/* AF_UNIX address of local logger */
6016414Sralph 
6112742Ssam extern	int errno, sys_nerr;
6212742Ssam extern	char *sys_errlist[];
6312742Ssam 
6412742Ssam syslog(pri, fmt, p0, p1, p2, p3, p4)
6512742Ssam 	int pri;
6612742Ssam 	char *fmt;
6712742Ssam {
6816414Sralph 	char buf[MAXLINE + 1], outline[MAXLINE + 1];
6916414Sralph 	register char *b, *f, *o;
7016414Sralph 	register int c;
7116414Sralph 	long now;
7216943Sralph 	int pid, olderrno = errno;
7312742Ssam 
7412742Ssam 	/* see if we should just throw out this message */
75*33786Skarels 	if ((unsigned) PRIFAC(pri) >= LOG_NFACILITIES ||
76*33786Skarels 	    (LOG_MASK(pri & LOG_PRIMASK) & LogMask) == 0 ||
77*33786Skarels 	    (pri &~ (LOG_PRIMASK|LOG_PRIMASK)) != 0)
7812742Ssam 		return;
7916414Sralph 	if (LogFile < 0)
8025187Seric 		openlog(LogTag, LogStat | LOG_NDELAY, 0);
8124846Seric 
8224846Seric 	/* set default facility if none specified */
8324846Seric 	if ((pri & LOG_FACMASK) == 0)
8424846Seric 		pri |= LogFacility;
8524846Seric 
8624846Seric 	/* build the message */
8716414Sralph 	o = outline;
8832497Sbostic 	(void)sprintf(o, "<%d>", pri);
8916943Sralph 	o += strlen(o);
9024846Seric 	time(&now);
9132497Sbostic 	(void)sprintf(o, "%.15s ", ctime(&now) + 4);
9224846Seric 	o += strlen(o);
9316414Sralph 	if (LogTag) {
9416414Sralph 		strcpy(o, LogTag);
9516414Sralph 		o += strlen(o);
9616414Sralph 	}
9716414Sralph 	if (LogStat & LOG_PID) {
9832497Sbostic 		(void)sprintf(o, "[%d]", getpid());
9916414Sralph 		o += strlen(o);
10016414Sralph 	}
10124846Seric 	if (LogTag) {
10224846Seric 		strcpy(o, ": ");
10324846Seric 		o += 2;
10424846Seric 	}
10512742Ssam 
10616414Sralph 	b = buf;
10716414Sralph 	f = fmt;
10816414Sralph 	while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) {
10916414Sralph 		if (c != '%') {
11016414Sralph 			*b++ = c;
11116414Sralph 			continue;
11212742Ssam 		}
11316414Sralph 		if ((c = *f++) != 'm') {
11416414Sralph 			*b++ = '%';
11516414Sralph 			*b++ = c;
11616414Sralph 			continue;
11712742Ssam 		}
11816943Sralph 		if ((unsigned)olderrno > sys_nerr)
11932497Sbostic 			(void)sprintf(b, "error %d", olderrno);
12012742Ssam 		else
12116943Sralph 			strcpy(b, sys_errlist[olderrno]);
12216414Sralph 		b += strlen(b);
12312742Ssam 	}
12416414Sralph 	*b++ = '\n';
12516414Sralph 	*b = '\0';
12632497Sbostic 	(void)sprintf(o, buf, p0, p1, p2, p3, p4);
12716414Sralph 	c = strlen(outline);
12816414Sralph 	if (c > MAXLINE)
12916414Sralph 		c = MAXLINE;
13024846Seric 
13124846Seric 	/* output the message to the local logger */
13216414Sralph 	if (sendto(LogFile, outline, c, 0, &SyslogAddr, sizeof SyslogAddr) >= 0)
13316414Sralph 		return;
13427343Skarels 	if (!(LogStat & LOG_CONS))
13516414Sralph 		return;
13624846Seric 
13724846Seric 	/* output the message to the console */
13826508Skarels 	pid = vfork();
13916414Sralph 	if (pid == -1)
14016414Sralph 		return;
14116414Sralph 	if (pid == 0) {
14227795Skarels 		int fd;
14327795Skarels 
14424880Seric 		signal(SIGALRM, SIG_DFL);
14532303Sbostic 		sigsetmask(sigblock(0L) & ~sigmask(SIGALRM));
14624880Seric 		alarm(5);
14727795Skarels 		fd = open(ctty, O_WRONLY);
14824880Seric 		alarm(0);
14917918Sralph 		strcat(o, "\r");
15026870Skarels 		o = index(outline, '>') + 1;
15127795Skarels 		write(fd, o, c + 1 - (o - outline));
15227795Skarels 		close(fd);
15327795Skarels 		_exit(0);
15416414Sralph 	}
15527343Skarels 	if (!(LogStat & LOG_NOWAIT))
15627343Skarels 		while ((c = wait((int *)0)) > 0 && c != pid)
15727343Skarels 			;
15812742Ssam }
15912742Ssam 
16012742Ssam /*
16112742Ssam  * OPENLOG -- open system log
16212742Ssam  */
16324846Seric 
16424846Seric openlog(ident, logstat, logfac)
16512742Ssam 	char *ident;
16624846Seric 	int logstat, logfac;
16712742Ssam {
16824846Seric 	if (ident != NULL)
16924846Seric 		LogTag = ident;
17012742Ssam 	LogStat = logstat;
171*33786Skarels 	if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
172*33786Skarels 		LogFacility = logfac;
17312742Ssam 	if (LogFile >= 0)
17412742Ssam 		return;
17516414Sralph 	SyslogAddr.sa_family = AF_UNIX;
17616414Sralph 	strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data);
17725187Seric 	if (LogStat & LOG_NDELAY) {
17817918Sralph 		LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
17917918Sralph 		fcntl(LogFile, F_SETFD, 1);
18017918Sralph 	}
18112742Ssam }
18212742Ssam 
18312742Ssam /*
18412742Ssam  * CLOSELOG -- close the system log
18512742Ssam  */
18625187Seric 
18712742Ssam closelog()
18812742Ssam {
18912742Ssam 
19012742Ssam 	(void) close(LogFile);
19112742Ssam 	LogFile = -1;
19212742Ssam }
19316414Sralph 
19416414Sralph /*
19516414Sralph  * SETLOGMASK -- set the log mask level
19616414Sralph  */
19717526Sralph setlogmask(pmask)
19817526Sralph 	int pmask;
19916414Sralph {
20017526Sralph 	int omask;
20116414Sralph 
20217526Sralph 	omask = LogMask;
20317526Sralph 	if (pmask != 0)
20417526Sralph 		LogMask = pmask;
20517526Sralph 	return (omask);
20616414Sralph }
207