xref: /original-bsd/lib/libc/gen/syslog.c (revision dfdcf295)
1 /*
2  * Copyright (c) 1983, 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)syslog.c	5.30 (Berkeley) 09/30/90";
10 #endif /* LIBC_SCCS and not lint */
11 
12 #include <sys/types.h>
13 #include <sys/socket.h>
14 #include <sys/file.h>
15 #include <sys/syslog.h>
16 #include <sys/uio.h>
17 #include <sys/errno.h>
18 #include <netdb.h>
19 #include <string.h>
20 #include <varargs.h>
21 #include <paths.h>
22 #include <stdio.h>
23 
24 static int	LogFile = -1;		/* fd for log */
25 static int	connected;		/* have done connect */
26 static int	LogStat = 0;		/* status bits, set by openlog() */
27 static char	*LogTag = "syslog";	/* string to tag the entry with */
28 static int	LogFacility = LOG_USER;	/* default facility code */
29 
30 /*
31  * syslog, vsyslog --
32  *	print message on log file; output is intended for syslogd(8).
33  */
34 syslog(pri, fmt, args)
35 	int pri, args;
36 	char *fmt;
37 {
38 	return(vsyslog(pri, fmt, &args));
39 }
40 
41 vsyslog(pri, fmt, ap)
42 	int pri;
43 	register char *fmt;
44 	va_list ap;
45 {
46 	register int cnt;
47 	register char *p;
48 	time_t now, time();
49 	int fd, saved_errno;
50 	char tbuf[2048], fmt_cpy[1024], *stdp, *ctime();
51 
52 	/* check for invalid bits or no priority set */
53 	if (!LOG_PRI(pri) || (pri &~ (LOG_PRIMASK|LOG_FACMASK))) {
54 		errno = EINVAL;
55 		return(-1);
56 	}
57 
58 	saved_errno = errno;
59 
60 	/* set default facility if none specified */
61 	if ((pri & LOG_FACMASK) == 0)
62 		pri |= LogFacility;
63 
64 	/* build the message */
65 	(void)time(&now);
66 	(void)sprintf(tbuf, "<%d>%.15s ", pri, ctime(&now) + 4);
67 	for (p = tbuf; *p; ++p);
68 	if (LogStat & LOG_PERROR)
69 		stdp = p;
70 	if (LogTag) {
71 		(void)strcpy(p, LogTag);
72 		for (; *p; ++p);
73 	}
74 	if (LogStat & LOG_PID) {
75 		(void)sprintf(p, "[%d]", getpid());
76 		for (; *p; ++p);
77 	}
78 	if (LogTag) {
79 		*p++ = ':';
80 		*p++ = ' ';
81 	}
82 
83 	/* substitute error message for %m */
84 	{
85 		register char ch, *t1, *t2;
86 		char *strerror();
87 
88 		for (t1 = fmt_cpy; ch = *fmt; ++fmt)
89 			if (ch == '%' && fmt[1] == 'm') {
90 				++fmt;
91 				for (t2 = strerror(saved_errno);
92 				    *t1 = *t2++; ++t1);
93 			}
94 			else
95 				*t1++ = ch;
96 		*t1 = '\0';
97 	}
98 
99 	(void)vsprintf(p, fmt_cpy, ap);
100 
101 	cnt = strlen(tbuf);
102 
103 	/* output to stderr if requested */
104 	if (LogStat & LOG_PERROR) {
105 		struct iovec iov[2];
106 		register struct iovec *v = iov;
107 
108 		v->iov_base = stdp;
109 		v->iov_len = cnt - (stdp - tbuf);
110 		++v;
111 		v->iov_base = "\n";
112 		v->iov_len = 1;
113 		(void)writev(2, iov, 2);
114 	}
115 
116 	/* get connected, output the message to the local logger */
117 	if ((connected || !openlog(LogTag, LogStat | LOG_NDELAY, 0)) &&
118 	    send(LogFile, tbuf, cnt, 0) >= 0)
119 		return(0);
120 
121 	/* see if should attempt the console */
122 	if (!(LogStat&LOG_CONS))
123 		return(-1);
124 
125 	/*
126 	 * Output the message to the console; don't worry about blocking,
127 	 * if console blocks everything will.  Make sure the error reported
128 	 * is the one from the syslogd failure.
129 	 */
130 	saved_errno = errno;
131 	if ((fd = open(_PATH_CONSOLE, O_WRONLY, 0)) >= 0) {
132 		(void)strcat(tbuf, "\r\n");
133 		cnt += 2;
134 		p = index(tbuf, '>') + 1;
135 		(void)write(fd, p, cnt - (p - tbuf));
136 		(void)close(fd);
137 	} else
138 		errno = saved_errno;
139 	return(-1);
140 }
141 
142 static struct sockaddr SyslogAddr;	/* AF_UNIX address of local logger */
143 
144 openlog(ident, logstat, logfac)
145 	char *ident;
146 	int logstat, logfac;
147 {
148 	int saved_errno;
149 
150 	if (ident != NULL)
151 		LogTag = ident;
152 	LogStat = logstat;
153 	if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
154 		LogFacility = logfac;
155 
156 	if (LogFile == -1) {
157 		SyslogAddr.sa_family = AF_UNIX;
158 		(void)strncpy(SyslogAddr.sa_data, _PATH_LOG,
159 		    sizeof(SyslogAddr.sa_data));
160 		if (LogStat & LOG_NDELAY) {
161 			if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
162 				return(-1);
163 			(void)fcntl(LogFile, F_SETFD, 1);
164 		}
165 	}
166 	if (LogFile != -1 && !connected)
167 		if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) == -1) {
168 			saved_errno = errno;
169 			(void)close(LogFile);
170 			errno = saved_errno;
171 			LogFile = -1;
172 			return(-1);
173 		} else
174 			connected = 1;
175 	return(0);
176 }
177 
178 closelog()
179 {
180 	int rval;
181 
182 	rval = close(LogFile);
183 	LogFile = -1;
184 	connected = 0;
185 	return(rval);
186 }
187 
188 static int	LogMask = 0xff;		/* mask of priorities to be logged */
189 
190 /* setlogmask -- set the log mask level */
191 setlogmask(pmask)
192 	int pmask;
193 {
194 	int omask;
195 
196 	omask = LogMask;
197 	if (pmask != 0)
198 		LogMask = pmask;
199 	return (omask);
200 }
201