xref: /original-bsd/lib/libc/gen/syslog.c (revision 0fc6f013)
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 #if defined(LIBC_SCCS) && !defined(lint)
8 static char sccsid[] = "@(#)syslog.c	5.9 (Berkeley) 05/07/86";
9 #endif LIBC_SCCS and 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 <sys/signal.h>
32 #include <sys/syslog.h>
33 #include <netdb.h>
34 #include <strings.h>
35 
36 #define	MAXLINE	1024			/* max message size */
37 #define NULL	0			/* manifest */
38 
39 #define PRIMASK(p)	(1 << ((p) & LOG_PRIMASK))
40 #define PRIFAC(p)	(((p) & LOG_FACMASK) >> 3)
41 #define IMPORTANT 	LOG_ERR
42 
43 static char	logname[] = "/dev/log";
44 static char	ctty[] = "/dev/console";
45 
46 static int	LogFile = -1;		/* fd for log */
47 static int	LogStat	= 0;		/* status bits, set by openlog() */
48 static char	*LogTag = "syslog";	/* string to tag the entry with */
49 static int	LogMask = 0xff;		/* mask of priorities to be logged */
50 static int	LogFacility = LOG_USER;	/* default facility code */
51 
52 static struct sockaddr SyslogAddr;	/* AF_UNIX address of local logger */
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 || PRIFAC(pri) >= LOG_NFACILITIES || (PRIMASK(pri) & LogMask) == 0)
69 		return;
70 	if (LogFile < 0)
71 		openlog(LogTag, LogStat | LOG_NDELAY, 0);
72 
73 	/* set default facility if none specified */
74 	if ((pri & LOG_FACMASK) == 0)
75 		pri |= LogFacility;
76 
77 	/* build the message */
78 	o = outline;
79 	sprintf(o, "<%d>", pri);
80 	o += strlen(o);
81 	time(&now);
82 	sprintf(o, "%.15s ", ctime(&now) + 4);
83 	o += strlen(o);
84 	if (LogTag) {
85 		strcpy(o, LogTag);
86 		o += strlen(o);
87 	}
88 	if (LogStat & LOG_PID) {
89 		sprintf(o, "[%d]", getpid());
90 		o += strlen(o);
91 	}
92 	if (LogTag) {
93 		strcpy(o, ": ");
94 		o += 2;
95 	}
96 
97 	b = buf;
98 	f = fmt;
99 	while ((c = *f++) != '\0' && c != '\n' && b < &buf[MAXLINE]) {
100 		if (c != '%') {
101 			*b++ = c;
102 			continue;
103 		}
104 		if ((c = *f++) != 'm') {
105 			*b++ = '%';
106 			*b++ = c;
107 			continue;
108 		}
109 		if ((unsigned)olderrno > sys_nerr)
110 			sprintf(b, "error %d", olderrno);
111 		else
112 			strcpy(b, sys_errlist[olderrno]);
113 		b += strlen(b);
114 	}
115 	*b++ = '\n';
116 	*b = '\0';
117 	sprintf(o, buf, p0, p1, p2, p3, p4);
118 	c = strlen(outline);
119 	if (c > MAXLINE)
120 		c = MAXLINE;
121 
122 	/* output the message to the local logger */
123 	if (sendto(LogFile, outline, c, 0, &SyslogAddr, sizeof SyslogAddr) >= 0)
124 		return;
125 	if (!(LogStat & LOG_CONS))
126 		return;
127 
128 	/* output the message to the console */
129 	pid = vfork();
130 	if (pid == -1)
131 		return;
132 	if (pid == 0) {
133 		int fd;
134 
135 		signal(SIGALRM, SIG_DFL);
136 		sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
137 		alarm(5);
138 		fd = open(ctty, O_WRONLY);
139 		alarm(0);
140 		strcat(o, "\r");
141 		o = index(outline, '>') + 1;
142 		write(fd, o, c + 1 - (o - outline));
143 		close(fd);
144 		_exit(0);
145 	}
146 	if (!(LogStat & LOG_NOWAIT))
147 		while ((c = wait((int *)0)) > 0 && c != pid)
148 			;
149 }
150 
151 /*
152  * OPENLOG -- open system log
153  */
154 
155 openlog(ident, logstat, logfac)
156 	char *ident;
157 	int logstat, logfac;
158 {
159 	if (ident != NULL)
160 		LogTag = ident;
161 	LogStat = logstat;
162 	if (logfac != 0)
163 		LogFacility = logfac & LOG_FACMASK;
164 	if (LogFile >= 0)
165 		return;
166 	SyslogAddr.sa_family = AF_UNIX;
167 	strncpy(SyslogAddr.sa_data, logname, sizeof SyslogAddr.sa_data);
168 	if (LogStat & LOG_NDELAY) {
169 		LogFile = socket(AF_UNIX, SOCK_DGRAM, 0);
170 		fcntl(LogFile, F_SETFD, 1);
171 	}
172 }
173 
174 /*
175  * CLOSELOG -- close the system log
176  */
177 
178 closelog()
179 {
180 
181 	(void) close(LogFile);
182 	LogFile = -1;
183 }
184 
185 /*
186  * SETLOGMASK -- set the log mask level
187  */
188 setlogmask(pmask)
189 	int pmask;
190 {
191 	int omask;
192 
193 	omask = LogMask;
194 	if (pmask != 0)
195 		LogMask = pmask;
196 	return (omask);
197 }
198