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