5ae6ded1a205ffa55d25a7b4e68fc0fad0f155e5
[obnox/tinyproxy.git] / src / log.c
1 /* $Id: log.c,v 1.18 2002-04-25 18:56:43 rjkaes Exp $
2  *
3  * Logs the various messages which tinyproxy produces to either a log file or
4  * the syslog daemon. Not much to it...
5  *
6  * Copyright (C) 1998  Steven Young
7  * Copyright (C) 1999  Robert James Kaes (rjkaes@flarenet.com)
8  *
9  * This program is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by the
11  * Free Software Foundation; either version 2, or (at your option) any
12  * later version.
13  *
14  * This program is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  */
19
20 #include "tinyproxy.h"
21
22 #include "hashmap.h"
23 #include "log.h"
24
25 static char *syslog_level[] = {
26         NULL,
27         NULL,
28         "CRITICAL",
29         "ERROR",
30         "WARNING",
31         "NOTICE",
32         "INFO",
33         "DEBUG",
34         "CONNECT"
35 };
36
37 #define TIME_LENGTH 16
38 #define STRING_LENGTH 800
39
40 /*
41  * Store the log level setting.
42  */
43 static int log_level = LOG_INFO;
44
45 /*
46  * Hold a listing of log messages which need to be sent once the log
47  * file has been established.
48  * The key is the actual messages (already filled in full), and the value
49  * is the log level.
50  */
51 static hashmap_t log_message_storage;
52
53 /*
54  * Set the log level for writing to the log file.
55  */
56 void
57 set_log_level(int level)
58 {
59         log_level = level;
60 }
61
62 /*
63  * This routine logs messages to either the log file or the syslog function.
64  */
65 void
66 log_message(int level, char *fmt, ...)
67 {
68         va_list args;
69         time_t nowtime;
70         FILE *cf;
71
72         char time_string[TIME_LENGTH];
73 #if defined(HAVE_SYSLOG_H) && !defined(HAVE_VSYSLOG_H)
74         char str[STRING_LENGTH];
75 #endif
76
77 #ifdef NDEBUG
78         /*
79          * Figure out if we should write the message or not.
80          */
81         if (log_level == LOG_CONN) {
82                 if (level == LOG_INFO)
83                         return;
84         } else if (log_level == LOG_INFO) {
85                 if (level > LOG_INFO && level != LOG_CONN)
86                         return;
87         } else if (level > log_level)
88                 return;
89 #endif
90
91 #ifdef HAVE_SYSLOG_H
92         if (config.syslog && level == LOG_CONN)
93                 level = LOG_INFO;
94 #endif
95
96         va_start(args, fmt);
97
98         /*
99          * If the config file hasn't been processed, then we need to store
100          * the messages for later processing.
101          */
102         if (!processed_config_file) {
103                 char string_level[4];
104
105                 if (!log_message_storage) {
106                         log_message_storage = hashmap_create(1);
107                         if (!log_message_storage)
108                                 return;
109                 }
110
111                 vsnprintf(str, STRING_LENGTH, fmt, args);
112                 snprintf(string_level, 4, "%d", level);
113
114                 hashmap_insert(log_message_storage, str,
115                                string_level, strlen(string_level) + 1);
116
117                 va_end(args);
118
119                 return;
120         }
121
122 #ifdef HAVE_SYSLOG_H
123         if (config.syslog) {
124 #  ifdef HAVE_VSYSLOG_H
125                 vsyslog(level, fmt, args);
126 #  else
127                 vsnprintf(str, STRING_LENGTH, fmt, args);
128                 syslog(level, "%s", str);
129 #  endif
130         } else {
131 #endif
132                 nowtime = time(NULL);
133                 /* Format is month day hour:minute:second (24 time) */
134                 strftime(time_string, TIME_LENGTH, "%b %d %H:%M:%S",
135                          localtime(&nowtime));
136
137                 if (!(cf = config.logf))
138                         cf = stderr;
139
140                 fprintf(cf, "%-9s %s [%ld]: ", syslog_level[level],
141                         time_string, (long int) getpid());
142                 vfprintf(cf, fmt, args);
143                 fprintf(cf, "\n");
144                 fflush(cf);
145 #ifdef HAVE_SYSLOG_H
146         }
147 #endif
148
149         va_end(args);
150 }
151
152 /*
153  * This needs to send any stored log messages.
154  */
155 void
156 send_stored_logs(void)
157 {
158         hashmap_iter iter;
159         char *level;
160         char *string;
161         
162         for (iter = hashmap_first(log_message_storage);
163              iter != hashmap_is_end(log_message_storage, iter);
164              ++iter) {
165                 hashmap_return_entry(log_message_storage,
166                                      iter,
167                                      &string,
168                                      (void **)&level);
169         }
170
171         hashmap_delete(log_message_storage);
172         log_message_storage = NULL;
173 }