xref: /csrg-svn/lib/libc/gen/syslog.c (revision 34563)
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.15 (Berkeley) 05/31/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 IMPORTANT 	LOG_ERR
47 
48 static char	logname[] = "/dev/log";
49 static char	ctty[] = "/dev/console";
50 
51 static int	LogFile = -1;		/* fd for log */
52 static int	connected;		/* have done connect */
53 static int	LogStat	= 0;		/* status bits, set by openlog() */
54 static char	*LogTag = "syslog";	/* string to tag the entry with */
55 static int	LogMask = 0xff;		/* mask of priorities to be logged */
56 static int	LogFacility = LOG_USER;	/* default facility code */
57 
58 static struct sockaddr SyslogAddr;	/* AF_UNIX address of local logger */
59 
60 extern	int errno, sys_nerr;
61 extern	char *sys_errlist[];
62 
63 syslog(pri, fmt, p0, p1, p2, p3, p4)
64 	int pri;
65 	char *fmt;
66 {
67 	char buf[MAXLINE + 1], outline[MAXLINE + 1];
68 	register char *b, *f, *o;
69 	register int c;
70 	long now;
71 	int pid, olderrno = errno;
72 
73 	/* see if we should just throw out this message */
74 	if ((unsigned) LOG_FAC(pri) >= LOG_NFACILITIES ||
75 	    LOG_MASK(LOG_PRI(pri)) == 0 ||
76 	    (pri &~ (LOG_PRIMASK|LOG_FACMASK)) != 0)
77 		return;
78 	if (LogFile < 0 || !connected)
79 		openlog(LogTag, LogStat | LOG_NDELAY, 0);
80 
81 	/* set default facility if none specified */
82 	if ((pri & LOG_FACMASK) == 0)
83 		pri |= LogFacility;
84 
85 	/* build the message */
86 	o = outline;
87 	(void)sprintf(o, "<%d>", pri);
88 	o += strlen(o);
89 	time(&now);
90 	(void)sprintf(o, "%.15s ", ctime(&now) + 4);
91 	o += strlen(o);
92 	if (LogTag) {
93 		strcpy(o, LogTag);
94 		o += strlen(o);
95 	}
96 	if (LogStat & LOG_PID) {
97 		(void)sprintf(o, "[%d]", getpid());
98 		o += strlen(o);
99 	}
100 	if (LogTag) {
101 		strcpy(o, ": ");
102 		o += 2;
103 	}
104 
105 	b = buf;
106 	f = fmt;
107 	while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) {
108 		if (c != '%') {
109 			*b++ = c;
110 			continue;
111 		}
112 		if ((c = *f++) != 'm') {
113 			*b++ = '%';
114 			*b++ = c;
115 			continue;
116 		}
117 		if ((unsigned)olderrno > sys_nerr)
118 			(void)sprintf(b, "error %d", olderrno);
119 		else
120 			strcpy(b, sys_errlist[olderrno]);
121 		b += strlen(b);
122 	}
123 	*b++ = '\n';
124 	*b = '\0';
125 	(void)sprintf(o, buf, p0, p1, p2, p3, p4);
126 	c = strlen(outline);
127 	if (c > MAXLINE)
128 		c = MAXLINE;
129 
130 	/* output the message to the local logger */
131 	if (send(LogFile, outline, c, 0) >= 0)
132 		return;
133 	if (!(LogStat & LOG_CONS))
134 		return;
135 
136 	/* output the message to the console */
137 	pid = vfork();
138 	if (pid == -1)
139 		return;
140 	if (pid == 0) {
141 		int fd;
142 
143 		signal(SIGALRM, SIG_DFL);
144 		sigsetmask(sigblock(0L) & ~sigmask(SIGALRM));
145 		alarm(5);
146 		fd = open(ctty, O_WRONLY);
147 		alarm(0);
148 		strcat(o, "\r");
149 		o = index(outline, '>') + 1;
150 		write(fd, o, c + 1 - (o - outline));
151 		close(fd);
152 		_exit(0);
153 	}
154 	if (!(LogStat & LOG_NOWAIT))
155 		while ((c = wait((int *)0)) > 0 && c != pid)
156 			;
157 }
158 
159 /*
160  * OPENLOG -- open system log
161  */
162 
163 openlog(ident, logstat, logfac)
164 	char *ident;
165 	int logstat, logfac;
166 {
167 	if (ident != NULL)
168 		LogTag = ident;
169 	LogStat = logstat;
170 	if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
171 		LogFacility = logfac;
172 	if (LogFile == -1) {
173 		SyslogAddr.sa_family = AF_UNIX;
174 		strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data);
175 		if (LogStat & LOG_NDELAY) {
176 			LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
177 			fcntl(LogFile, F_SETFD, 1);
178 		}
179 	}
180 	if (LogFile != -1 && !connected &&
181 	    connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) != -1)
182 		connected = 1;
183 }
184 
185 /*
186  * CLOSELOG -- close the system log
187  */
188 
189 closelog()
190 {
191 
192 	(void) close(LogFile);
193 	LogFile = -1;
194 	connected = 0;
195 }
196 
197 /*
198  * SETLOGMASK -- set the log mask level
199  */
200 setlogmask(pmask)
201 	int pmask;
202 {
203 	int omask;
204 
205 	omask = LogMask;
206 	if (pmask != 0)
207 		LogMask = pmask;
208 	return (omask);
209 }
210