/* $NetBSD: logger.c,v 1.4 2006/09/09 16:22:09 manu Exp $ */ /* $KAME: logger.c,v 1.9 2002/09/03 14:37:03 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #include <sys/types.h> #include <sys/param.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #ifdef HAVE_STDARG_H #include <stdarg.h> #else #include <varargs.h> #endif #if TIME_WITH_SYS_TIME # include <sys/time.h> # include <time.h> #else # if HAVE_SYS_TIME_H # include <sys/time.h> # else # include <time.h> # endif #endif #include "logger.h" #include "var.h" #include "gcmalloc.h" struct log * log_open(siz, fname) size_t siz; char *fname; { struct log *p; p = (struct log *)racoon_malloc(sizeof(*p)); if (p == NULL) return NULL; memset(p, 0, sizeof(*p)); p->buf = (char **)racoon_malloc(sizeof(char *) * siz); if (p->buf == NULL) { racoon_free(p); return NULL; } memset(p->buf, 0, sizeof(char *) * siz); p->tbuf = (time_t *)racoon_malloc(sizeof(time_t *) * siz); if (p->tbuf == NULL) { racoon_free(p->buf); racoon_free(p); return NULL; } memset(p->tbuf, 0, sizeof(time_t *) * siz); p->siz = siz; if (fname) p->fname = racoon_strdup(fname); return p; } /* * append string to ring buffer. * string must be \n-terminated (since we add timestamps). * even if not, we'll add \n to avoid formatting mistake (see log_close()). */ void log_add(p, str) struct log *p; char *str; { /* syslog if p->fname == NULL? */ if (p->buf[p->head]) racoon_free(p->buf[p->head]); p->buf[p->head] = racoon_strdup(str); p->tbuf[p->head] = time(NULL); p->head++; p->head %= p->siz; } /* * write out string to the log file, as is. * \n-termination is up to the caller. if you don't add \n, the file * format may be broken. */ int log_print(p, str) struct log *p; char *str; { FILE *fp; if (p->fname == NULL) return -1; /*XXX syslog?*/ fp = fopen(p->fname, "a"); if (fp == NULL) return -1; fprintf(fp, "%s", str); fclose(fp); return 0; } int log_vprint(struct log *p, const char *fmt, ...) { va_list ap; FILE *fp; if (p->fname == NULL) return -1; /*XXX syslog?*/ fp = fopen(p->fname, "a"); if (fp == NULL) return -1; va_start(ap, fmt); vfprintf(fp, fmt, ap); va_end(ap); fclose(fp); return 0; } int log_vaprint(struct log *p, const char *fmt, va_list ap) { FILE *fp; if (p->fname == NULL) return -1; /*XXX syslog?*/ fp = fopen(p->fname, "a"); if (fp == NULL) return -1; vfprintf(fp, fmt, ap); fclose(fp); return 0; } /* * write out content of ring buffer, and reclaim the log structure */ int log_close(p) struct log *p; { FILE *fp; int i, j; char ts[256]; struct tm *tm; if (p->fname == NULL) goto nowrite; fp = fopen(p->fname, "a"); if (fp == NULL) goto nowrite; for (i = 0; i < p->siz; i++) { j = (p->head + i) % p->siz; if (p->buf[j]) { tm = localtime(&p->tbuf[j]); strftime(ts, sizeof(ts), "%B %d %T", tm); fprintf(fp, "%s: %s\n", ts, p->buf[j]); if (*(p->buf[j] + strlen(p->buf[j]) - 1) != '\n') fprintf(fp, "\n"); } } fclose(fp); nowrite: log_free(p); return 0; } void log_free(p) struct log *p; { int i; for (i = 0; i < p->siz; i++) racoon_free(p->buf[i]); racoon_free(p->buf); racoon_free(p->tbuf); if (p->fname) racoon_free(p->fname); racoon_free(p); } #ifdef TEST struct log *l; void vatest(const char *fmt, ...) { va_list ap; va_start(ap, fmt); log_vaprint(l, fmt, ap); va_end(ap); } int main(argc, argv) int argc; char **argv; { int i; l = log_open(30, "/tmp/hoge"); if (l == NULL) errx(1, "hoge"); for (i = 0; i < 50; i++) { log_add(l, "foo"); log_add(l, "baa"); log_add(l, "baz"); } log_print(l, "hoge\n"); log_vprint(l, "hoge %s\n", "this is test"); vatest("%s %s\n", "this is", "vprint test"); abort(); log_free(l); } #endif