klog.c

00001 /*
00002  * Copyright (c) 2005-2012 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: klog.c,v 1.28 2009/01/27 12:27:21 tho Exp $
00009  */
00010 
00011 #include "klone_conf.h"
00012 #include <time.h>
00013 #include <u/libu.h>
00014 #include <klone/klog.h>
00015 #include <klone/klogprv.h>
00016 
00017 static int klog_args_new (klog_args_t **pka);
00018 static int klog_args_check (klog_args_t *ka);
00019 
00020 static int klog_type (const char *type);
00021 static int klog_facility (klog_args_t *ka, const char *fac);
00022 static int klog_threshold (const char *threshold);
00023 static int klog_logopt (const char *options);
00024 
00025 
00037 int klog_args (u_config_t *ls, klog_args_t **pka)
00038 {
00039     const char *cs;
00040     klog_args_t *ka = NULL;
00041 
00042     dbg_return_if (ls == NULL, ~0);
00043     dbg_return_if (pka == NULL, ~0);
00044 
00045     /* here defaults are set */
00046     dbg_err_if (klog_args_new(&ka));
00047 
00048     /* read in config values */
00049     ka->type = klog_type(u_config_get_subkey_value(ls, "type"));
00050 
00051     if ((cs = u_config_get_subkey_value(ls, "ident")) != NULL)
00052         ka->ident = u_strdup(cs);
00053 
00054     ka->threshold = klog_threshold(u_config_get_subkey_value(ls, "threshold"));
00055 
00056     if ((cs = u_config_get_subkey_value(ls, "memory.limit")) != NULL)
00057     {
00058         dbg_err_ifm (u_atoi(cs, &ka->mlimit), 
00059                 "'memory.limit' bad value: %s", cs);
00060     }
00061 
00062     if ((cs = u_config_get_subkey_value(ls, "file.basename")) != NULL) 
00063         ka->fbasename = u_strdup(cs);
00064 
00065     if ((cs = u_config_get_subkey_value(ls, "file.limit")) != NULL)
00066     {
00067         dbg_err_ifm (u_atoi(cs, &ka->flimit), 
00068                 "'file.limit' bad value: %s", cs);
00069     }
00070 
00071     if ((cs = u_config_get_subkey_value(ls, "file.splits")) != NULL)
00072     {
00073         dbg_err_ifm (u_atoi(cs, &ka->fsplits),
00074                 "'file.splits' bad value: %s", cs);
00075     }
00076 
00077     #ifdef HAVE_SYSLOG
00078     ka->sfacility = 
00079         klog_facility(ka, u_config_get_subkey_value(ls, "syslog.facility"));
00080 
00081     ka->soptions = klog_logopt(u_config_get_subkey_value(ls, "syslog.options"));
00082     #endif
00083 
00084     dbg_return_if (klog_args_check(ka), ~0);
00085 
00086     *pka = ka;
00087     
00088     return 0;
00089 err:
00090     if (ka)
00091         klog_args_free(ka);
00092     return ~0;
00093 }
00094 
00105 int klog_open (klog_args_t *ka, klog_t **pkl)
00106 {
00107     int rv;
00108     klog_t *kl = NULL;
00109 
00110     dbg_return_if (pkl == NULL, ~0);
00111     dbg_return_if (ka == NULL, ~0);
00112 
00113     /* create a klog_t object: each per-type init will create and stick 
00114      * its klog_*_t obj */
00115     dbg_err_if (klog_new(ka->type, ka->threshold, ka->ident, &kl));
00116 
00117     switch (ka->type)
00118     {
00119         case KLOG_TYPE_MEM:
00120             rv = klog_open_mem(kl, ka->mlimit);
00121             break;
00122         case KLOG_TYPE_FILE:
00123             rv = klog_open_file(kl, ka->fbasename, ka->fsplits, ka->flimit);
00124             break;
00125         #ifdef HAVE_SYSLOG
00126         case KLOG_TYPE_SYSLOG:
00127             rv = klog_open_syslog(kl, ka->sfacility, ka->soptions);
00128             break;
00129         #endif
00130         default:
00131             return ~0;
00132     }
00133 
00134     dbg_err_if (rv);
00135     *pkl = kl;
00136     
00137     return 0;
00138 err:
00139     klog_close(kl);
00140     return ~0;
00141 }
00142 
00158 int klog (klog_t *kl, int level, const char *fmt, ...)
00159 {
00160     va_list ap;
00161     int rv = 0;
00162 
00163     dbg_return_if (kl == NULL, ~0);
00164     dbg_return_if (fmt == NULL, ~0);
00165     dbg_return_if (!IS_KLOG_TYPE(kl->type), ~0);
00166 
00167     va_start(ap, fmt);
00168     
00169     /* get rid of spurious stuff */
00170     dbg_goto_if (level < KLOG_DEBUG || level >= KLOG_LEVEL_UNKNOWN, end);
00171 
00172     /* early filtering of msgs with level lower than threshold */
00173     if (level < kl->threshold)
00174         goto end;
00175     
00176     /* if the log function is set call it with the supplied args */
00177     if (kl->cb_log)
00178         rv = kl->cb_log(kl, level, fmt, ap);
00179 
00180 end:
00181     va_end(ap);
00182 
00183     return rv;
00184 }
00185 
00193 void klog_close (klog_t *kl)
00194 {
00195     if (kl == NULL) 
00196         return;
00197     if (!IS_KLOG_TYPE(kl->type)) 
00198         return;
00199 
00200     /* call private close function */
00201     if (kl->cb_close)
00202         kl->cb_close(kl);
00203 
00204     U_FREE(kl);
00205 
00206     return;
00207 }
00208 
00221 int klog_getln (klog_t *kl, size_t nth, char ln[])
00222 {
00223     dbg_return_if (kl == NULL, ~0);
00224     dbg_return_if (!IS_KLOG_TYPE(kl->type), ~0);
00225 
00226     if (kl->cb_getln)
00227         return kl->cb_getln(kl, nth, ln);
00228     
00229     return 0;
00230 }
00231 
00241 int klog_clear (klog_t *kl)
00242 {
00243     dbg_return_if (kl == NULL, ~0);
00244     dbg_return_if (!IS_KLOG_TYPE(kl->type), ~0);
00245 
00246     if (kl->cb_clear)
00247         return kl->cb_clear(kl);
00248 
00249     return ~0;
00250 }
00251 
00259 ssize_t klog_countln (klog_t *kl)
00260 {
00261     dbg_return_if (kl == NULL, -1);
00262     dbg_return_if (!IS_KLOG_TYPE(kl->type), ~0);
00263 
00264     if (kl->cb_countln)
00265         return kl->cb_countln(kl);
00266 
00267     return -1;      /* XXX should be 0 ? */
00268 }
00269 
00281 int klog_open_from_config(u_config_t *ls, klog_t **pkl)
00282 {
00283     klog_t *kl = NULL;
00284     klog_args_t *kargs = NULL;
00285 
00286     /* parse config parameters */
00287     dbg_err_if(klog_args(ls, &kargs));
00288 
00289     /* create a klog object */
00290     dbg_err_if(klog_open(kargs, &kl));
00291 
00292     klog_args_free(kargs);
00293     kargs = NULL;
00294 
00295     /* stick it */
00296     *pkl = kl;
00297 
00298     return 0;
00299 err:
00300     if(kargs)
00301         klog_args_free(kargs);
00302     if(kl)
00303         klog_close(kl);
00304     return ~0;
00305 }
00306 
00316 int klog_flush (klog_t *kl)
00317 {
00318     dbg_return_if (kl == NULL, ~0);
00319     dbg_return_if (!IS_KLOG_TYPE(kl->type), ~0);
00320 
00321     /* call private flush function */
00322     if (kl->cb_flush)
00323         return kl->cb_flush(kl);
00324 
00325     return 0;
00326 }
00327 
00328 void klog_args_free (klog_args_t *ka)
00329 {
00330     U_FREE(ka->ident);
00331     U_FREE(ka->fbasename);
00332     U_FREE(ka);
00333     return;
00334 }
00335 
00336 /* map type directive to the internal representation */
00337 static int klog_type (const char *type)
00338 {
00339     dbg_return_if (type == NULL, KLOG_TYPE_UNKNOWN);
00340 
00341     if (!strcasecmp(type, "memory"))
00342         return KLOG_TYPE_MEM;
00343     else if (!strcasecmp(type, "file"))
00344         return KLOG_TYPE_FILE;
00345     else if (!strcasecmp(type, "syslog"))
00346         return KLOG_TYPE_SYSLOG;
00347     else
00348         return KLOG_TYPE_UNKNOWN;
00349 }
00350 
00351 /* map threshold directive to the internal representation */
00352 static int klog_threshold (const char *threshold)
00353 {
00354     int i;
00355 
00356     dbg_return_if (threshold == NULL, KLOG_LEVEL_UNKNOWN);
00357 
00358     for (i = KLOG_DEBUG; i <= KLOG_EMERG; i++)
00359         if (!strcasecmp(threshold, kloglev[i]))
00360             return i;
00361 
00362     warn("bad threshold value: \'%s\'", threshold);
00363     return KLOG_LEVEL_UNKNOWN;
00364 }
00365 
00366 #ifdef HAVE_SYSLOG
00367 /* map threshold directive to the internal representation */
00368 static int klog_logopt (const char *options)
00369 {
00370     char *o2 = NULL;    /* 'options' dupped for safe u_tokenize() */
00371     int i, logopt = 0;
00372     enum { NOPTS = 4 };
00373     char *optv[NOPTS + 1];
00374     
00375     dbg_return_if (options == NULL, 0);
00376     dbg_return_if ((o2 = u_strdup(options)) == NULL, 0);
00377 
00378     dbg_err_if (u_tokenize(o2, " \t", optv, NOPTS + 1));
00379     
00380     for (i = 0; optv[i] != NULL; i++)
00381     {
00382         if (!strcasecmp(optv[i], "LOG_CONS"))
00383             logopt |= LOG_CONS;
00384         else if (!strcasecmp(optv[i], "LOG_NDELAY"))
00385             logopt |= LOG_NDELAY;
00386 #ifdef HAVE_LOG_PERROR
00387         else if (!strcasecmp(optv[i], "LOG_PERROR"))
00388             logopt |= LOG_PERROR;
00389 #endif  /* HAVE_LOG_PERROR */
00390         else if (!strcasecmp(optv[i], "LOG_PID"))
00391             logopt |= LOG_PID;
00392         else
00393             warn("bad log option: \'%s\'", optv[i]);
00394     }
00395 
00396     U_FREE(o2);
00397     return logopt;
00398 
00399 err:
00400     U_FREE(o2);
00401     return 0;
00402 }
00403 #endif
00404 
00405 /* map LOG_LOCAL[0-7] strings into syslog(3) #define'd values */
00406 static int klog_facility (klog_args_t *ka, const char *fac)
00407 {
00408     dbg_goto_if (fac == NULL, end);
00409     nop_goto_if (ka->type != KLOG_TYPE_SYSLOG, end);
00410 
00411     if (!strcasecmp(fac, "LOG_LOCAL0")) 
00412         return LOG_LOCAL0;
00413     else if (!strcasecmp(fac, "LOG_LOCAL1")) 
00414         return LOG_LOCAL1;
00415     else if (!strcasecmp(fac, "LOG_LOCAL2")) 
00416         return LOG_LOCAL2;
00417     else if (!strcasecmp(fac, "LOG_LOCAL3")) 
00418         return LOG_LOCAL3;
00419     else if (!strcasecmp(fac, "LOG_LOCAL4")) 
00420         return LOG_LOCAL4;
00421     else if (!strcasecmp(fac, "LOG_LOCAL5")) 
00422         return LOG_LOCAL5;
00423     else if (!strcasecmp(fac, "LOG_LOCAL6")) 
00424         return LOG_LOCAL6;
00425     else if (!strcasecmp(fac, "LOG_LOCAL7")) 
00426         return LOG_LOCAL7;
00427     else
00428         warn("unknown facility value \'%s\'", fac);
00429         /* fall through */
00430 end:
00431     return KLOG_FACILITY_UNKNOWN; 
00432 }
00433 
00434 static int klog_args_new (klog_args_t **pka)
00435 {
00436     dbg_return_if (pka == NULL, ~0);
00437 
00438     *pka = u_zalloc(sizeof(klog_args_t));
00439     dbg_return_if (*pka == NULL, ~0);
00440 
00441     return 0;
00442 }
00443 
00444 static int klog_args_check (klog_args_t *ka)
00445 {
00446     dbg_return_if (ka == NULL, ~0);
00447 
00448     if (ka->type == KLOG_TYPE_UNKNOWN)
00449         warn_err("unknown log type");
00450 
00451     /* do not filter if not specified or if a wrong value has been supplied */
00452     if (ka->threshold == KLOG_LEVEL_UNKNOWN)
00453     {
00454         u_dbg("threshold unspecified: assuming lowest possible (DEBUG)");
00455         ka->threshold = KLOG_DEBUG;
00456     }
00457 
00458     switch (ka->type)
00459     {
00460         case KLOG_TYPE_MEM:
00461             if (ka->mlimit == 0)
00462                 ka->mlimit = KLOG_MLIMIT_DFL;
00463             break;
00464         case KLOG_TYPE_FILE:
00465             if (ka->fbasename == NULL)
00466                 warn_err("log file path is mandatory !");
00467             if (ka->fsplits == 0)
00468                 ka->fsplits =  KLOG_FSPLITS_DFL;
00469             if (ka->flimit == 0)
00470                 ka->flimit = KLOG_FLIMIT_DFL;
00471             break;
00472         case KLOG_TYPE_SYSLOG:
00473             if (ka->sfacility == KLOG_FACILITY_UNKNOWN)
00474             {
00475                 warn("facility unspecified: defaults to LOG_LOCAL7");
00476                 ka->sfacility = LOG_LOCAL7;
00477             }
00478             break;
00479         default:
00480             warn_err("what are you doing here ?");
00481     }
00482 
00483     return 0;
00484 err:
00485     return ~0;
00486 }
00487 
00488 

←Products
Copyright © 2005-2012 - KoanLogic S.r.l. - All rights reserved