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

# User Rev Content
1 root 1.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