Home | History | Annotate | Download | only in conman-0.2.4.1
      1 /*****************************************************************************
      2  *  $Id: log.c 945 2009-04-21 22:17:51Z dun $
      3  *****************************************************************************
      4  *  Written by Chris Dunlap <cdunlap (at) llnl.gov>.
      5  *  Copyright (C) 2007-2009 Lawrence Livermore National Security, LLC.
      6  *  Copyright (C) 2001-2007 The Regents of the University of California.
      7  *  UCRL-CODE-2002-009.
      8  *
      9  *  This file is part of ConMan: The Console Manager.
     10  *  For details, see <http://home.gna.org/conman/>.
     11  *
     12  *  This is free software; you can redistribute it and/or modify it
     13  *  under the terms of the GNU General Public License as published by
     14  *  the Free Software Foundation; either version 2 of the License, or
     15  *  (at your option) any later version.
     16  *
     17  *  This is distributed in the hope that it will be useful, but WITHOUT
     18  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     19  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     20  *  for more details.
     21  *
     22  *  You should have received a copy of the GNU General Public License
     23  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
     24  *****************************************************************************
     25  *  Refer to "log.h" for documentation on public functions.
     26  *****************************************************************************/
     27 
     28 
     29 #ifdef HAVE_CONFIG_H
     30 #  include "config.h"
     31 #endif /* HAVE_CONFIG_H */
     32 
     33 #include <assert.h>
     34 #include <errno.h>
     35 #include <stdarg.h>
     36 #include <stdio.h>
     37 #include <stdlib.h>
     38 #include <string.h>
     39 #include <syslog.h>
     40 #include <time.h>
     41 #include <unistd.h>
     42 #include "log.h"
     43 #include "util-str.h"
     44 
     45 
     46 #ifndef MAX_LINE
     47 #  define MAX_LINE 1024
     48 #endif /* !MAX_LINE */
     49 
     50 
     51 static FILE * log_file_fp = NULL;
     52 static int    log_file_priority = -1;
     53 static int    log_file_timestamp = 0;
     54 static int    log_syslog = 0;
     55 static int    log_fd_daemonize = -1;
     56 
     57 
     58 static void log_aux(int errnum, int priority, char *msgbug, int msgbuflen,
     59     const char *format, va_list vargs);
     60 
     61 static const char * log_prefix(int priority);
     62 
     63 
     64 void debug_printf(int level, const char *format, ...)
     65 {
     66     static int debug_level = -1;
     67     va_list vargs;
     68     char *p;
     69     int i = 0;
     70 
     71     if (debug_level < 0) {
     72         if ((p = getenv("DEBUG"))) {
     73             i = atoi(p);
     74         }
     75         debug_level = (i > 0) ? i : 0;
     76     }
     77     if ((level > 0) && (level <= debug_level)) {
     78         va_start(vargs, format);
     79         vfprintf(stderr, format, vargs);
     80         va_end(vargs);
     81     }
     82     return;
     83 }
     84 
     85 
     86 void log_set_file(FILE *fp, int priority, int timestamp)
     87 {
     88     if (fp && !ferror(fp)) {
     89         log_file_fp = fp;
     90         log_file_priority = (priority > 0) ? priority : 0;
     91         log_file_timestamp = !!timestamp;
     92         setvbuf(fp, NULL, _IONBF, 0);   /* set stream unbuffered */
     93     }
     94     else {
     95         log_file_fp = NULL;
     96         log_file_priority = -1;
     97         log_file_timestamp = 0;
     98     }
     99     return;
    100 }
    101 
    102 
    103 void log_set_syslog(char *ident, int facility)
    104 {
    105     char *p;
    106 
    107     if (ident) {
    108         if ((p = strrchr(ident, '/'))) {
    109             ident = p + 1;
    110         }
    111         openlog(ident, LOG_NDELAY | LOG_PID, facility);
    112         log_syslog = 1;
    113     }
    114     else {
    115         closelog();
    116         log_syslog = 0;
    117     }
    118     return;
    119 }
    120 
    121 
    122 void log_set_err_pipe(int fd)
    123 {
    124     log_fd_daemonize = (fd >= 0) ? fd : -1;
    125     return;
    126 }
    127 
    128 
    129 void log_err(int errnum, const char *format, ...)
    130 {
    131     int priority = LOG_ERR;
    132     va_list vargs;
    133     char msg[MAX_LINE];
    134     signed char c;
    135     int n;
    136     char *p;
    137 
    138     va_start(vargs, format);
    139     log_aux(errnum, priority, msg, sizeof(msg), format, vargs);
    140     va_end(vargs);
    141 
    142     /*  Return error priority and message across "daemonize" pipe.
    143      */
    144     if (log_fd_daemonize >= 0) {
    145         c = (signed char) priority;
    146         n = write(log_fd_daemonize, &c, sizeof(c));
    147         if ((n > 0) && (msg[0] != '\0') && (log_file_fp != stderr)) {
    148             if ((p = strchr(msg, '\n'))) {
    149                 *p = '\0';
    150             }
    151             /*  Ignore return value from write() instead of logging an error
    152              *    about failing to log an error.  Replaced void cast with
    153              *    useless assignment since compilation under rhel5 complained
    154              *    about ignoring return value of 'write'.
    155              */
    156             n = write(log_fd_daemonize, msg, strlen(msg) + 1);
    157         }
    158     }
    159 #ifndef NDEBUG
    160     /*  Generate core for debugging.
    161      */
    162     if (getenv("DEBUG")) {
    163         abort();
    164     }
    165 #endif /* !NDEBUG */
    166 
    167     exit(1);
    168 }
    169 
    170 
    171 void log_msg(int priority, const char *format, ...)
    172 {
    173     va_list vargs;
    174 
    175     va_start(vargs, format);
    176     log_aux(0, priority, NULL, 0, format, vargs);
    177     va_end(vargs);
    178 
    179     return;
    180 }
    181 
    182 
    183 static void log_aux(int errnum, int priority, char *msgbuf, int msgbuflen,
    184     const char *format, va_list vargs)
    185 {
    186     time_t t;
    187     struct tm tm;
    188     const char *prefix;
    189     char buf[MAX_LINE];                 /* buf starting with timestamp       */
    190     char *pbuf;                         /* buf starting with priority string */
    191     char *sbuf;                         /* buf starting with message         */
    192     char *p;
    193     int len;
    194     int n;
    195 
    196     p = sbuf = pbuf = buf;
    197     len = sizeof(buf) - 1;              /* reserve char for terminating '\n' */
    198 
    199     t = 0;
    200     get_localtime(&t, &tm);
    201     n = strftime(p, len, "%Y-%m-%d %H:%M:%S ", &tm);
    202     if (n == 0) {
    203         *p = '\0';
    204         len = 0;
    205     }
    206     p = sbuf = pbuf += n;
    207     len -= n;
    208 
    209     if ((prefix = log_prefix(priority))) {
    210         int m = 10 - strlen(prefix);
    211         if (m <= 0) {
    212             m = 1;
    213         }
    214         assert(strlen(prefix) < 10);
    215         n = snprintf(p, len, "%s:%*c", prefix, m, 0x20);
    216         if ((n < 0) || (n >= len)) {
    217             n = len - 1;
    218         }
    219         p = sbuf += n;
    220         len -= n;
    221     }
    222 
    223     n = vsnprintf(p, len, format, vargs);
    224     if ((n < 0) || (n >= len)) {
    225         n = len - 1;
    226     }
    227     p += n;
    228     len -= n;
    229 
    230     if (format[strlen(format) - 1] != '\n') {
    231         if ((errnum > 0) && (len > 0)) {
    232             n = snprintf(p, len, ": %s", strerror(errnum));
    233             if ((n < 0) || (n >= len)) {
    234                 n = len - 1;
    235             }
    236             p += n;
    237             len -= n;
    238         }
    239         strcat(p, "\n");
    240     }
    241 
    242     if (msgbuf && (msgbuflen > 0)) {
    243         if (sbuf) {
    244             strncpy(msgbuf, sbuf, msgbuflen);
    245             msgbuf[msgbuflen - 1] = '\0';
    246         }
    247         else {
    248             msgbuf[0] = '\0';
    249         }
    250     }
    251 
    252     if (log_syslog) {
    253         syslog(priority, "%s", sbuf);
    254     }
    255     if (log_file_fp && (priority <= log_file_priority)) {
    256         n = fprintf(log_file_fp, "%s", log_file_timestamp ? buf : pbuf);
    257         if (n == EOF) {
    258             syslog(LOG_CRIT, "Logging stopped due to error");
    259             log_file_fp = NULL;
    260         }
    261     }
    262     return;
    263 }
    264 
    265 
    266 static const char * log_prefix(int priority)
    267 {
    268     switch (priority) {
    269     case LOG_EMERG:
    270         return("EMERGENCY");
    271     case LOG_ALERT:
    272         return("ALERT");
    273     case LOG_CRIT:
    274         return("CRITICAL");
    275     case LOG_ERR:
    276         return("ERROR");
    277     case LOG_WARNING:
    278         return("WARNING");
    279     case LOG_NOTICE:
    280         return("NOTICE");
    281     case LOG_INFO:
    282         return("INFO");
    283     case LOG_DEBUG:
    284         return("DEBUG");
    285     default:
    286         return("UNKNOWN");
    287     }
    288 }
    289