• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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