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