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
63struct log *
64log_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 */
102void
103log_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 */
121int
122log_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
139int
140log_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
160int
161log_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 */
179int
180log_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
206nowrite:
207	log_free(p);
208	return 0;
209}
210
211void
212log_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
227struct log *l;
228
229void
230vatest(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
238int
239main(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