00001
00002
00003
00004
00005
00006
00007
00008
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
00046 dbg_err_if (klog_args_new(&ka));
00047
00048
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
00114
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
00170 dbg_goto_if (level < KLOG_DEBUG || level >= KLOG_LEVEL_UNKNOWN, end);
00171
00172
00173 if (level < kl->threshold)
00174 goto end;
00175
00176
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
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;
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
00287 dbg_err_if(klog_args(ls, &kargs));
00288
00289
00290 dbg_err_if(klog_open(kargs, &kl));
00291
00292 klog_args_free(kargs);
00293 kargs = NULL;
00294
00295
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
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
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
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
00368 static int klog_logopt (const char *options)
00369 {
00370 char *o2 = NULL;
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
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
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
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
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