source: trunk/third/openssh/log.c @ 18759

Revision 18759, 8.8 KB checked in by zacheiss, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18758, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Author: Tatu Ylonen <ylo@cs.hut.fi>
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 *                    All rights reserved
5 *
6 * As far as I am concerned, the code I have written for this software
7 * can be used freely for any purpose.  Any derived versions of this
8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell".
11 */
12/*
13 * Copyright (c) 2000 Markus Friedl.  All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include "includes.h"
37RCSID("$OpenBSD: log.c,v 1.24 2002/07/19 15:43:33 markus Exp $");
38
39#include "log.h"
40#include "xmalloc.h"
41
42#include <syslog.h>
43
44static LogLevel log_level = SYSLOG_LEVEL_INFO;
45static int log_on_stderr = 1;
46static int log_facility = LOG_AUTH;
47static char *argv0;
48
49extern char *__progname;
50
51/* textual representation of log-facilities/levels */
52
53static struct {
54        const char *name;
55        SyslogFacility val;
56} log_facilities[] = {
57        { "DAEMON",     SYSLOG_FACILITY_DAEMON },
58        { "USER",       SYSLOG_FACILITY_USER },
59        { "AUTH",       SYSLOG_FACILITY_AUTH },
60#ifdef LOG_AUTHPRIV
61        { "AUTHPRIV",   SYSLOG_FACILITY_AUTHPRIV },
62#endif
63        { "LOCAL0",     SYSLOG_FACILITY_LOCAL0 },
64        { "LOCAL1",     SYSLOG_FACILITY_LOCAL1 },
65        { "LOCAL2",     SYSLOG_FACILITY_LOCAL2 },
66        { "LOCAL3",     SYSLOG_FACILITY_LOCAL3 },
67        { "LOCAL4",     SYSLOG_FACILITY_LOCAL4 },
68        { "LOCAL5",     SYSLOG_FACILITY_LOCAL5 },
69        { "LOCAL6",     SYSLOG_FACILITY_LOCAL6 },
70        { "LOCAL7",     SYSLOG_FACILITY_LOCAL7 },
71        { NULL,         SYSLOG_FACILITY_NOT_SET }
72};
73
74static struct {
75        const char *name;
76        LogLevel val;
77} log_levels[] =
78{
79        { "QUIET",      SYSLOG_LEVEL_QUIET },
80        { "FATAL",      SYSLOG_LEVEL_FATAL },
81        { "ERROR",      SYSLOG_LEVEL_ERROR },
82        { "INFO",       SYSLOG_LEVEL_INFO },
83        { "VERBOSE",    SYSLOG_LEVEL_VERBOSE },
84        { "DEBUG",      SYSLOG_LEVEL_DEBUG1 },
85        { "DEBUG1",     SYSLOG_LEVEL_DEBUG1 },
86        { "DEBUG2",     SYSLOG_LEVEL_DEBUG2 },
87        { "DEBUG3",     SYSLOG_LEVEL_DEBUG3 },
88        { NULL,         SYSLOG_LEVEL_NOT_SET }
89};
90
91SyslogFacility
92log_facility_number(char *name)
93{
94        int i;
95
96        if (name != NULL)
97                for (i = 0; log_facilities[i].name; i++)
98                        if (strcasecmp(log_facilities[i].name, name) == 0)
99                                return log_facilities[i].val;
100        return SYSLOG_FACILITY_NOT_SET;
101}
102
103LogLevel
104log_level_number(char *name)
105{
106        int i;
107
108        if (name != NULL)
109                for (i = 0; log_levels[i].name; i++)
110                        if (strcasecmp(log_levels[i].name, name) == 0)
111                                return log_levels[i].val;
112        return SYSLOG_LEVEL_NOT_SET;
113}
114
115/* Error messages that should be logged. */
116
117void
118error(const char *fmt,...)
119{
120        va_list args;
121
122        va_start(args, fmt);
123        do_log(SYSLOG_LEVEL_ERROR, fmt, args);
124        va_end(args);
125}
126
127/* Log this message (information that usually should go to the log). */
128
129void
130log(const char *fmt,...)
131{
132        va_list args;
133
134        va_start(args, fmt);
135        do_log(SYSLOG_LEVEL_INFO, fmt, args);
136        va_end(args);
137}
138
139/* More detailed messages (information that does not need to go to the log). */
140
141void
142verbose(const char *fmt,...)
143{
144        va_list args;
145
146        va_start(args, fmt);
147        do_log(SYSLOG_LEVEL_VERBOSE, fmt, args);
148        va_end(args);
149}
150
151/* Debugging messages that should not be logged during normal operation. */
152
153void
154debug(const char *fmt,...)
155{
156        va_list args;
157
158        va_start(args, fmt);
159        do_log(SYSLOG_LEVEL_DEBUG1, fmt, args);
160        va_end(args);
161}
162
163void
164debug2(const char *fmt,...)
165{
166        va_list args;
167
168        va_start(args, fmt);
169        do_log(SYSLOG_LEVEL_DEBUG2, fmt, args);
170        va_end(args);
171}
172
173void
174debug3(const char *fmt,...)
175{
176        va_list args;
177
178        va_start(args, fmt);
179        do_log(SYSLOG_LEVEL_DEBUG3, fmt, args);
180        va_end(args);
181}
182
183/* Fatal cleanup */
184
185struct fatal_cleanup {
186        struct fatal_cleanup *next;
187        void (*proc) (void *);
188        void *context;
189};
190
191static struct fatal_cleanup *fatal_cleanups = NULL;
192
193/* Registers a cleanup function to be called by fatal() before exiting. */
194
195void
196fatal_add_cleanup(void (*proc) (void *), void *context)
197{
198        struct fatal_cleanup *cu;
199
200        cu = xmalloc(sizeof(*cu));
201        cu->proc = proc;
202        cu->context = context;
203        cu->next = fatal_cleanups;
204        fatal_cleanups = cu;
205}
206
207/* Removes a cleanup frunction to be called at fatal(). */
208
209void
210fatal_remove_cleanup(void (*proc) (void *context), void *context)
211{
212        struct fatal_cleanup **cup, *cu;
213
214        for (cup = &fatal_cleanups; *cup; cup = &cu->next) {
215                cu = *cup;
216                if (cu->proc == proc && cu->context == context) {
217                        *cup = cu->next;
218                        xfree(cu);
219                        return;
220                }
221        }
222        fatal("fatal_remove_cleanup: no such cleanup function: 0x%lx 0x%lx",
223            (u_long) proc, (u_long) context);
224}
225
226/* Remove all cleanups, to be called after fork() */
227void
228fatal_remove_all_cleanups(void)
229{
230        struct fatal_cleanup *cu, *next_cu;
231
232        for (cu = fatal_cleanups; cu; cu = next_cu) {
233                next_cu = cu->next;
234                xfree(cu);
235        }
236}
237
238/* Cleanup and exit */
239void
240fatal_cleanup(void)
241{
242        struct fatal_cleanup *cu, *next_cu;
243        static int called = 0;
244
245        if (called)
246                exit(255);
247        called = 1;
248        /* Call cleanup functions. */
249        for (cu = fatal_cleanups; cu; cu = next_cu) {
250                next_cu = cu->next;
251                debug("Calling cleanup 0x%lx(0x%lx)",
252                    (u_long) cu->proc, (u_long) cu->context);
253                (*cu->proc) (cu->context);
254        }
255        exit(255);
256}
257
258
259/*
260 * Initialize the log.
261 */
262
263void
264log_init(char *av0, LogLevel level, SyslogFacility facility, int on_stderr)
265{
266        argv0 = av0;
267
268        switch (level) {
269        case SYSLOG_LEVEL_QUIET:
270        case SYSLOG_LEVEL_FATAL:
271        case SYSLOG_LEVEL_ERROR:
272        case SYSLOG_LEVEL_INFO:
273        case SYSLOG_LEVEL_VERBOSE:
274        case SYSLOG_LEVEL_DEBUG1:
275        case SYSLOG_LEVEL_DEBUG2:
276        case SYSLOG_LEVEL_DEBUG3:
277                log_level = level;
278                break;
279        default:
280                fprintf(stderr, "Unrecognized internal syslog level code %d\n",
281                    (int) level);
282                exit(1);
283        }
284
285        log_on_stderr = on_stderr;
286        if (on_stderr)
287                return;
288
289        switch (facility) {
290        case SYSLOG_FACILITY_DAEMON:
291                log_facility = LOG_DAEMON;
292                break;
293        case SYSLOG_FACILITY_USER:
294                log_facility = LOG_USER;
295                break;
296        case SYSLOG_FACILITY_AUTH:
297                log_facility = LOG_AUTH;
298                break;
299#ifdef LOG_AUTHPRIV
300        case SYSLOG_FACILITY_AUTHPRIV:
301                log_facility = LOG_AUTHPRIV;
302                break;
303#endif
304        case SYSLOG_FACILITY_LOCAL0:
305                log_facility = LOG_LOCAL0;
306                break;
307        case SYSLOG_FACILITY_LOCAL1:
308                log_facility = LOG_LOCAL1;
309                break;
310        case SYSLOG_FACILITY_LOCAL2:
311                log_facility = LOG_LOCAL2;
312                break;
313        case SYSLOG_FACILITY_LOCAL3:
314                log_facility = LOG_LOCAL3;
315                break;
316        case SYSLOG_FACILITY_LOCAL4:
317                log_facility = LOG_LOCAL4;
318                break;
319        case SYSLOG_FACILITY_LOCAL5:
320                log_facility = LOG_LOCAL5;
321                break;
322        case SYSLOG_FACILITY_LOCAL6:
323                log_facility = LOG_LOCAL6;
324                break;
325        case SYSLOG_FACILITY_LOCAL7:
326                log_facility = LOG_LOCAL7;
327                break;
328        default:
329                fprintf(stderr,
330                    "Unrecognized internal syslog facility code %d\n",
331                    (int) facility);
332                exit(1);
333        }
334}
335
336#define MSGBUFSIZ 1024
337
338void
339do_log(LogLevel level, const char *fmt, va_list args)
340{
341        char msgbuf[MSGBUFSIZ];
342        char fmtbuf[MSGBUFSIZ];
343        char *txt = NULL;
344        int pri = LOG_INFO;
345
346        if (level > log_level)
347                return;
348
349        switch (level) {
350        case SYSLOG_LEVEL_FATAL:
351                if (!log_on_stderr)
352                        txt = "fatal";
353                pri = LOG_CRIT;
354                break;
355        case SYSLOG_LEVEL_ERROR:
356                if (!log_on_stderr)
357                        txt = "error";
358                pri = LOG_ERR;
359                break;
360        case SYSLOG_LEVEL_INFO:
361                pri = LOG_INFO;
362                break;
363        case SYSLOG_LEVEL_VERBOSE:
364                pri = LOG_INFO;
365                break;
366        case SYSLOG_LEVEL_DEBUG1:
367                txt = "debug1";
368                pri = LOG_DEBUG;
369                break;
370        case SYSLOG_LEVEL_DEBUG2:
371                txt = "debug2";
372                pri = LOG_DEBUG;
373                break;
374        case SYSLOG_LEVEL_DEBUG3:
375                txt = "debug3";
376                pri = LOG_DEBUG;
377                break;
378        default:
379                txt = "internal error";
380                pri = LOG_ERR;
381                break;
382        }
383        if (txt != NULL) {
384                snprintf(fmtbuf, sizeof(fmtbuf), "%s: %s", txt, fmt);
385                vsnprintf(msgbuf, sizeof(msgbuf), fmtbuf, args);
386        } else {
387                vsnprintf(msgbuf, sizeof(msgbuf), fmt, args);
388        }
389        if (log_on_stderr) {
390                fprintf(stderr, "%s\r\n", msgbuf);
391        } else {
392                openlog(argv0 ? argv0 : __progname, LOG_PID, log_facility);
393                syslog(pri, "%.500s", msgbuf);
394                closelog();
395        }
396}
Note: See TracBrowser for help on using the repository browser.