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