xref: /csrg-svn/lib/libc/gen/syslog.c (revision 34821)
1 /*
2  * Copyright (c) 1983, 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #if defined(LIBC_SCCS) && !defined(lint)
19 static char sccsid[] = "@(#)syslog.c	5.16 (Berkeley) 06/27/88";
20 #endif /* LIBC_SCCS and not lint */
21 
22 /*
23  * SYSLOG -- print message on log file
24  *
25  * This routine looks a lot like printf, except that it
26  * outputs to the log file instead of the standard output.
27  * Also:
28  *	adds a timestamp,
29  *	prints the module name in front of the message,
30  *	has some other formatting types (or will sometime),
31  *	adds a newline on the end of the message.
32  *
33  * The output of this routine is intended to be read by /etc/syslogd.
34  *
35  * Author: Eric Allman
36  * Modified to use UNIX domain IPC by Ralph Campbell
37  */
38 
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <sys/file.h>
42 #include <sys/signal.h>
43 #include <sys/syslog.h>
44 #include <netdb.h>
45 #include <strings.h>
46 
47 #define	MAXLINE	1024			/* max message size */
48 #define NULL	0			/* manifest */
49 
50 #define IMPORTANT 	LOG_ERR
51 
52 static char	logname[] = "/dev/log";
53 static char	ctty[] = "/dev/console";
54 
55 static int	LogFile = -1;		/* fd for log */
56 static int	connected;		/* have done connect */
57 static int	LogStat	= 0;		/* status bits, set by openlog() */
58 static char	*LogTag = "syslog";	/* string to tag the entry with */
59 static int	LogMask = 0xff;		/* mask of priorities to be logged */
60 static int	LogFacility = LOG_USER;	/* default facility code */
61 
62 static struct sockaddr SyslogAddr;	/* AF_UNIX address of local logger */
63 
64 extern	int errno, sys_nerr;
65 extern	char *sys_errlist[];
66 
67 syslog(pri, fmt, p0, p1, p2, p3, p4)
68 	int pri;
69 	char *fmt;
70 {
71 	char buf[MAXLINE + 1], outline[MAXLINE + 1];
72 	register char *b, *f, *o;
73 	register int c;
74 	long now;
75 	int pid, olderrno = errno;
76 
77 	/* see if we should just throw out this message */
78 	if ((unsigned) LOG_FAC(pri) >= LOG_NFACILITIES ||
79 	    LOG_MASK(LOG_PRI(pri)) == 0 ||
80 	    (pri &~ (LOG_PRIMASK|LOG_FACMASK)) != 0)
81 		return;
82 	if (LogFile < 0 || !connected)
83 		openlog(LogTag, LogStat | LOG_NDELAY, 0);
84 
85 	/* set default facility if none specified */
86 	if ((pri & LOG_FACMASK) == 0)
87 		pri |= LogFacility;
88 
89 	/* build the message */
90 	o = outline;
91 	(void)sprintf(o, "<%d>", pri);
92 	o += strlen(o);
93 	time(&now);
94 	(void)sprintf(o, "%.15s ", ctime(&now) + 4);
95 	o += strlen(o);
96 	if (LogTag) {
97 		strcpy(o, LogTag);
98 		o += strlen(o);
99 	}
100 	if (LogStat & LOG_PID) {
101 		(void)sprintf(o, "[%d]", getpid());
102 		o += strlen(o);
103 	}
104 	if (LogTag) {
105 		strcpy(o, ": ");
106 		o += 2;
107 	}
108 
109 	b = buf;
110 	f = fmt;
111 	while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) {
112 		if (c != '%') {
113 			*b++ = c;
114 			continue;
115 		}
116 		if ((c = *f++) != 'm') {
117 			*b++ = '%';
118 			*b++ = c;
119 			continue;
120 		}
121 		if ((unsigned)olderrno > sys_nerr)
122 			(void)sprintf(b, "error %d", olderrno);
123 		else
124 			strcpy(b, sys_errlist[olderrno]);
125 		b += strlen(b);
126 	}
127 	*b++ = '\n';
128 	*b = '\0';
129 	(void)sprintf(o, buf, p0, p1, p2, p3, p4);
130 	c = strlen(outline);
131 	if (c > MAXLINE)
132 		c = MAXLINE;
133 
134 	/* output the message to the local logger */
135 	if (send(LogFile, outline, c, 0) >= 0)
136 		return;
137 	if (!(LogStat & LOG_CONS))
138 		return;
139 
140 	/* output the message to the console */
141 	pid = vfork();
142 	if (pid == -1)
143 		return;
144 	if (pid == 0) {
145 		int fd;
146 
147 		signal(SIGALRM, SIG_DFL);
148 		sigsetmask(sigblock(0L) & ~sigmask(SIGALRM));
149 		alarm(5);
150 		fd = open(ctty, O_WRONLY);
151 		alarm(0);
152 		strcat(o, "\r");
153 		o = index(outline, '>') + 1;
154 		write(fd, o, c + 1 - (o - outline));
155 		close(fd);
156 		_exit(0);
157 	}
158 	if (!(LogStat & LOG_NOWAIT))
159 		while ((c = wait((int *)0)) > 0 && c != pid)
160 			;
161 }
162 
163 /*
164  * OPENLOG -- open system log
165  */
166 
167 openlog(ident, logstat, logfac)
168 	char *ident;
169 	int logstat, logfac;
170 {
171 	if (ident != NULL)
172 		LogTag = ident;
173 	LogStat = logstat;
174 	if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
175 		LogFacility = logfac;
176 	if (LogFile == -1) {
177 		SyslogAddr.sa_family = AF_UNIX;
178 		strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data);
179 		if (LogStat & LOG_NDELAY) {
180 			LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
181 			fcntl(LogFile, F_SETFD, 1);
182 		}
183 	}
184 	if (LogFile != -1 && !connected &&
185 	    connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) != -1)
186 		connected = 1;
187 }
188 
189 /*
190  * CLOSELOG -- close the system log
191  */
192 
193 closelog()
194 {
195 
196 	(void) close(LogFile);
197 	LogFile = -1;
198 	connected = 0;
199 }
200 
201 /*
202  * SETLOGMASK -- set the log mask level
203  */
204 setlogmask(pmask)
205 	int pmask;
206 {
207 	int omask;
208 
209 	omask = LogMask;
210 	if (pmask != 0)
211 		LogMask = pmask;
212 	return (omask);
213 }
214