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
40 * Logging facility names
42 static const FR_NAME_NUMBER levels[] = {
43 { ": Debug: ", L_DBG },
44 { ": Auth: ", L_AUTH },
45 { ": Proxy: ", L_PROXY },
46 { ": Info: ", L_INFO },
47 { ": Acct: ", L_ACCT },
48 { ": Error: ", L_ERR },
52 #define VTC_RED "\x1b[31m"
53 #define VTC_BOLD "\x1b[1m"
54 #define VTC_RESET "\x1b[0m"
56 static const FR_NAME_NUMBER colours[] = {
59 { VTC_BOLD, L_PROXY },
66 int log_dates_utc = 0;
70 * Log the message to the logfile. Include the severity and
73 int vradlog(int lvl, const char *fmt, va_list ap)
75 struct main_config_t *myconfig = &mainconfig;
82 * NOT debugging, and trying to log debug messages.
84 * Throw the message away.
86 if (!debug_flag && (lvl == L_DBG)) {
91 * If we don't want any messages, then
94 if (myconfig->radlog_dest == RADLOG_NULL) {
101 if (myconfig->colourise &&
102 ((myconfig->radlog_dest == RADLOG_STDOUT) ||
103 (myconfig->radlog_dest == RADLOG_STDERR))) {
104 len += strlcpy(buffer + len, fr_int2str(colours, lvl, ""),
105 sizeof(buffer) - len) ;
109 * Mark the point where we treat the buffer as unsanitized.
111 unsan = buffer + len;
114 * Don't print timestamps to syslog, it does that for us.
115 * Don't print timestamps for low levels of debugging.
117 * Print timestamps for non-debugging, and for high levels
120 if ((myconfig->radlog_dest != RADLOG_SYSLOG) &&
121 (debug_flag != 1) && (debug_flag != 2)) {
124 timeval = time(NULL);
125 CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
127 len = strlen(buffer);
129 len += strlcpy(buffer + len,
130 fr_int2str(levels, (lvl & ~L_CONS), ": "),
131 sizeof(buffer) - len);
134 if (len < sizeof(buffer)) {
135 len += vsnprintf(buffer + len,
136 sizeof(buffer) - len - 1, fmt, ap);
140 * Filter out characters not in Latin-1.
142 for (p = (unsigned char *)unsan; *p != '\0'; p++) {
143 if (*p == '\r' || *p == '\n')
145 else if (*p == '\t') continue;
146 else if (*p < 32 || (*p >= 128 && *p <= 160))
150 if (myconfig->colourise && (len < sizeof(buffer)) &&
151 ((myconfig->radlog_dest == RADLOG_STDOUT) ||
152 (myconfig->radlog_dest == RADLOG_STDERR))) {
153 len += strlcpy(buffer + len, VTC_RESET, sizeof(buffer) - len);
156 if (len < (sizeof(buffer) - 1)) {
158 buffer[len + 1] = '\0';
160 buffer[len - 1] = '\n';
164 switch (myconfig->radlog_dest) {
168 switch(lvl & ~L_CONS) {
188 syslog(lvl, "%s", buffer);
195 write(myconfig->radlog_fd, buffer, strlen(buffer));
199 case RADLOG_NULL: /* should have been caught above */
206 int log_debug(const char *msg, ...)
212 r = vradlog(L_DBG, msg, ap);
218 int radlog(int lvl, const char *msg, ...)
224 r = vradlog(lvl, msg, ap);
232 * Dump a whole list of attributes to DEBUG2
234 void vp_listdebug(VALUE_PAIR *vp)
237 for (; vp; vp = vp->next) {
238 vp_prints(tmpPair, sizeof(tmpPair), vp);
239 DEBUG2(" %s", tmpPair);
243 extern char *request_log_file;
244 #ifdef WITH_COMMAND_SOCKET
245 extern char *debug_log_file;
248 void radlog_request(int lvl, int priority, REQUEST *request, const char *msg, ...)
251 const char *filename = request_log_file;
260 * Debug messages get treated specially.
264 * There is log function, but the debug level
265 * isn't high enough. OR, we're in debug mode,
266 * and the debug level isn't high enough. Return.
268 if ((request && request->radlog &&
269 (priority > request->options)) ||
270 ((debug_flag != 0) && (priority > debug_flag))) {
276 * Use the debug output file, if specified,
277 * otherwise leave it as "request_log_file".
279 #ifdef WITH_COMMAND_SOCKET
280 filename = debug_log_file;
283 filename = request_log_file;
285 filename = request_log_file;
288 if (request && filename) {
289 radlog_func_t rl = request->radlog;
291 request->radlog = NULL;
294 * This is SLOW! Doing it for every log message
295 * in every request is NOT recommended!
298 radius_xlat(buffer, sizeof(buffer), filename,
299 request, NULL, NULL); /* FIXME: escape chars! */
300 request->radlog = rl;
302 p = strrchr(buffer, FR_DIR_SEP);
305 if (rad_mkdir(buffer, S_IRWXU) < 0) {
306 radlog(L_ERR, "Failed creating %s: %s",
307 buffer,strerror(errno));
314 fp = fopen(buffer, "a");
318 * Print timestamps to the file.
322 timeval = time(NULL);
327 gmtime_r(&timeval, &utc);
328 asctime_r(&utc, buffer);
331 CTIME_R(&timeval, buffer, sizeof(buffer) - 1);
333 len = strlen(buffer);
334 p = strrchr(buffer, '\n');
340 len += strlcpy(buffer + len,
341 fr_int2str(levels, (lvl & ~L_CONS), ": "),
342 sizeof(buffer) - len);
344 if (len >= sizeof(buffer)) goto finish;
347 if (request && request->module[0]) {
348 len = snprintf(buffer + len, sizeof(buffer) - len, "%s : ",
351 if (len >= sizeof(buffer)) goto finish;
354 vsnprintf(buffer + len, sizeof(buffer) - len, msg, ap);
359 radlog(lvl, "(%u) %s", request->number, buffer);
361 radlog(lvl, "%s", buffer);
364 if (request) fprintf(fp, "(%u) ", request->number);