xref: /csrg-svn/lib/libc/gen/syslog.c (revision 21362)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)syslog.c	5.1 (Berkeley) 05/30/85";
9 #endif not lint
10 
11 /*
12  * SYSLOG -- print message on log file
13  *
14  * This routine looks a lot like printf, except that it
15  * outputs to the log file instead of the standard output.
16  * Also:
17  *	adds a timestamp,
18  *	prints the module name in front of the message,
19  *	has some other formatting types (or will sometime),
20  *	adds a newline on the end of the message.
21  *
22  * The output of this routine is intended to be read by /etc/syslogd.
23  *
24  * Author: Eric Allman
25  * Modified to use UNIX domain IPC by Ralph Campbell
26  */
27 
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/file.h>
31 #include <syslog.h>
32 #include <netdb.h>
33 
34 #define	MAXLINE	1024			/* max message size */
35 #define NULL	0			/* manifest */
36 
37 #define mask(p)	(1 << (p))
38 #define IMPORTANT (mask(KERN_EMERG)|mask(KERN_ALERT)|mask(KERN_ERR)|mask(KERN_FAIL)\
39 	|mask(KERN_RECOV)|mask(KERN_INFO)|mask(LOG_EMERG)|mask(LOG_ALERT)\
40 	|mask(LOG_CRIT)|mask(LOG_ERR)|mask(LOG_FAIL))
41 
42 static char	logname[] = "/dev/log";
43 static char	ctty[] = "/dev/console";
44 
45 static int	LogFile = -1;		/* fd for log */
46 static int	LogStat	= 0;		/* status bits, set by openlog() */
47 static char	*LogTag = NULL;		/* string to tag the entry with */
48 		    			/* mask of priorities to be logged */
49 static int	LogMask = ~(mask(KERN_EMERG)|mask(KERN_ALERT)|mask(KERN_ERR)|
50 		    mask(KERN_FAIL)|mask(KERN_RECOV)|mask(KERN_INFO));
51 
52 static struct sockaddr SyslogAddr;
53 
54 extern	int errno, sys_nerr;
55 extern	char *sys_errlist[];
56 
57 syslog(pri, fmt, p0, p1, p2, p3, p4)
58 	int pri;
59 	char *fmt;
60 {
61 	char buf[MAXLINE + 1], outline[MAXLINE + 1];
62 	register char *b, *f, *o;
63 	register int c;
64 	long now;
65 	int pid, olderrno = errno;
66 
67 	/* see if we should just throw out this message */
68 	if (pri <= 0 || pri >= 32 || (mask(pri) & LogMask) == 0)
69 		return;
70 	if (LogFile < 0)
71 		openlog(LogTag, LogStat & ~LOG_ODELAY, 0);
72 	o = outline;
73 	sprintf(o, "<%d>", pri);
74 	o += strlen(o);
75 	if (LogTag) {
76 		strcpy(o, LogTag);
77 		o += strlen(o);
78 	}
79 	if (LogStat & LOG_PID) {
80 		sprintf(o, "[%d]", getpid());
81 		o += strlen(o);
82 	}
83 	time(&now);
84 	sprintf(o, ": %.15s-- ", ctime(&now) + 4);
85 	o += strlen(o);
86 
87 	b = buf;
88 	f = fmt;
89 	while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) {
90 		if (c != '%') {
91 			*b++ = c;
92 			continue;
93 		}
94 		if ((c = *f++) != 'm') {
95 			*b++ = '%';
96 			*b++ = c;
97 			continue;
98 		}
99 		if ((unsigned)olderrno > sys_nerr)
100 			sprintf(b, "error %d", olderrno);
101 		else
102 			strcpy(b, sys_errlist[olderrno]);
103 		b += strlen(b);
104 	}
105 	*b++ = '\n';
106 	*b = '\0';
107 	sprintf(o, buf, p0, p1, p2, p3, p4);
108 	c = strlen(outline);
109 	if (c > MAXLINE)
110 		c = MAXLINE;
111 	if (sendto(LogFile, outline, c, 0, &SyslogAddr, sizeof SyslogAddr) >= 0)
112 		return;
113 	if (!(LogStat & LOG_CONS) && !(mask(pri) & IMPORTANT))
114 		return;
115 	pid = fork();
116 	if (pid == -1)
117 		return;
118 	if (pid == 0) {
119 		LogFile = open(ctty, O_RDWR);
120 		strcat(o, "\r");
121 		write(LogFile, outline, c+1);
122 		close(LogFile);
123 		exit(0);
124 	}
125 	while ((c = wait((int *)0)) > 0 && c != pid)
126 		;
127 }
128 
129 /*
130  * OPENLOG -- open system log
131  */
132 openlog(ident, logstat, logmask)
133 	char *ident;
134 	int logstat, logmask;
135 {
136 
137 	LogTag = (ident != NULL) ? ident : "syslog";
138 	LogStat = logstat;
139 	if (logmask != 0)
140 		LogMask = logmask;
141 	if (LogFile >= 0)
142 		return;
143 	SyslogAddr.sa_family = AF_UNIX;
144 	strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data);
145 	if (!(LogStat & LOG_ODELAY)) {
146 		LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
147 		fcntl(LogFile, F_SETFD, 1);
148 	}
149 }
150 
151 /*
152  * CLOSELOG -- close the system log
153  */
154 closelog()
155 {
156 
157 	(void) close(LogFile);
158 	LogFile = -1;
159 }
160 
161 /*
162  * SETLOGMASK -- set the log mask level
163  */
164 setlogmask(pmask)
165 	int pmask;
166 {
167 	int omask;
168 
169 	omask = LogMask;
170 	if (pmask != 0)
171 		LogMask = pmask;
172 	return (omask);
173 }
174