2 * log.c Logging module.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2001,2006 The FreeRADIUS server project
21 * Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
22 * Copyright 2000 Alan DeKok <aland@ox.org>
23 * Copyright 2001 Chad Miller <cmiller@surfsouth.com>
26 #include <freeradius-devel/ident.h>
29 #include <freeradius-devel/radiusd.h>
31 #ifdef HAVE_SYS_STAT_H
37 /* keep track of whether we've run openlog() */
38 static int openlog_run = 0;
41 static int can_update_log_fp = TRUE;
42 static FILE *log_fp = NULL;
45 * Logging facility names
47 static const FR_NAME_NUMBER levels[] = {
48 { ": Debug: ", L_DBG },
49 { ": Auth: ", L_AUTH },
50 { ": Proxy: ", L_PROXY },
51 { ": Info: ", L_INFO },
52 { ": Acct: ", L_ACCT },
53 { ": Error: ", L_ERR },
58 * Log the message to the logfile. Include the severity and
61 int vradlog(int lvl, const char *fmt, va_list ap)
63 struct main_config_t *myconfig = &mainconfig;
64 int fd = myconfig->radlog_fd;
68 int len, print_timestamp = 0;
71 * NOT debugging, and trying to log debug messages.
73 * Throw the message away.
75 if (!debug_flag && (lvl == L_DBG)) {
80 * If we don't want any messages, then
83 if (myconfig->radlog_dest == RADLOG_NULL) {
88 * Don't print timestamps to syslog, it does that for us.
89 * Don't print timestamps for low levels of debugging.
91 * Print timestamps for non-debugging, and for high levels
94 if ((myconfig->radlog_dest != RADLOG_SYSLOG) &&
95 (debug_flag != 1) && (debug_flag != 2)) {
100 (myconfig->radlog_dest != RADLOG_STDOUT) &&
101 (myconfig->radlog_dest != RADLOG_STDERR)) {
102 myconfig->radlog_fd = -1;
110 * Use it, rather than anything else.
114 } else if (myconfig->radlog_dest == RADLOG_SYSLOG) {
116 * Open run openlog() on the first log message
119 openlog(progname, LOG_PID, myconfig->syslog_facility);
124 } else if (myconfig->radlog_dest == RADLOG_FILES) {
125 if (!myconfig->log_file) {
127 * Errors go to stderr, in the hope that
128 * they will be printed somewhere.
133 snprintf(buffer, sizeof(buffer), "%s: ", progname);
134 len = strlen(buffer);
137 * No log file set. Discard it.
145 if (stat(myconfig->log_file, &buf) < 0) {
147 log_fp = fr_log_fp = NULL;
151 if (!log_fp && myconfig->log_file) {
152 fp = fopen(myconfig->log_file, "a");
154 fprintf(stderr, "%s: Couldn't open %s for logging: %s\n",
155 progname, myconfig->log_file, strerror(errno));
157 fprintf(stderr, " (");
158 vfprintf(stderr, fmt, ap); /* the message that caused the log */
159 fprintf(stderr, ")\n");
166 * We can only set the global variable log_fp IF
167 * we have no child threads. If we do have child
168 * threads, each thread has to open it's own FP.
170 if (can_update_log_fp && fp) fr_log_fp = log_fp = fp;
173 if (print_timestamp) {
177 timeval = time(NULL);
178 CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
180 s = fr_int2str(levels, (lvl & ~L_CONS), ": ");
183 len = strlen(buffer);
186 vsnprintf(buffer + len, sizeof(buffer) - len - 1, fmt, ap);
189 * Filter out characters not in Latin-1.
191 for (p = (unsigned char *)buffer; *p != '\0'; p++) {
192 if (*p == '\r' || *p == '\n')
194 else if (*p == '\t') continue;
195 else if (*p < 32 || (*p >= 128 && *p <= 160))
198 strcat(buffer, "\n");
201 if (myconfig->radlog_dest == RADLOG_SYSLOG) {
202 switch(lvl & ~L_CONS) {
222 syslog(lvl, "%s", buffer);
225 if (log_fp != NULL) {
226 fputs(buffer, log_fp);
227 } else if (fp != NULL) {
230 } else if (fd >= 0) {
231 write(fd, buffer, strlen(buffer));
237 int log_debug(const char *msg, ...)
243 r = vradlog(L_DBG, msg, ap);
249 int radlog(int lvl, const char *msg, ...)
255 r = vradlog(lvl, msg, ap);
263 * Dump a whole list of attributes to DEBUG2
265 void vp_listdebug(VALUE_PAIR *vp)
268 for (; vp; vp = vp->next) {
269 vp_prints(tmpPair, sizeof(tmpPair), vp);
270 DEBUG2(" %s", tmpPair);
275 * If the server is running with multiple threads, signal the log
276 * subsystem that we're about to START multiple threads. Once
277 * that happens, we can no longer open/close the log_fp in a
278 * child thread, as writing to global variables causes a race
281 * We also close the fr_log_fp, as it can no longer write to the
284 * All of this work is because we want to catch the case of the
285 * administrator deleting the log file. If that happens, we want
286 * the logs to go to the *new* file, and not the *old* one.
288 void force_log_reopen(void)
290 can_update_log_fp = 0;
292 if (mainconfig.radlog_dest != RADLOG_FILES) return;
294 if (log_fp) fclose(log_fp);
295 fr_log_fp = log_fp = NULL;
298 extern char *request_log_file;
299 char *debug_log_file = NULL;
301 void radlog_request(int lvl, int priority, REQUEST *request, const char *msg, ...)
304 const char *filename = request_log_file;
312 * Debug messages get treated specially.
316 * There is log function, but the debug level
317 * isn't high enough. OR, we're in debug mode,
318 * and the debug level isn't high enough. Return.
320 if ((request && request->radlog &&
321 (priority > request->options)) ||
322 ((debug_flag != 0) && (priority > debug_flag))) {
328 * Use the debug output file, if specified,
329 * otherwise leave it as "request_log_file".
331 filename = debug_log_file;
332 if (!filename) filename = request_log_file;
335 * Debug messages get mashed to L_INFO for
338 if (!filename) lvl = L_INFO;
341 if (request && filename) {
343 radlog_func_t rl = request->radlog;
345 request->radlog = NULL;
348 * This is SLOW! Doing it for every log message
349 * in every request is NOT recommended!
352 radius_xlat(buffer, sizeof(buffer), filename,
353 request, NULL); /* FIXME: escape chars! */
354 request->radlog = rl;
356 p = strrchr(buffer, FR_DIR_SEP);
359 if (rad_mkdir(buffer, S_IRWXU) < 0) {
360 radlog(L_ERR, "Failed creating %s: %s",
361 buffer,strerror(errno));
368 fp = fopen(buffer, "a");
372 * Print timestamps to the file.
377 timeval = time(NULL);
379 CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
381 s = strrchr(buffer, '\n');
387 s = fr_int2str(levels, (lvl & ~L_CONS), ": ");
390 len = strlen(buffer);
393 if (request && request->module[0]) {
394 snprintf(buffer + len, sizeof(buffer) + len, "[%s] ", request->module);
395 len = strlen(buffer);
397 vsnprintf(buffer + len, sizeof(buffer) - len, msg, ap);
401 radlog(lvl, "(%u) %s", request->number, buffer);
403 radlog(lvl, "%s", buffer);
406 if (request) fprintf(fp, "(%u) ", request->number);