lib/log.c

Go to the documentation of this file.
00001 /* log.c - logging for servers, can log to a file and/or syslog.  Compile with
00002  * -DNO_SYSLOG for systems without syslog. */
00003 
00004 #include "common.h"
00005 #include "log.h"
00006 #include "errabort.h"
00007 #include "dystring.h"
00008 #include "options.h"
00009 #include "portable.h"
00010 
00011 #ifndef NO_SYSLOG
00012 #include <syslog.h>
00013 #endif
00014 #include <time.h>
00015 
00016 static char *gProgram = "unknown";  /* name of program */
00017 static boolean gSysLogOn = FALSE;   /* syslog logging enabled? */
00018 static FILE *gLogFh = NULL;         /* logging file */
00019 
00020 #ifndef NO_SYSLOG
00021 
00022 static struct {
00023     char *name;   /* string name for facility */
00024     int   fac;    /* integer value */
00025 } facilityNameTbl[] =
00026 /* not all version of syslog have the facilitynames table, so  define our own */
00027 {
00028     {"auth",         LOG_AUTH},
00029 #ifdef LOG_AUTHPRIV
00030     {"authpriv",     LOG_AUTHPRIV},
00031 #endif
00032     {"cron",         LOG_CRON},
00033     {"daemon",       LOG_DAEMON},
00034 #ifdef LOG_FTP
00035     {"ftp",          LOG_FTP},
00036 #endif
00037     {"kern",         LOG_KERN},
00038     {"lpr",          LOG_LPR},
00039     {"mail",         LOG_MAIL},
00040     {"news",         LOG_NEWS},
00041     {"syslog",       LOG_SYSLOG},
00042     {"user",         LOG_USER},
00043 #ifdef LOG_UUCP
00044     {"uucp",         LOG_UUCP},
00045 #endif
00046     {"local0",       LOG_LOCAL0},
00047     {"local1",       LOG_LOCAL1},
00048     {"local2",       LOG_LOCAL2},
00049     {"local3",       LOG_LOCAL3},
00050     {"local4",       LOG_LOCAL4},
00051     {"local5",       LOG_LOCAL5},
00052     {"local6",       LOG_LOCAL6},
00053     {"local7",       LOG_LOCAL7},
00054     {NULL,           0}
00055 };
00056 #endif
00057 
00058 static void logWarnHander(char *format, va_list args)
00059 /* Warn handler that logs message. */
00060 {
00061 /* use logError, since errAbort and warn all print through warn handler */
00062 logErrorVa(format, args);
00063 }
00064 
00065 static void logAbortHandler()
00066 /* abort handler that logs this fact and exits. */
00067 {
00068 logError("%s aborted", gProgram);
00069 fprintf(stderr, "aborted");
00070 exit(1);
00071 }
00072 
00073 static void setProgram(char* program)
00074 /* set the program name, removing leading directories from file */
00075 {
00076 char name[128], ext[64];
00077 int len;
00078 splitPath(program, NULL, name, ext);
00079 len = strlen(name) + strlen(ext) + 1;
00080 gProgram = needMem(len);
00081 strcpy(gProgram, name);
00082 if (ext[0] != '\0')
00083     strcat(gProgram, ext); /* includes dot */
00084 }
00085 
00086 #ifndef NO_SYSLOG
00087 static int parseFacility(char *facility)
00088 /* parse a facility name into a number, or use default if NULL. */
00089 {
00090 int i;
00091 struct dyString *msg;
00092 if (facility == NULL)
00093     return LOG_LOCAL0;
00094 for (i = 0; facilityNameTbl[i].name != NULL; i++)
00095     {
00096     if (sameString(facilityNameTbl[i].name, facility))
00097         return facilityNameTbl[i].fac;
00098     }
00099 msg = dyStringNew(256);
00100 
00101 for (i = 0; facilityNameTbl[i].name != NULL; i++)
00102     {
00103     if (i > 0)
00104         dyStringAppend(msg, ", ");
00105     dyStringAppend(msg, facilityNameTbl[i].name);
00106     }
00107 
00108 errAbort("invalid log facility: %s, expected one of: %s", facility, msg->string);
00109 return 0; /* never reached */
00110 }
00111 #endif
00112 
00113 void logOpenSyslog(char* program, char *facility)
00114 /* Initialize syslog using the specified facility.  Facility is the syslog
00115  * facility as specified in syslog.conf.  If facility is NULL, local0 is used.
00116  * This adds a warn and errAbort handlers that do logging.  If custom handlers
00117  * are added, they should call logErrorVa().
00118  */
00119 {
00120 #ifndef NO_SYSLOG
00121 setProgram(program);
00122 openlog(program, LOG_PID, parseFacility(facility));
00123 pushWarnHandler(logWarnHander);
00124 pushAbortHandler(logAbortHandler);
00125 gSysLogOn = TRUE;
00126 #else
00127 errAbort("syslog support was not compiled into %s", __FILE__);
00128 #endif
00129 }
00130 
00131 void logOpenFile(char* program, char *logFile)
00132 /* Initialize logging to the specified file.  Append to the file if it exists.
00133  * This adds a warn and errAbort handlers that do logging.  If custom handlers
00134  * are added, they should call logErrorVa().
00135  */
00136 {
00137 setProgram(program);
00138 gLogFh = mustOpen(logFile, "a");
00139 pushWarnHandler(logWarnHander);
00140 pushAbortHandler(logAbortHandler);
00141 }
00142 
00143 FILE *logGetFile()
00144 /* Returns the log FILE object if file logging is enabled, or NULL if it
00145  * isn't. This is useful for logging debugging data that doesn't fit the log
00146  * message paradigm, For example, logging fasta records. */
00147 {
00148 return gLogFh;
00149 }
00150 
00151 static void logFilePrint(char* level, char *format, va_list args)
00152 /* write a message to the log file */
00153 {
00154 static char *timeFmt = "%Y/%m/%d %H:%M:%S";
00155 char timeBuf[128];
00156 time_t curTime = time(NULL);
00157 strftime(timeBuf, sizeof(timeBuf), timeFmt, localtime(&curTime));
00158 fprintf(gLogFh, "%s: %s: ", timeBuf, level);
00159 vfprintf(gLogFh, format, args);
00160 fputc('\n', gLogFh);
00161 fflush(gLogFh);
00162 }
00163 
00164 void logErrorVa(char *format, va_list args)
00165 /* Variable args logError. */
00166 {
00167 #ifndef NO_SYSLOG
00168 if (gSysLogOn)
00169     vsyslog(LOG_ERR, format, args);
00170 #endif
00171 if (gLogFh != NULL)
00172     logFilePrint("error", format, args);
00173 }
00174 
00175 void logError(char *format, ...)
00176 /* Log an error message. */
00177 {
00178 va_list args;
00179 va_start(args, format);
00180 logErrorVa(format, args);
00181 va_end(args);
00182 }
00183 
00184 void logWarnVa(char *format, va_list args)
00185 /* Variable args logWarn. */
00186 {
00187 #ifndef NO_SYSLOG
00188 if (gSysLogOn)
00189     vsyslog(LOG_WARNING, format, args);
00190 #endif
00191 if (gLogFh != NULL)
00192     logFilePrint("warn", format, args);
00193 }
00194 
00195 void logWarn(char *format, ...)
00196 /* Log a warn message. */
00197 {
00198 va_list args;
00199 va_start(args, format);
00200 logWarnVa(format, args);
00201 va_end(args);
00202 }
00203 
00204 void logInfoVa(char *format, va_list args)
00205 /* Variable args logInfo. */
00206 {
00207 #ifndef NO_SYSLOG
00208 if (gSysLogOn)
00209     vsyslog(LOG_INFO, format, args);
00210 #endif
00211 if (gLogFh != NULL)
00212     logFilePrint("info", format, args);
00213 }
00214 
00215 void logInfo(char *format, ...)
00216 /* Log an info message. */
00217 {
00218 va_list args;
00219 va_start(args, format);
00220 logInfoVa(format, args);
00221 va_end(args);
00222 }
00223 
00224 void logDebugVa(char *format, va_list args)
00225 /* Variable args logDebug. */
00226 {
00227 #ifndef NO_SYSLOG
00228 if (gSysLogOn)
00229     vsyslog(LOG_DEBUG, format, args);
00230 #endif
00231 if (gLogFh != NULL)
00232     logFilePrint("debug", format, args);
00233 }
00234 
00235 void logDebug(char *format, ...)
00236 /* Log a debug message. */
00237 {
00238 va_list args;
00239 va_start(args, format);
00240 logDebugVa(format, args);
00241 va_end(args);
00242 }
00243 
00244 void logDaemonize(char *progName)
00245 /* daemonize parasol server process, closing open file descriptors and
00246  * starting logging based on the -logFacility and -log command line options .
00247  * if -debug is supplied , don't fork. */
00248 {
00249 if (!optionExists("debug"))
00250     {
00251     int i, maxFiles = getdtablesize();
00252     if (mustFork() != 0)
00253         exit(0);  /* parent goes away */
00254 
00255     /* Close all open files first (before logging) */
00256     for (i = 0; i < maxFiles; i++)
00257         close(i);
00258     }
00259 
00260 /* Set up log handler. */
00261 if (optionExists("log"))
00262     logOpenFile(progName, optionVal("log", NULL));
00263 else    
00264     logOpenSyslog(progName, optionVal("logFacility", NULL));
00265 }
00266 

Generated on Tue Dec 25 18:39:31 2007 for blat by  doxygen 1.5.2