* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
- * Copyright 2001 The FreeRADIUS server project
+ * Copyright 2001,2006 The FreeRADIUS server project
* Copyright 2000 Miquel van Smoorenburg <miquels@cistron.nl>
* Copyright 2000 Alan DeKok <aland@ox.org>
* Copyright 2001 Chad Miller <cmiller@surfsouth.com>
*/
-static const char rcsid[] = "$Id$";
-
-#include <freeradius-devel/autoconf.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <errno.h>
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
#include <freeradius-devel/radiusd.h>
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
#ifdef HAVE_SYSLOG_H
# include <syslog.h>
-/* keep track of whether we've run openlog() */
-static int openlog_run = 0;
#endif
- /*
+/*
* Logging facility names
*/
-static const LRAD_NAME_NUMBER levels[] = {
+static const FR_NAME_NUMBER levels[] = {
{ ": Debug: ", L_DBG },
{ ": Auth: ", L_AUTH },
{ ": Proxy: ", L_PROXY },
{ ": Info: ", L_INFO },
+ { ": Acct: ", L_ACCT },
{ ": Error: ", L_ERR },
{ NULL, 0 }
};
+int log_dates_utc = 0;
+
+
/*
* Log the message to the logfile. Include the severity and
* a time stamp.
*/
int vradlog(int lvl, const char *fmt, va_list ap)
{
- int fd = mainconfig.radlog_fd;
- FILE *fp = NULL;
+ struct main_config_t *myconfig = &mainconfig;
unsigned char *p;
char buffer[8192];
- int len, print_timestamp = 0;
+ int len;
/*
* NOT debugging, and trying to log debug messages.
* If we don't want any messages, then
* throw them away.
*/
- if (mainconfig.radlog_dest == RADLOG_NULL) {
+ if (myconfig->radlog_dest == RADLOG_NULL) {
return 0;
}
-
+
+ *buffer = '\0';
+ len = 0;
+
/*
* Don't print timestamps to syslog, it does that for us.
* Don't print timestamps for low levels of debugging.
* Print timestamps for non-debugging, and for high levels
* of debugging.
*/
- if ((mainconfig.radlog_dest != RADLOG_SYSLOG) &&
+ if ((myconfig->radlog_dest != RADLOG_SYSLOG) &&
(debug_flag != 1) && (debug_flag != 2)) {
- print_timestamp = 1;
- }
-
- *buffer = '\0';
- len = 0;
- if (fd != -1) {
- /*
- * Use it, rather than anything else.
- */
-
-#ifdef HAVE_SYSLOG_H
- } else if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
- /*
- * Open run openlog() on the first log message
- */
- if(!openlog_run) {
- openlog(progname, LOG_PID, mainconfig.syslog_facility);
- openlog_run = 1;
- }
-#endif
-
- } else if (!mainconfig.log_file) {
- /*
- * Errors go to stderr, in the hope that they will
- * be printed somewhere.
- */
- if (lvl & L_ERR) {
- fd = STDERR_FILENO;
- print_timestamp = 0;
- snprintf(buffer, sizeof(buffer), "%s: ", progname);
- len = strlen(buffer);
- } else {
- /*
- * No log file set. Discard it.
- */
- return 0;
- }
-
- } else if ((fp = fopen(mainconfig.log_file, "a")) == NULL) {
- fprintf(stderr, "%s: Couldn't open %s for logging: %s\n",
- progname, mainconfig.log_file, strerror(errno));
-
- fprintf(stderr, " (");
- vfprintf(stderr, fmt, ap); /* the message that caused the log */
- fprintf(stderr, ")\n");
- return -1;
- }
-
- if (print_timestamp) {
const char *s;
time_t timeval;
timeval = time(NULL);
- CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
+#ifdef HAVE_GMTIME_R
+ if (log_dates_utc) {
+ struct tm utc;
+ gmtime_r(&timeval, &utc);
+ asctime_r(&utc, buffer + len);
+ } else
+#endif
+ CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
- s = lrad_int2str(levels, (lvl & ~L_CONS), ": ");
+ s = fr_int2str(levels, (lvl & ~L_CONS), ": ");
strcat(buffer, s);
len = strlen(buffer);
}
strcat(buffer, "\n");
+ switch (myconfig->radlog_dest) {
+
#ifdef HAVE_SYSLOG_H
- if (mainconfig.radlog_dest == RADLOG_SYSLOG) {
+ case RADLOG_SYSLOG:
switch(lvl & ~L_CONS) {
case L_DBG:
lvl = LOG_DEBUG;
case L_PROXY:
lvl = LOG_NOTICE;
break;
+ case L_ACCT:
+ lvl = LOG_NOTICE;
+ break;
case L_INFO:
lvl = LOG_INFO;
break;
break;
}
syslog(lvl, "%s", buffer);
- } else
+ break;
#endif
- if (fp != NULL) {
- fputs(buffer, fp);
- fflush(fp);
- fclose(fp);
- } else if (fd >= 0) {
- write(fd, buffer, strlen(buffer));
+
+ case RADLOG_FILES:
+ case RADLOG_STDOUT:
+ case RADLOG_STDERR:
+ write(myconfig->radlog_fd, buffer, strlen(buffer));
+ break;
+
+ default:
+ case RADLOG_NULL: /* should have been caught above */
+ break;
}
return 0;
}
}
+extern char *request_log_file;
+#ifdef HAVE_SYS_UN_H
+extern char *debug_log_file;
+#endif
+void radlog_request(int lvl, int priority, REQUEST *request, const char *msg, ...)
+{
+ size_t len = 0;
+ const char *filename = request_log_file;
+ FILE *fp = NULL;
+ va_list ap;
+ char buffer[1024];
+ va_start(ap, msg);
+ /*
+ * Debug messages get treated specially.
+ */
+ if (lvl == L_DBG) {
+ /*
+ * There is log function, but the debug level
+ * isn't high enough. OR, we're in debug mode,
+ * and the debug level isn't high enough. Return.
+ */
+ if ((request && request->radlog &&
+ (priority > request->options)) ||
+ ((debug_flag != 0) && (priority > debug_flag))) {
+ va_end(ap);
+ return;
+ }
+
+ /*
+ * Use the debug output file, if specified,
+ * otherwise leave it as "request_log_file".
+ */
+#ifdef HAVE_SYS_UN_H
+ filename = debug_log_file;
+ if (!filename)
+#endif
+ filename = request_log_file;
+
+ /*
+ * Debug messages get mashed to L_INFO for
+ * radius.log.
+ */
+ if (!filename) lvl = L_INFO;
+ }
+
+ if (request && filename) {
+ char *p;
+ radlog_func_t rl = request->radlog;
+
+ request->radlog = NULL;
+
+ /*
+ * This is SLOW! Doing it for every log message
+ * in every request is NOT recommended!
+ */
+
+ radius_xlat(buffer, sizeof(buffer), filename,
+ request, NULL); /* FIXME: escape chars! */
+ request->radlog = rl;
+
+ p = strrchr(buffer, FR_DIR_SEP);
+ if (p) {
+ *p = '\0';
+ if (rad_mkdir(buffer, S_IRWXU) < 0) {
+ radlog(L_ERR, "Failed creating %s: %s",
+ buffer,strerror(errno));
+ va_end(ap);
+ return;
+ }
+ *p = FR_DIR_SEP;
+ }
+
+ fp = fopen(buffer, "a");
+ }
+
+ /*
+ * Print timestamps to the file.
+ */
+ if (fp) {
+ char *s;
+ time_t timeval;
+ timeval = time(NULL);
+
+#ifdef HAVE_GMTIME_R
+ if (log_dates_utc) {
+ struct tm utc;
+ gmtime_r(&timeval, &utc);
+ ASCTIME_R(&utc, buffer + len, sizeof(buffer) - len - 1);
+ } else
+#endif
+ {
+ CTIME_R(&timeval, buffer + len, sizeof(buffer) - len - 1);
+ }
+
+ s = strrchr(buffer, '\n');
+ if (s) {
+ s[0] = ' ';
+ s[1] = '\0';
+ }
+
+ len = strlen(buffer);
+
+ if (len < sizeof(buffer)) {
+ len += strlcpy(buffer + len, fr_int2str(levels, (lvl & ~L_CONS), ": "), sizeof(buffer) - len);
+ }
+ }
+
+ if (request && request->module[0]) {
+ snprintf(buffer + len, sizeof(buffer) - len, "[%s] ", request->module);
+ len = strlen(buffer);
+ }
+ vsnprintf(buffer + len, sizeof(buffer) - len, msg, ap);
+
+ if (!fp) {
+ radlog(lvl, "%s", buffer);
+ } else {
+ if (strlcat(buffer, "\n", sizeof(buffer)) >= sizeof(buffer)) {
+ buffer[sizeof(buffer) - 1] = '\n';
+ }
+ fputs(buffer, fp);
+ fclose(fp);
+ }
+
+ va_end(ap);
+}