jabberd2  2.2.16
util/log.c
Go to the documentation of this file.
00001 /*
00002  * jabberd - Jabber Open Source Server
00003  * Copyright (c) 2002 Jeremie Miller, Thomas Muldowney,
00004  *                    Ryan Eatmon, Robert Norris
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA
00019  */
00020 
00021 #include "util.h"
00022 
00023 #define MAX_LOG_LINE (1024)
00024 
00025 #ifdef DEBUG
00026 static int debug_flag;
00027 static FILE *debug_log_target = 0;
00028 #endif
00029 
00030 static const char *_log_level[] =
00031 {
00032     "emergency",
00033     "alert",
00034     "critical",
00035     "error",
00036     "warning",
00037     "notice",
00038     "info",
00039     "debug"
00040 };
00041 
00042 static log_facility_t _log_facilities[] = {
00043     { "local0", LOG_LOCAL0 },
00044     { "local1", LOG_LOCAL1 },
00045     { "local2", LOG_LOCAL2 },
00046     { "local3", LOG_LOCAL3 },
00047     { "local4", LOG_LOCAL4 },
00048     { "local5", LOG_LOCAL5 },
00049     { "local6", LOG_LOCAL6 },
00050     { "local7", LOG_LOCAL7 },
00051     { "log_user", LOG_USER },
00052     { NULL, -1 }
00053 };
00054 
00055 static int _log_facility(const char *facility) {
00056     log_facility_t *lp;
00057 
00058     if (facility == NULL) {
00059         return -1;
00060     }
00061     for (lp = _log_facilities; lp->facility; lp++) {
00062         if (!strcasecmp(lp->facility, facility)) {
00063             break;
00064         }
00065     }
00066     return lp->number;
00067 }
00068 
00069 log_t log_new(log_type_t type, const char *ident, const char *facility)
00070 {
00071     log_t log;
00072     int fnum = 0;
00073 
00074     log = (log_t) calloc(1, sizeof(struct log_st));
00075 
00076     log->type = type;
00077 
00078     if(type == log_SYSLOG) {
00079         fnum = _log_facility(facility);
00080         if (fnum < 0)
00081             fnum = LOG_LOCAL7;
00082         openlog(ident, LOG_PID, fnum);
00083         return log;
00084     }
00085 
00086     else if(type == log_STDOUT) {
00087         log->file = stdout;
00088         return log;
00089     }
00090 
00091     log->file = fopen(ident, "a+");
00092     if(log->file == NULL)
00093     {
00094         fprintf(stderr,
00095             "ERROR: couldn't open logfile: %s\n"
00096             "       logging will go to stdout instead\n", strerror(errno));
00097         log->type = log_STDOUT;
00098         log->file = stdout;
00099     }
00100 
00101     return log;
00102 }
00103 
00104 void log_write(log_t log, int level, const char *msgfmt, ...)
00105 {
00106     va_list ap;
00107     char *pos, message[MAX_LOG_LINE+1];
00108     int sz, len;
00109     time_t t;
00110 
00111     if(log && log->type == log_SYSLOG) {
00112         va_start(ap, msgfmt);
00113 #ifdef HAVE_VSYSLOG
00114         vsyslog(level, msgfmt, ap);
00115 #else
00116         len = vsnprintf(message, MAX_LOG_LINE, msgfmt, ap);
00117         if (len > MAX_LOG_LINE)
00118             message[MAX_LOG_LINE] = '\0';
00119         else
00120             message[len] = '\0';
00121         syslog(level, "%s", message);
00122 #endif
00123         va_end(ap);
00124 
00125 #ifndef DEBUG
00126         return;
00127 #endif
00128     }
00129 
00130     /* timestamp */
00131     t = time(NULL);
00132     pos = ctime(&t);
00133     sz = strlen(pos);
00134     /* chop off the \n */
00135     pos[sz-1]=' ';
00136 
00137     /* insert the header */
00138     len = snprintf(message, MAX_LOG_LINE, "%s[%s] ", pos, _log_level[level]);
00139     if (len > MAX_LOG_LINE)
00140         message[MAX_LOG_LINE] = '\0';
00141     else
00142         message[len] = '\0';
00143 
00144     /* find the end and attach the rest of the msg */
00145     for (pos = message; *pos != '\0'; pos++); /*empty statement */
00146     sz = pos - message;
00147     va_start(ap, msgfmt);
00148     vsnprintf(pos, MAX_LOG_LINE - sz, msgfmt, ap);
00149     va_end(ap);
00150 #ifndef DEBUG
00151     if(log && log->type != log_SYSLOG) {
00152 #endif
00153         if(log && log->file) {
00154             fprintf(log->file,"%s", message);
00155             fprintf(log->file, "\n");
00156             fflush(log->file);
00157         }
00158 #ifndef DEBUG
00159     }
00160 #endif
00161 
00162 #ifdef DEBUG
00163     if (!debug_log_target) {
00164         debug_log_target = stderr;
00165     }
00166     /* If we are in debug mode we want everything copied to the stdout */
00167     if ((log == 0) || (get_debug_flag() && log->type != log_STDOUT)) {
00168         fprintf(debug_log_target, "%s\n", message);
00169         fflush(debug_log_target);
00170     }
00171 #endif /*DEBUG*/
00172 }
00173 
00174 void log_free(log_t log) {
00175     if(log->type == log_SYSLOG)
00176         closelog();
00177     else if(log->type == log_FILE)
00178         fclose(log->file);
00179 
00180     free(log);
00181 }
00182 
00183 #ifdef DEBUG
00184 
00185 void debug_log(const char *file, int line, const char *msgfmt, ...)
00186 {
00187     va_list ap;
00188     char *pos, message[MAX_DEBUG];
00189     int sz;
00190     time_t t;
00191 
00192     if (!debug_log_target) {
00193         debug_log_target = stderr;
00194     }
00195     /* timestamp */
00196     t = time(NULL);
00197     pos = ctime(&t);
00198     sz = strlen(pos);
00199     /* chop off the \n */
00200     pos[sz-1]=' ';
00201 
00202     /* insert the header */
00203     snprintf(message, MAX_DEBUG, "%s%s:%d ", pos, file, line);
00204 
00205     /* find the end and attach the rest of the msg */
00206     for (pos = message; *pos != '\0'; pos++); /*empty statement */
00207     sz = pos - message;
00208     va_start(ap, msgfmt);
00209     vsnprintf(pos, MAX_DEBUG - sz, msgfmt, ap);
00210     va_end(ap);
00211     fprintf(debug_log_target,"%s", message);
00212     fprintf(debug_log_target, "\n");
00213     fflush(debug_log_target);
00214 }
00215 
00216 int get_debug_flag(void)
00217 {
00218     return debug_flag;
00219 }
00220 
00221 void set_debug_flag(int v)
00222 {
00223     debug_flag = v;
00224 }
00225 
00226 int set_debug_log_from_config(config_t c)
00227 {
00228     return set_debug_file(config_get_one(c, "log.debug", 0));
00229 };
00230 
00231 JABBERD2_API int set_debug_file(const char *filename)
00232 {
00233     // Close debug output file but not stderr
00234     if (debug_log_target != 0 &&
00235         debug_log_target != stderr)
00236     {
00237         fprintf(debug_log_target, "Closing log\n");
00238         fclose(debug_log_target);
00239 
00240         debug_log_target = stderr;
00241     }
00242 
00243     // Setup new log target
00244     if (filename) {
00245         log_debug(ZONE, "Openning debug log file %s", filename);
00246         debug_log_target = fopen(filename, "a+");
00247 
00248         if (debug_log_target) {
00249             log_debug(ZONE, "Staring debug log");
00250         } else {
00251             debug_log_target = stderr;
00252             log_debug(ZONE, "Failed to open debug output file %s. Fallback to stderr", filename);
00253         }
00254     } else {
00255         // set stderr
00256         debug_log_target = stderr;
00257     }
00258 };
00259 
00260 #else /* DEBUG */
00261 void debug_log(const char *file, int line, const char *msgfmt, ...)
00262 { }
00263 
00264 void set_debug_flag(int v)
00265 { }
00266 #endif