1/* $KAME: logger.c,v 1.8 2001/04/03 15:51:56 thorpej Exp $ */ 2 3/* 4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the project nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32#include <sys/types.h> 33#include <sys/param.h> 34 35#include <stdlib.h> 36#include <stdio.h> 37#include <string.h> 38#include <errno.h> 39#ifdef HAVE_STDARG_H 40#include <stdarg.h> 41#else 42#include <varargs.h> 43#endif 44#if TIME_WITH_SYS_TIME 45# include <sys/time.h> 46# include <time.h> 47#else 48# if HAVE_SYS_TIME_H 49# include <sys/time.h> 50# else 51# include <time.h> 52# endif 53#endif 54 55#include "logger.h" 56#include "var.h" 57#include "gcmalloc.h" 58 59struct log * 60log_open(siz, fname) 61 size_t siz; 62 char *fname; 63{ 64 struct log *p; 65 66 p = (struct log *)racoon_malloc(sizeof(*p)); 67 if (p == NULL) 68 return NULL; 69 memset(p, 0, sizeof(*p)); 70 71 p->buf = (char **)racoon_malloc(sizeof(char *) * siz); 72 if (p->buf == NULL) { 73 racoon_free(p); 74 return NULL; 75 } 76 memset(p->buf, 0, sizeof(char *) * siz); 77 78 p->tbuf = (time_t *)racoon_malloc(sizeof(time_t *) * siz); 79 if (p->tbuf == NULL) { 80 racoon_free(p); 81 racoon_free(p->buf); 82 return NULL; 83 } 84 memset(p->tbuf, 0, sizeof(time_t *) * siz); 85 86 p->siz = siz; 87 if (fname) 88 p->fname = strdup(fname); 89 90 return p; 91} 92 93/* 94 * append string to ring buffer. 95 * string must be \n-terminated (since we add timestamps). 96 * even if not, we'll add \n to avoid formatting mistake (see log_close()). 97 */ 98void 99log_add(p, str) 100 struct log *p; 101 char *str; 102{ 103 /* syslog if p->fname == NULL? */ 104 if (p->buf[p->head]) 105 racoon_free(p->buf[p->head]); 106 p->buf[p->head] = strdup(str); 107 p->tbuf[p->head] = time(NULL); 108 p->head++; 109 p->head %= p->siz; 110} 111 112/* 113 * write out string to the log file, as is. 114 * \n-termination is up to the caller. if you don't add \n, the file 115 * format may be broken. 116 */ 117int 118log_print(p, str) 119 struct log *p; 120 char *str; 121{ 122 FILE *fp; 123 124 if (p->fname == NULL) 125 return -1; 126 fp = fopen(p->fname, "a"); 127 if (fp == NULL) 128 return -1; 129 fprintf(fp, "%s", str); 130 fclose(fp); 131 132 return 0; 133} 134 135int 136log_vprint(struct log *p, const char *fmt, ...) 137{ 138 va_list ap; 139 140 FILE *fp; 141 142 if (p->fname == NULL) 143 return -1; 144 fp = fopen(p->fname, "a"); 145 if (fp == NULL) 146 return -1; 147 va_start(ap, fmt); 148 vfprintf(fp, fmt, ap); 149 va_end(ap); 150 151 fclose(fp); 152 153 return 0; 154} 155 156int 157log_vaprint(struct log *p, const char *fmt, va_list ap) 158{ 159 FILE *fp; 160 161 if (p->fname == NULL) 162 return -1; 163 fp = fopen(p->fname, "a"); 164 if (fp == NULL) 165 return -1; 166 vfprintf(fp, fmt, ap); 167 fclose(fp); 168 169 return 0; 170} 171 172/* 173 * write out content of ring buffer, and reclaim the log structure 174 */ 175int 176log_close(p) 177 struct log *p; 178{ 179 FILE *fp; 180 int i, j; 181 char ts[256]; 182 struct tm *tm; 183 184 if (p->fname == NULL) 185 goto nowrite; 186 fp = fopen(p->fname, "a"); 187 if (fp == NULL) 188 goto nowrite; 189 190 for (i = 0; i < p->siz; i++) { 191 j = (p->head + i) % p->siz; 192 if (p->buf[j]) { 193 tm = localtime(&p->tbuf[j]); 194 strftime(ts, sizeof(ts), "%B %d %T", tm); 195 fprintf(fp, "%s: %s\n", ts, p->buf[j]); 196 if (*(p->buf[j] + strlen(p->buf[j]) - 1) != '\n') 197 fprintf(fp, "\n"); 198 } 199 } 200 fclose(fp); 201 202nowrite: 203 log_free(p); 204 return 0; 205} 206 207void 208log_free(p) 209 struct log *p; 210{ 211 int i; 212 213 for (i = 0; i < p->siz; i++) 214 racoon_free(p->buf[i]); 215 racoon_free(p->buf); 216 racoon_free(p->tbuf); 217 if (p->fname) 218 racoon_free(p->fname); 219 racoon_free(p); 220} 221 222#ifdef TEST 223struct log *l; 224 225void 226vatest(const char *fmt, ...) 227{ 228 va_list ap; 229 va_start(ap, fmt); 230 log_vaprint(l, fmt, ap); 231 va_end(ap); 232} 233 234int 235main(argc, argv) 236 int argc; 237 char **argv; 238{ 239 int i; 240 241 l = log_open(30, "/tmp/hoge"); 242 if (l == NULL) 243 errx(1, "hoge"); 244 245 for (i = 0; i < 50; i++) { 246 log_add(l, "foo"); 247 log_add(l, "baa"); 248 log_add(l, "baz"); 249 } 250 log_print(l, "hoge\n"); 251 log_vprint(l, "hoge %s\n", "this is test"); 252 vatest("%s %s\n", "this is", "vprint test"); 253 abort(); 254 log_free(l); 255} 256 257#endif 258