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 *
log_open(siz,fname)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
log_add(p,str)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
log_print(p,str)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
log_vprint(struct log * p,const char * fmt,...)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
log_vaprint(struct log * p,const char * fmt,va_list ap)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
log_close(p)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
log_free(p)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
vatest(const char * fmt,...)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
main(argc,argv)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