1 static const char version[] = "$Id: init.c,v 1.22 2013/09/29 17:50:09 valtri Exp $";
2
3 /*
4 * init.c
5 *
6 * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
7 *
8 * See the COPYING file for the terms of usage and distribution.
9 */
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #include <log4c/init.h>
15 #include <log4c/category.h>
16 #include <log4c/appender.h>
17 #include <log4c/layout.h>
18 #include <log4c/rollingpolicy.h>
19 #include <log4c/rc.h>
20 #include <sd/error.h>
21 #include <sd/sprintf.h>
22 #include <sd/factory.h>
23 #include <sd/sd_xplatform.h>
24 #include <stdlib.h>
25
26 #include <appender_type_stream.h>
27 #include <appender_type_stream2.h>
28 #include <appender_type_syslog.h>
29 #include <appender_type_mmap.h>
30 #include <appender_type_rollingfile.h>
31 #include <rollingpolicy_type_sizewin.h>
32 #include <layout_type_basic.h>
33 #include <layout_type_dated.h>
34 #include <layout_type_dated_local.h>
35 #include <layout_type_basic_r.h>
36 #include <layout_type_dated_r.h>
37 #include <layout_type_dated_local_r.h>
38
39 #if defined(__LOG4C_DEBUG__) && defined(__GLIBC__)
40 #include <mcheck.h>
41 #endif
42
43 static const log4c_layout_type_t * const layout_types[] = {
44 &log4c_layout_type_basic,
45 &log4c_layout_type_dated,
46 &log4c_layout_type_dated_local,
47 &log4c_layout_type_basic_r,
48 &log4c_layout_type_dated_r,
49 &log4c_layout_type_dated_local_r,
50 };
51 static size_t nlayout_types = sizeof(layout_types) / sizeof(layout_types[0]);
52
53 static const log4c_appender_type_t * const appender_types[] = {
54 &log4c_appender_type_stream,
55 &log4c_appender_type_stream2,
56 #ifdef HAVE_MMAP
57 &log4c_appender_type_mmap,
58 #endif
59 #ifdef HAVE_SYSLOG_H
60 &log4c_appender_type_syslog,
61 #endif
62 #ifdef WITH_ROLLINGFILE
63 &log4c_appender_type_rollingfile
64 #endif
65 };
66 static size_t nappender_types = sizeof(appender_types) / sizeof(appender_types[0]);
67
68 #ifdef WITH_ROLLINGFILE
69 static const log4c_rollingpolicy_type_t * const rollingpolicy_types[] = {
70 &log4c_rollingpolicy_type_sizewin
71 };
72 static size_t nrollingpolicy_types =
73 sizeof(rollingpolicy_types) / sizeof(rollingpolicy_types[0]);
74 #endif
75
76 static int log4c_is_init = 0;
77 typedef struct rcfile
78 {
79 char name[256];
80 time_t ctime;
81 int exists;
82 } rcfile_t;
83
84 static rcfile_t rcfiles[] = {
85 { "$LOG4C_RCPATH/log4crc" },
86 { "$HOME/.log4crc" },
87 { "./log4crc" }
88 };
89
90 static const int nrcfiles = sizeof(rcfiles) / sizeof(rcfiles[0]);
91
92
93 /******************************************************************************/
log4c_init(void)94 extern int log4c_init(void)
95 {
96 size_t i;
97 int ret = 0;
98
99 sd_debug("log4c_init[");
100
101 /* activate GLIBC allocation debugging */
102 #if defined(__LOG4C_DEBUG__) && defined(__GLIBC__)
103 mtrace();
104 #endif
105
106 if (log4c_is_init){
107 sd_debug("log4c already initialized ]");
108 return 0;
109 }
110
111 log4c_is_init++;
112
113 /* Initialize default types: layouts, appenders, rollingpolicies */
114 sd_debug("intializing default types: appenders, layouts, rollingpolicies");
115 for (i = 0; i < nlayout_types; i++)
116 log4c_layout_type_set(layout_types[i]);
117
118 for (i = 0; i < nappender_types; i++)
119 log4c_appender_type_set(appender_types[i]);
120 #ifdef WITH_ROLLINGFILE
121 for (i = 0; i < nrollingpolicy_types; i++)
122 log4c_rollingpolicy_type_set(rollingpolicy_types[i]);
123 #endif
124
125 /* load configuration files */
126 {
127 int i;
128 sd_debug("looking for conf files...");
129 snprintf(rcfiles[0].name, sizeof(rcfiles[0].name) - 1, "%s/log4crc",
130 getenv("LOG4C_RCPATH") ? getenv("LOG4C_RCPATH") : LOG4C_RCPATH);
131 snprintf(rcfiles[1].name, sizeof(rcfiles[1].name) - 1, "%s/.log4crc",
132 getenv("HOME") ? getenv("HOME") : "");
133
134 for (i = 0; i < nrcfiles; i++) {
135 sd_debug("checking for conf file at '%s'", rcfiles[i].name);
136 if (SD_ACCESS_READ(rcfiles[i].name)) continue;
137 if (SD_STAT_CTIME(rcfiles[i].name,&rcfiles[i].ctime) != 0)
138 sd_error("sd_stat_ctime %s failed", rcfiles[i].name);
139 rcfiles[i].exists=1;
140 if (log4c_load(rcfiles[i].name) == -1) {
141 sd_error("loading %s failed", rcfiles[i].name);
142 ret = -1;
143 }
144 else {
145 sd_debug("loading %s succeeded", rcfiles[i].name);
146 ret = 0;
147 break;
148 }
149 }
150 }
151
152 /* override configuration with environment variables */
153 {
154 const char* priority;
155 const char* appender;
156
157 sd_debug("checking environment variables...");
158 if ( (priority = getenv("LOG4C_PRIORITY")) != NULL){
159 sd_debug("setting priority of root category to '%s'",
160 priority);
161 log4c_category_set_priority(log4c_category_get("root"),
162 log4c_priority_to_int(priority));
163 }
164
165 if ( (appender = getenv("LOG4C_APPENDER")) != NULL){
166 sd_debug("setting appender of root category to '%s'",
167 appender);
168 log4c_category_set_appender(log4c_category_get("root"),
169 log4c_appender_get(appender));
170 }
171 }
172
173 /*
174 * For debug dump current types and instances:
175 * this allows the caller of log4c_init() to see:
176 * 1. all types currently registered, including perhaps his own.
177 * 2. all instances instantiated via the configuration file.
178 *
179 * If the caller goes on to programmatically create instaces then he
180 * can call log4c_dump_all_instances() later himself to
181 * verify that they were created as expected.
182 *
183 */
184 #ifdef __SD_DEBUG__
185 if( getenv("SD_DEBUG")){
186 log4c_dump_all_types(stderr);
187 log4c_dump_all_instances(stderr);
188 }
189 #endif
190
191
192 sd_debug("]");
193 return ret;
194 }
195
196 /******************************************************************************/
__log4c_reread(void)197 void __log4c_reread(void)
198 {
199 time_t file_ctime;
200 int i;
201
202 for (i = 0; i < nrcfiles; i++){
203 /* only reread files that existed when we first initialized */
204 if (rcfiles[i].exists && SD_STAT_CTIME(rcfiles[i].name,&file_ctime) == 0){
205 /* time_t is number of second since epoch, just compare for == */
206 if (file_ctime != rcfiles[i].ctime){
207 sd_debug("Need reread on file %s\n",rcfiles[i].name);
208 SD_STAT_CTIME(rcfiles[i].name,&rcfiles[i].ctime);
209 if (log4c_rc_load(log4c_rc, rcfiles[i].name) == -1){
210 sd_error("re-loading config file %s failed", rcfiles[i].name);
211 }
212 }
213 }
214 }
215 }
216
217 /******************************************************************************/
218 /*
219 * Rereads any log4crc files that have changed
220 */
log4c_reread(void)221 void log4c_reread(void)
222 {
223 #ifdef __ENABLE_REREAD__
224 if (0 != log4c_rc->config.reread){
225 __log4c_reread();
226 }
227 #endif
228 }
229
230
231
232 /******************************************************************************/
log4c_fini(void)233 extern int log4c_fini(void)
234 {
235 /* Some acceptable use of goto here to avoid lots of nested ifs
236 * when we need a quick exit
237 */
238 sd_debug("log4c_fini[");
239 if (log4c_rc->config.nocleanup){
240 sd_debug("not cleaning up--nocleanup specified in conf");
241 goto log4c_fini_exit;
242 }
243
244 if (!log4c_is_init){
245 sd_debug("not cleaning up--log4c not initialized");
246 goto log4c_fini_exit;
247 }
248
249 log4c_is_init--;
250
251 sd_debug("cleaning up category, appender, layout and"
252 "rollingpolicy instances");
253 if (log4c_category_factory) {
254 sd_factory_delete(log4c_category_factory);
255 log4c_category_factory = NULL;
256 }
257
258 if (log4c_appender_factory) {
259 sd_factory_delete(log4c_appender_factory);
260 log4c_appender_factory = NULL;
261 }
262 log4c_appender_types_free();
263
264 if (log4c_layout_factory) {
265 sd_factory_delete(log4c_layout_factory);
266 log4c_layout_factory = NULL;
267 }
268 log4c_layout_types_free();
269
270 #ifdef WITH_ROLLINGFILE
271 if (log4c_rollingpolicy_factory) {
272 sd_factory_delete(log4c_rollingpolicy_factory);
273 log4c_rollingpolicy_factory = NULL;
274 }
275 log4c_rollingpolicy_types_free();
276 #endif
277
278 #ifdef __SD_DEBUG__
279 if( getenv("SD_DEBUG")){
280 sd_debug("Instance dump after cleanup:");
281 log4c_dump_all_instances(stderr);
282 }
283 #endif
284 #if defined(__LOG4C_DEBUG__) && defined(__GLIBC__)
285 muntrace();
286 #endif
287
288 log4c_fini_exit:
289 sd_debug("]");
290
291 return 0;
292 }
293
294
295 /******************************************************************************/
296 #ifdef __GNUC__
__log4c_init(void)297 extern void __attribute__ ((constructor)) __log4c_init(void)
298 {
299 #ifdef WITH_CONSTRUCTORS
300 log4c_init();
301 #endif
302 }
303
__log4c_fini(void)304 extern void __attribute__ ((destructor)) __log4c_fini(void)
305 {
306 #ifdef WITH_CONSTRUCTORS
307 log4c_fini();
308 #endif
309 }
310 #endif
311
312 /******************************************************************************/
313
log4c_dump_all_types(FILE * fp)314 extern void log4c_dump_all_types(FILE *fp){
315 /*
316 *
317 * For debug, dump all the types that have been registered during init. We just
318 * display the name of the the type for the moment--the rest of the type info
319 * right now consists of functions to call, so not really printable.
320 */
321
322 log4c_appender_types_print(fp);
323 log4c_layout_types_print(fp);
324 #ifdef WITH_ROLLINGFILE
325 log4c_rollingpolicy_types_print(fp);
326 #endif
327 }
328
log4c_dump_all_instances(FILE * fp)329 extern void log4c_dump_all_instances(FILE *fp){
330
331 /*
332 * Also dump any instances that were created during init by
333 * reading the conf file.
334 *
335 * An instances of a type consists of the base
336 * type information (name plus function table) and an instance name and
337 * configuration. For example one can have an instance of the rollingfile
338 * appender which logs to /var/tmp and another instance which logs to
339 * /usr/tmp. They are both of type rollingfile, but are distinct instances of
340 * it
341 */
342 fprintf(fp, "instance dump follows (may be empty):\n");
343 sd_factory_print(log4c_category_factory, fp);
344 sd_factory_print(log4c_appender_factory, fp);
345 sd_factory_print(log4c_layout_factory, fp);
346 #ifdef WITH_ROLLINGFILE
347 sd_factory_print(log4c_rollingpolicy_factory, fp);
348 #endif
349 }
350