1 /*
2 * logging.c:
3 * Logging for tpop3d.
4 *
5 * Copyright (c) 2001 Chris Lightfoot.
6 * Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23 static const char rcsid[] = "$Id$";
24
25 #include <errno.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <syslog.h>
31
32 #include "config.h"
33 #include "util.h"
34
35 extern int log_stderr; /* in main.c */
36
37 /* facil:
38 * Log facility names and constants, used to allow configurable logging at
39 * run time. Not all those defined in openlog(3) make sense, so only a few
40 * are listed here. */
41 static struct logfac {
42 char *name;
43 int fac;
44 } facil[] = {
45 {"mail", LOG_MAIL},
46 #ifdef LOG_AUTHPRIV
47 {"authpriv", LOG_AUTHPRIV},
48 #endif
49 #ifdef LOG_AUTH
50 {"auth", LOG_AUTH},
51 #endif
52 {"daemon", LOG_DAEMON},
53 {"user", LOG_USER},
54
55 {"local0", LOG_LOCAL0},
56 {"local1", LOG_LOCAL1},
57 {"local2", LOG_LOCAL2},
58 {"local3", LOG_LOCAL3},
59 {"local4", LOG_LOCAL4},
60 {"local5", LOG_LOCAL5},
61 {"local6", LOG_LOCAL6},
62 {"local7", LOG_LOCAL7},
63 };
64
65 #define NFACIL (sizeof(facil) / sizeof(struct logfac))
66
67 /* level:
68 * Log level names and constants, used to allow configurable logging at
69 * run time. */
70 static struct loglev {
71 char *name;
72 int lev;
73 } level[] = {
74 {"debug", LOG_DEBUG},
75 {"info", LOG_INFO},
76 {"notice", LOG_NOTICE},
77 {"warning", LOG_WARNING},
78 {"warn", LOG_WARNING}, /* DEPRECATED */
79 {"err", LOG_ERR},
80 {"error", LOG_ERR}, /* DEPRECATED */
81 {"crit", LOG_CRIT},
82 {"alert", LOG_ALERT},
83 {"emerg", LOG_EMERG},
84 {"panic", LOG_EMERG}, /* DEPRECATED */
85 };
86
87 #define NLEVEL (sizeof(level) / sizeof(struct loglev))
88
89 static int log_fac;
90 static int log_lev;
91
92 /* log_init:
93 * Start up logging. */
log_init(void)94 void log_init(void) {
95 int fac = LOG_MAIL, lev = LOG_DEBUG, warn_fac = 0, warn_lev = 0;
96 char *sfac, *slev;
97
98 if ((sfac = config_get_string("log-facility"))) {
99 struct logfac *l;
100 warn_fac = 1;
101 for (l = facil; l < facil + NFACIL; ++l)
102 if (strcasecmp(l->name, sfac) == 0) {
103 warn_fac = 0;
104 fac = l->fac;
105 break;
106 }
107 }
108
109 if ((slev = config_get_string("log-level"))) {
110 struct loglev *l;
111 warn_lev = 1;
112 for (l = level; l < level + NLEVEL; ++l)
113 if (strcasecmp(l->name, slev) == 0) {
114 warn_lev = 0;
115 lev = l->lev;
116 break;
117 }
118 }
119
120 log_fac = fac;
121 log_lev = lev;
122
123 openlog("tpop3d", LOG_PID | LOG_NDELAY, fac);
124
125 if (warn_fac == 1)
126 log_print(LOG_ERR, _("log_init: log-facility `%s' unknown, using `mail'"), sfac);
127 if (warn_lev == 1)
128 log_print(LOG_ERR, _("log_init: log-level `%s' unknown, using `debug'"), slev);
129
130 }
131
132
133 /* verrprintf:
134 * Returns a static string with the appropriate arguments printed into it.
135 * (Replaced the dynamically allocating one with a static-buffer based
136 * alternative, since it isn't possible to call vsnprintf(..., ap) in a loop,
137 * as the arg list can't be reset. D'oh.) */
verrprintf(const char * fmt,va_list ap)138 static char *verrprintf(const char *fmt, va_list ap) {
139 char *e = strerror(errno);
140 const char *p, *q;
141 char fmtbuf[1024];
142 static char errbuf[1024];
143
144 *fmtbuf = 0;
145
146 /* First, we need to substitute errors into the string. This would not be
147 * safe in the presence of very long format strings in the rest of the
148 * code, but we can guarantee that won't happen.... */
149 for (p = fmt, q = strstr(p, "%m"); q; p = q, q = strstr(p, "%m")) {
150 strncat(fmtbuf, p, q - p);
151 strcat(fmtbuf, e);
152 q += 2;
153 }
154
155 strcat(fmtbuf, p);
156
157 vsnprintf(errbuf, sizeof(errbuf), fmtbuf, ap);
158
159 return errbuf;
160 }
161
162 /* log_print:
163 * Print a line to the log. */
log_print(int priority,const char * fmt,...)164 void log_print(int priority, const char *fmt, ...) {
165 char *s;
166 va_list ap;
167
168 if(priority > log_lev)
169 return;
170
171 va_start(ap, fmt);
172 s = verrprintf(fmt, ap);
173 va_end(ap);
174 syslog(priority | log_fac, "%s", s);
175 if (log_stderr) fprintf(stderr, "%s\n", s);
176 }
177
178
179