init.c 12 KB

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