/* * Copyright (C), 2000-2007 by the monit project group. * All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #ifdef HAVE_STDIO_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_ERRNO_H #include #endif #ifdef HAVE_STDARG_H #include #endif #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif #ifdef HAVE_SYSLOG_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_STRINGS_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SYS_TYPES_H #include #endif #ifdef HAVE_SYS_STAT_H #include #endif #include "monitor.h" /** * Implementation of a logger that appends log messages to a file * with a preceding timestamp. Methods support both syslog or own * logfile. * * @author Jan-Henrik Haukeland, * * @version \$Id: log.c,v 1.35 2007/07/26 07:41:32 hauk Exp $ * * @file */ /* ------------------------------------------------------------- Definitions */ static FILE *LOG= NULL; static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER; static struct mylogpriority { int priority; char *description; } logPriority[]= { {LOG_EMERG, "emergency"}, {LOG_ALERT, "alert"}, {LOG_CRIT, "critical"}, {LOG_ERR, "error"}, {LOG_WARNING, "warning"}, {LOG_NOTICE, "notice"}, {LOG_INFO, "info"}, {LOG_DEBUG, "debug"}, {-1, NULL} }; /* -------------------------------------------------------------- Prototypes */ static int open_log(); static char *timefmt(char *t, int size); static const char *logPriorityDescription(int p); static void log_log(int priority, const char *s, va_list ap); /* ------------------------------------------------------------------ Public */ /** * Initialize the log system and 'log' function * @return TRUE if the log system was successfully initialized */ int log_init() { if(!Run.dolog) { return TRUE; } if(!open_log()) { return FALSE; } /* Register log_close to be called at program termination */ atexit(log_close); return TRUE; } /** * Logging interface with priority support * @param s A formated (printf-style) string to log */ void LogEmergency(const char *s, ...) { va_list ap; ASSERT(s); va_start(ap, s); log_log(LOG_EMERG, s, ap); va_end(ap); } /** * Logging interface with priority support * @param s A formated (printf-style) string to log */ void LogAlert(const char *s, ...) { va_list ap; ASSERT(s); va_start(ap, s); log_log(LOG_ALERT, s, ap); va_end(ap); } /** * Logging interface with priority support * @param s A formated (printf-style) string to log */ void LogCritical(const char *s, ...) { va_list ap; ASSERT(s); va_start(ap, s); log_log(LOG_CRIT, s, ap); va_end(ap); } /** * Logging interface with priority support * @param s A formated (printf-style) string to log */ void LogError(const char *s, ...) { va_list ap; ASSERT(s); va_start(ap, s); log_log(LOG_ERR, s, ap); va_end(ap); } /** * Logging interface with priority support * @param s A formated (printf-style) string to log */ void LogWarning(const char *s, ...) { va_list ap; ASSERT(s); va_start(ap, s); log_log(LOG_WARNING, s, ap); va_end(ap); } /** * Logging interface with priority support * @param s A formated (printf-style) string to log */ void LogNotice(const char *s, ...) { va_list ap; ASSERT(s); va_start(ap, s); log_log(LOG_NOTICE, s, ap); va_end(ap); } /** * Logging interface with priority support * @param s A formated (printf-style) string to log */ void LogInfo(const char *s, ...) { va_list ap; ASSERT(s); va_start(ap, s); log_log(LOG_INFO, s, ap); va_end(ap); } /** * Logging interface with priority support * @param s A formated (printf-style) string to log */ void LogDebug(const char *s, ...) { va_list ap; ASSERT(s); va_start(ap, s); log_log(LOG_DEBUG, s, ap); va_end(ap); } /** * Close the log file or syslog */ void log_close() { if(Run.use_syslog) { closelog(); } if(LOG && (0 != fclose(LOG))) { LogError("%s: Error closing the log file -- %s\n", prog, STRERROR); } LOG= NULL; } /* ----------------------------------------------------------------- Private */ /** * Open a log file or syslog */ static int open_log() { if(Run.use_syslog) { openlog(prog, LOG_PID, Run.facility); } else { umask(LOGMASK); if((LOG= fopen(Run.logfile,"a+")) == (FILE *)NULL) { LogError("%s: Error opening the log file '%s' for writing -- %s\n", prog, Run.logfile, STRERROR); return(FALSE); } /* Set logger in unbuffered mode */ setvbuf(LOG, NULL, _IONBF, 0); } return TRUE; } /** * Returns the current time as a formated string, see the TIMEFORMAT * macro in monitor.h */ static char *timefmt(char *t, int size) { time_t now; struct tm tm; time(&now); if(!strftime(t, size, TIMEFORMAT, localtime_r(&now, &tm))) { *t= 0; } return t; } /** * Get a textual description of the actual log priority. * @param p The log priority * @return A string describing the log priority in clear text. If the * priority is not found NULL is returned. */ static const char *logPriorityDescription(int p) { struct mylogpriority *lp= logPriority; while((*lp).description) { if(p == (*lp).priority) { return (*lp).description; } lp++; } return "unknown"; } /** * Log a message to monits logfile or syslog. * @param priority A message priority * @param s A formated (printf-style) string to log */ static void log_log(int priority, const char *s, va_list ap) { #ifdef HAVE_VA_COPY va_list ap_copy; #endif ASSERT(s); LOCK(log_mutex) #ifdef HAVE_VA_COPY va_copy(ap_copy, ap); vfprintf(stderr, s, ap_copy); va_end(ap_copy); #else vfprintf(stderr, s, ap); #endif fflush(stderr); END_LOCK; if(Run.dolog) { char datetime[STRLEN]; if(Run.use_syslog) { LOCK(log_mutex) #ifdef HAVE_VA_COPY va_copy(ap_copy, ap); vsyslog(priority, s, ap_copy); va_end(ap_copy); #else vsyslog(priority, s, ap); #endif END_LOCK; } else if(LOG) { LOCK(log_mutex) fprintf(LOG, "[%s] %-8s : ", timefmt(datetime, STRLEN), logPriorityDescription(priority)); #ifdef HAVE_VA_COPY va_copy(ap_copy, ap); vfprintf(LOG, s, ap_copy); va_end(ap_copy); #else vfprintf(LOG, s, ap); #endif END_LOCK; } } }