ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/thttpd/syslog.c
Revision: 1.1
Committed: Mon Jun 18 21:11:57 2001 UTC (23 years ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: mp_j, dp_j, cp_j, HEAD
Branch point for: connpatch, dirpatch, mmapppatch
Log Message:
*** empty log message ***

File Contents

# Content
1 /* This is a special version of syslog.c that has been modified to
2 ** always use network sockets, so that it can be called from within
3 ** a chroot() tree. It has also been made more portable. -JP
4 */
5
6 /*
7 * Copyright (c) 1983, 1988, 1993
8 * The Regents of the University of California. All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39 #ifdef __alpha
40 #define _XOPEN_SOURCE_EXTENDED
41 #endif
42
43 /* Always use a network socket. This lets us run in a chroot() tree. */
44 #define USE_INET
45
46 #if defined(LIBC_SCCS) && !defined(lint)
47 static char sccsid[] = "@(#)syslog.c 8.9 (Berkeley) 9/4/95";
48 #endif /* LIBC_SCCS and not lint */
49
50 #include <sys/param.h>
51 #include <sys/types.h>
52 #include <sys/socket.h>
53 #include <sys/uio.h>
54 #ifdef USE_INET
55 #include <netinet/in.h>
56 #include <arpa/inet.h>
57 #endif
58 #include <syslog.h>
59 #include <netdb.h>
60
61 #include <errno.h>
62 #include <fcntl.h>
63 #include <stdio.h>
64 #include <string.h>
65 #include <time.h>
66 #include <unistd.h>
67
68 #ifdef HAVE_PATHS_H
69 # include <paths.h>
70 #endif
71 #ifndef _PATH_CONSOLE
72 # define _PATH_CONSOLE "/dev/console"
73 #endif
74 #ifndef _PATH_LOG
75 # define _PATH_LOG "/dev/log"
76 #endif
77
78 #include <stdarg.h>
79
80 #ifndef HAVE_STRERROR
81 char *strerror(int);
82 #endif
83
84 #ifndef LOG_PRI
85 # define LOG_PRI(p) ((p) & LOG_PRIMASK)
86 #endif
87
88 #ifndef LOG_PERROR
89 # define LOG_PERROR 0
90 #endif
91
92 #ifndef STDERR_FILENO
93 #define STDERR_FILENO 2
94 #endif
95
96 #define BUFSLOP 1024 /* overflow space */
97
98 static int LogFile = -1; /* fd for log */
99 static int connected; /* have done connect */
100 static int LogStat = 0; /* status bits, set by openlog() */
101 static const char *LogTag = NULL; /* string to tag the entry with */
102 static int LogFacility = LOG_USER; /* default facility code */
103 static int LogMask = 0xff; /* mask of priorities to be logged */
104 #ifdef HAVE__PROGNAME
105 extern char *__progname; /* Program name, from crt0. */
106 #else
107 char *__progname = NULL;
108 #endif
109
110 void syslog(int pri, const char *fmt, ...);
111 void openlog(const char *ident, int logstat, int logfac);
112 void closelog(void);
113
114 /*
115 * syslog --
116 * print message on log file; output is intended for syslogd(8).
117 */
118 void
119 syslog(int pri, const char *fmt, ...)
120 {
121 register int cnt;
122 register char ch, *p, *t;
123 time_t now;
124 int fd, saved_errno;
125 #ifndef HAVE_VSNPRINTF
126 int panic = 0;
127 #endif
128 static int maxsend = BUFSIZ;
129 char *stdp, fmt_cpy[1024], tbuf[BUFSIZ + BUFSLOP];
130 va_list ap;
131
132 #define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
133 /* Check for invalid bits. */
134 if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
135 syslog(INTERNALLOG,
136 "syslog: unknown facility/priority: %x", pri);
137 pri &= LOG_PRIMASK|LOG_FACMASK;
138 }
139
140 /* Check priority against setlogmask values. */
141 if (!(LOG_MASK(LOG_PRI(pri)) & LogMask))
142 return;
143
144 saved_errno = errno;
145
146 /* Set default facility if none specified. */
147 if ((pri & LOG_FACMASK) == 0)
148 pri |= LogFacility;
149
150 /* Get connected. */
151 if (!connected)
152 openlog(LogTag, LogStat | LOG_NDELAY, 0);
153
154 /* Build the message. */
155 (void)time(&now);
156 sprintf(tbuf, "<%d>", pri);
157 p = tbuf + strlen(tbuf);
158 strftime(p, sizeof (tbuf) - (p - tbuf), "%h %e %T ", localtime(&now));
159 p += strlen(p);
160 stdp = p;
161 if (LogTag == NULL)
162 LogTag = __progname;
163 if (LogTag != NULL) {
164 char *q = strrchr(LogTag, '/');
165
166 if (q != NULL)
167 LogTag = ++q;
168 sprintf(p, "%.20s", LogTag);
169 p += strlen(p);
170 }
171 if (LogStat & LOG_PID) {
172 sprintf(p, "[%ld]", (long) getpid());
173 p += strlen(p);
174 }
175 if (LogTag != NULL) {
176 *p++ = ':';
177 *p++ = ' ';
178 }
179
180 /* Substitute error message for %m. */
181 for (t = fmt_cpy; (ch = *fmt) != '\0'; ++fmt)
182 if (ch == '%' && fmt[1] == 'm') {
183 ++fmt;
184 strcpy(t, strerror(saved_errno));
185 t += strlen(t);
186 } else
187 *t++ = ch;
188 *t = '\0';
189
190 va_start(ap, fmt);
191 #ifdef HAVE_VSNPRINTF
192 cnt = maxsend - (p - tbuf) + 1;
193 p += vsnprintf(p, cnt, fmt_cpy, ap);
194 cnt = p - tbuf;
195 #else
196 vsprintf(p, fmt_cpy, ap);
197 p += strlen(p);
198 cnt = p - tbuf;
199 if (cnt > sizeof tbuf) {
200 /* Panic condition. */
201 panic = 1;
202 }
203 if (cnt > maxsend)
204 cnt = maxsend;
205 #endif
206 va_end(ap);
207
208 /* Output to stderr if requested. */
209 if (LogStat & LOG_PERROR) {
210 struct iovec iov[2];
211 register struct iovec *v = iov;
212
213 v->iov_base = stdp;
214 v->iov_len = cnt - (stdp - tbuf);
215 ++v;
216 v->iov_base = "\n";
217 v->iov_len = 1;
218 (void)writev(STDERR_FILENO, iov, 2);
219 }
220
221 /* Output the message to the local logger. */
222 for (;;) {
223 if (send(LogFile, tbuf, cnt, 0) >= 0)
224 goto done;
225 if (errno != EMSGSIZE || maxsend <= 256)
226 break;
227
228 /* Message was too large -- back it off. */
229 do {
230 maxsend -= 128;
231 } while (cnt < maxsend && maxsend > 256);
232 cnt = maxsend;
233 }
234
235 /*
236 * Output the message to the console; don't worry about blocking,
237 * if console blocks everything will. Make sure the error reported
238 * is the one from the syslogd failure.
239 */
240 if (LogStat & LOG_CONS &&
241 (fd = open(_PATH_CONSOLE, O_WRONLY, 0)) >= 0) {
242 (void)strcat(tbuf, "\r\n");
243 cnt += 2;
244 p = strchr(tbuf, '>') + 1;
245 (void)write(fd, p, cnt - (p - tbuf));
246 (void)close(fd);
247 }
248
249 done: ;
250 #ifndef HAVE_VSNPRINTF
251 /*
252 * If we had a buffer overrun, log a panic and abort.
253 * We can't return because our stack is probably toast.
254 */
255 if (panic) {
256 syslog(LOG_EMERG, "SYSLOG BUFFER OVERRUN -- EXITING");
257 abort();
258 }
259 #endif
260 }
261
262 static struct sockaddr SyslogAddr; /* AF_UNIX address of local logger */
263
264 void
265 openlog(const char *ident, int logstat, int logfac)
266 {
267 if (ident != NULL)
268 LogTag = ident;
269 LogStat = logstat;
270 if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
271 LogFacility = logfac;
272
273 if (LogFile == -1) {
274 #ifndef USE_INET
275 SyslogAddr.sa_family = AF_UNIX;
276 (void)strncpy(SyslogAddr.sa_data, _PATH_LOG,
277 sizeof(SyslogAddr.sa_data));
278 if (LogStat & LOG_NDELAY) {
279 if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
280 return;
281 (void)fcntl(LogFile, F_SETFD, 1);
282 }
283 #else
284 #define satosin(sa) ((struct sockaddr_in *)(sa))
285
286 satosin(&SyslogAddr)->sin_family = AF_INET;
287 satosin(&SyslogAddr)->sin_port = 514;
288 satosin(&SyslogAddr)->sin_addr.s_addr = inet_addr("127.0.0.1");
289 if (LogStat & LOG_NDELAY) {
290 if ((LogFile = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
291 return;
292 (void)fcntl(LogFile, F_SETFD, 1);
293 if (connect(LogFile, &SyslogAddr,
294 sizeof(SyslogAddr)) < 0) {
295 closelog();
296 return;
297 }
298 }
299 #endif
300 }
301 if (LogFile != -1 && !connected) {
302 if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) == -1) {
303 (void)close(LogFile);
304 LogFile = -1;
305 } else
306 connected = 1;
307 }
308 }
309
310 void
311 closelog(void)
312 {
313 (void)close(LogFile);
314 LogFile = -1;
315 connected = 0;
316 }
317
318 #ifdef notdef
319 /* setlogmask -- set the log mask level */
320 int
321 setlogmask(int pmask)
322 {
323 int omask;
324
325 omask = LogMask;
326 if (pmask != 0)
327 LogMask = pmask;
328 return (omask);
329 }
330 #endif