/contrib/bind9/lib/isc/log.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 1763 lines · 1088 code · 278 blank · 397 comment · 350 complexity · 104e7f14f4e1921a28b0c2c2b37cde52 MD5 · raw file

  1. /*
  2. * Copyright (C) 2004-2007, 2009, 2011, 2012 Internet Systems Consortium, Inc. ("ISC")
  3. * Copyright (C) 1999-2003 Internet Software Consortium.
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any
  6. * purpose with or without fee is hereby granted, provided that the above
  7. * copyright notice and this permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  10. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  11. * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  12. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  13. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  14. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  15. * PERFORMANCE OF THIS SOFTWARE.
  16. */
  17. /* $Id$ */
  18. /*! \file
  19. * \author Principal Authors: DCL */
  20. #include <config.h>
  21. #include <errno.h>
  22. #include <stdlib.h>
  23. #include <limits.h>
  24. #include <time.h>
  25. #include <sys/types.h> /* dev_t FreeBSD 2.1 */
  26. #include <isc/dir.h>
  27. #include <isc/file.h>
  28. #include <isc/log.h>
  29. #include <isc/magic.h>
  30. #include <isc/mem.h>
  31. #include <isc/msgs.h>
  32. #include <isc/print.h>
  33. #include <isc/stat.h>
  34. #include <isc/stdio.h>
  35. #include <isc/string.h>
  36. #include <isc/time.h>
  37. #include <isc/util.h>
  38. #define LCTX_MAGIC ISC_MAGIC('L', 'c', 't', 'x')
  39. #define VALID_CONTEXT(lctx) ISC_MAGIC_VALID(lctx, LCTX_MAGIC)
  40. #define LCFG_MAGIC ISC_MAGIC('L', 'c', 'f', 'g')
  41. #define VALID_CONFIG(lcfg) ISC_MAGIC_VALID(lcfg, LCFG_MAGIC)
  42. /*
  43. * XXXDCL make dynamic?
  44. */
  45. #define LOG_BUFFER_SIZE (8 * 1024)
  46. #ifndef PATH_MAX
  47. #define PATH_MAX 1024 /* AIX and others don't define this. */
  48. #endif
  49. /*!
  50. * This is the structure that holds each named channel. A simple linked
  51. * list chains all of the channels together, so an individual channel is
  52. * found by doing strcmp()s with the names down the list. Their should
  53. * be no performance penalty from this as it is expected that the number
  54. * of named channels will be no more than a dozen or so, and name lookups
  55. * from the head of the list are only done when isc_log_usechannel() is
  56. * called, which should also be very infrequent.
  57. */
  58. typedef struct isc_logchannel isc_logchannel_t;
  59. struct isc_logchannel {
  60. char * name;
  61. unsigned int type;
  62. int level;
  63. unsigned int flags;
  64. isc_logdestination_t destination;
  65. ISC_LINK(isc_logchannel_t) link;
  66. };
  67. /*!
  68. * The logchannellist structure associates categories and modules with
  69. * channels. First the appropriate channellist is found based on the
  70. * category, and then each structure in the linked list is checked for
  71. * a matching module. It is expected that the number of channels
  72. * associated with any given category will be very short, no more than
  73. * three or four in the more unusual cases.
  74. */
  75. typedef struct isc_logchannellist isc_logchannellist_t;
  76. struct isc_logchannellist {
  77. const isc_logmodule_t * module;
  78. isc_logchannel_t * channel;
  79. ISC_LINK(isc_logchannellist_t) link;
  80. };
  81. /*!
  82. * This structure is used to remember messages for pruning via
  83. * isc_log_[v]write1().
  84. */
  85. typedef struct isc_logmessage isc_logmessage_t;
  86. struct isc_logmessage {
  87. char * text;
  88. isc_time_t time;
  89. ISC_LINK(isc_logmessage_t) link;
  90. };
  91. /*!
  92. * The isc_logconfig structure is used to store the configurable information
  93. * about where messages are actually supposed to be sent -- the information
  94. * that could changed based on some configuration file, as opposed to the
  95. * the category/module specification of isc_log_[v]write[1] that is compiled
  96. * into a program, or the debug_level which is dynamic state information.
  97. */
  98. struct isc_logconfig {
  99. unsigned int magic;
  100. isc_log_t * lctx;
  101. ISC_LIST(isc_logchannel_t) channels;
  102. ISC_LIST(isc_logchannellist_t) *channellists;
  103. unsigned int channellist_count;
  104. unsigned int duplicate_interval;
  105. int highest_level;
  106. char * tag;
  107. isc_boolean_t dynamic;
  108. };
  109. /*!
  110. * This isc_log structure provides the context for the isc_log functions.
  111. * The log context locks itself in isc_log_doit, the internal backend to
  112. * isc_log_write. The locking is necessary both to provide exclusive access
  113. * to the buffer into which the message is formatted and to guard against
  114. * competing threads trying to write to the same syslog resource. (On
  115. * some systems, such as BSD/OS, stdio is thread safe but syslog is not.)
  116. * Unfortunately, the lock cannot guard against a _different_ logging
  117. * context in the same program competing for syslog's attention. Thus
  118. * There Can Be Only One, but this is not enforced.
  119. * XXXDCL enforce it?
  120. *
  121. * Note that the category and module information is not locked.
  122. * This is because in the usual case, only one isc_log_t is ever created
  123. * in a program, and the category/module registration happens only once.
  124. * XXXDCL it might be wise to add more locking overall.
  125. */
  126. struct isc_log {
  127. /* Not locked. */
  128. unsigned int magic;
  129. isc_mem_t * mctx;
  130. isc_logcategory_t * categories;
  131. unsigned int category_count;
  132. isc_logmodule_t * modules;
  133. unsigned int module_count;
  134. int debug_level;
  135. isc_mutex_t lock;
  136. /* Locked by isc_log lock. */
  137. isc_logconfig_t * logconfig;
  138. char buffer[LOG_BUFFER_SIZE];
  139. ISC_LIST(isc_logmessage_t) messages;
  140. };
  141. /*!
  142. * Used when ISC_LOG_PRINTLEVEL is enabled for a channel.
  143. */
  144. static const char *log_level_strings[] = {
  145. "debug",
  146. "info",
  147. "notice",
  148. "warning",
  149. "error",
  150. "critical"
  151. };
  152. /*!
  153. * Used to convert ISC_LOG_* priorities into syslog priorities.
  154. * XXXDCL This will need modification for NT.
  155. */
  156. static const int syslog_map[] = {
  157. LOG_DEBUG,
  158. LOG_INFO,
  159. LOG_NOTICE,
  160. LOG_WARNING,
  161. LOG_ERR,
  162. LOG_CRIT
  163. };
  164. /*!
  165. * When adding new categories, a corresponding ISC_LOGCATEGORY_foo
  166. * definition needs to be added to <isc/log.h>.
  167. *
  168. * The default category is provided so that the internal default can
  169. * be overridden. Since the default is always looked up as the first
  170. * channellist in the log context, it must come first in isc_categories[].
  171. */
  172. LIBISC_EXTERNAL_DATA isc_logcategory_t isc_categories[] = {
  173. { "default", 0 }, /* "default" must come first. */
  174. { "general", 0 },
  175. { NULL, 0 }
  176. };
  177. /*!
  178. * See above comment for categories on LIBISC_EXTERNAL_DATA, and apply it to modules.
  179. */
  180. LIBISC_EXTERNAL_DATA isc_logmodule_t isc_modules[] = {
  181. { "socket", 0 },
  182. { "time", 0 },
  183. { "interface", 0 },
  184. { "timer", 0 },
  185. { "file", 0 },
  186. { NULL, 0 }
  187. };
  188. /*!
  189. * This essentially constant structure must be filled in at run time,
  190. * because its channel member is pointed to a channel that is created
  191. * dynamically with isc_log_createchannel.
  192. */
  193. static isc_logchannellist_t default_channel;
  194. /*!
  195. * libisc logs to this context.
  196. */
  197. LIBISC_EXTERNAL_DATA isc_log_t *isc_lctx = NULL;
  198. /*!
  199. * Forward declarations.
  200. */
  201. static isc_result_t
  202. assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
  203. const isc_logmodule_t *module, isc_logchannel_t *channel);
  204. static isc_result_t
  205. sync_channellist(isc_logconfig_t *lcfg);
  206. static isc_result_t
  207. greatest_version(isc_logchannel_t *channel, int *greatest);
  208. static isc_result_t
  209. roll_log(isc_logchannel_t *channel);
  210. static void
  211. isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
  212. isc_logmodule_t *module, int level, isc_boolean_t write_once,
  213. isc_msgcat_t *msgcat, int msgset, int msg,
  214. const char *format, va_list args)
  215. ISC_FORMAT_PRINTF(9, 0);
  216. /*@{*/
  217. /*!
  218. * Convenience macros.
  219. */
  220. #define FACILITY(channel) (channel->destination.facility)
  221. #define FILE_NAME(channel) (channel->destination.file.name)
  222. #define FILE_STREAM(channel) (channel->destination.file.stream)
  223. #define FILE_VERSIONS(channel) (channel->destination.file.versions)
  224. #define FILE_MAXSIZE(channel) (channel->destination.file.maximum_size)
  225. #define FILE_MAXREACHED(channel) (channel->destination.file.maximum_reached)
  226. /*@}*/
  227. /****
  228. **** Public interfaces.
  229. ****/
  230. /*
  231. * Establish a new logging context, with default channels.
  232. */
  233. isc_result_t
  234. isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) {
  235. isc_log_t *lctx;
  236. isc_logconfig_t *lcfg = NULL;
  237. isc_result_t result;
  238. REQUIRE(mctx != NULL);
  239. REQUIRE(lctxp != NULL && *lctxp == NULL);
  240. REQUIRE(lcfgp == NULL || *lcfgp == NULL);
  241. lctx = isc_mem_get(mctx, sizeof(*lctx));
  242. if (lctx != NULL) {
  243. lctx->mctx = mctx;
  244. lctx->categories = NULL;
  245. lctx->category_count = 0;
  246. lctx->modules = NULL;
  247. lctx->module_count = 0;
  248. lctx->debug_level = 0;
  249. ISC_LIST_INIT(lctx->messages);
  250. result = isc_mutex_init(&lctx->lock);
  251. if (result != ISC_R_SUCCESS) {
  252. isc_mem_put(mctx, lctx, sizeof(*lctx));
  253. return (result);
  254. }
  255. /*
  256. * Normally setting the magic number is the last step done
  257. * in a creation function, but a valid log context is needed
  258. * by isc_log_registercategories and isc_logconfig_create.
  259. * If either fails, the lctx is destroyed and not returned
  260. * to the caller.
  261. */
  262. lctx->magic = LCTX_MAGIC;
  263. isc_log_registercategories(lctx, isc_categories);
  264. isc_log_registermodules(lctx, isc_modules);
  265. result = isc_logconfig_create(lctx, &lcfg);
  266. } else
  267. result = ISC_R_NOMEMORY;
  268. if (result == ISC_R_SUCCESS)
  269. result = sync_channellist(lcfg);
  270. if (result == ISC_R_SUCCESS) {
  271. lctx->logconfig = lcfg;
  272. *lctxp = lctx;
  273. if (lcfgp != NULL)
  274. *lcfgp = lcfg;
  275. } else {
  276. if (lcfg != NULL)
  277. isc_logconfig_destroy(&lcfg);
  278. if (lctx != NULL)
  279. isc_log_destroy(&lctx);
  280. }
  281. return (result);
  282. }
  283. isc_result_t
  284. isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp) {
  285. isc_logconfig_t *lcfg;
  286. isc_logdestination_t destination;
  287. isc_result_t result = ISC_R_SUCCESS;
  288. int level = ISC_LOG_INFO;
  289. REQUIRE(lcfgp != NULL && *lcfgp == NULL);
  290. REQUIRE(VALID_CONTEXT(lctx));
  291. lcfg = isc_mem_get(lctx->mctx, sizeof(*lcfg));
  292. if (lcfg != NULL) {
  293. lcfg->lctx = lctx;
  294. lcfg->channellists = NULL;
  295. lcfg->channellist_count = 0;
  296. lcfg->duplicate_interval = 0;
  297. lcfg->highest_level = level;
  298. lcfg->tag = NULL;
  299. lcfg->dynamic = ISC_FALSE;
  300. ISC_LIST_INIT(lcfg->channels);
  301. /*
  302. * Normally the magic number is the last thing set in the
  303. * structure, but isc_log_createchannel() needs a valid
  304. * config. If the channel creation fails, the lcfg is not
  305. * returned to the caller.
  306. */
  307. lcfg->magic = LCFG_MAGIC;
  308. } else
  309. result = ISC_R_NOMEMORY;
  310. /*
  311. * Create the default channels:
  312. * default_syslog, default_stderr, default_debug and null.
  313. */
  314. if (result == ISC_R_SUCCESS) {
  315. destination.facility = LOG_DAEMON;
  316. result = isc_log_createchannel(lcfg, "default_syslog",
  317. ISC_LOG_TOSYSLOG, level,
  318. &destination, 0);
  319. }
  320. if (result == ISC_R_SUCCESS) {
  321. destination.file.stream = stderr;
  322. destination.file.name = NULL;
  323. destination.file.versions = ISC_LOG_ROLLNEVER;
  324. destination.file.maximum_size = 0;
  325. result = isc_log_createchannel(lcfg, "default_stderr",
  326. ISC_LOG_TOFILEDESC,
  327. level,
  328. &destination,
  329. ISC_LOG_PRINTTIME);
  330. }
  331. if (result == ISC_R_SUCCESS) {
  332. /*
  333. * Set the default category's channel to default_stderr,
  334. * which is at the head of the channels list because it was
  335. * just created.
  336. */
  337. default_channel.channel = ISC_LIST_HEAD(lcfg->channels);
  338. destination.file.stream = stderr;
  339. destination.file.name = NULL;
  340. destination.file.versions = ISC_LOG_ROLLNEVER;
  341. destination.file.maximum_size = 0;
  342. result = isc_log_createchannel(lcfg, "default_debug",
  343. ISC_LOG_TOFILEDESC,
  344. ISC_LOG_DYNAMIC,
  345. &destination,
  346. ISC_LOG_PRINTTIME);
  347. }
  348. if (result == ISC_R_SUCCESS)
  349. result = isc_log_createchannel(lcfg, "null",
  350. ISC_LOG_TONULL,
  351. ISC_LOG_DYNAMIC,
  352. NULL, 0);
  353. if (result == ISC_R_SUCCESS)
  354. *lcfgp = lcfg;
  355. else
  356. if (lcfg != NULL)
  357. isc_logconfig_destroy(&lcfg);
  358. return (result);
  359. }
  360. isc_logconfig_t *
  361. isc_logconfig_get(isc_log_t *lctx) {
  362. REQUIRE(VALID_CONTEXT(lctx));
  363. ENSURE(lctx->logconfig != NULL);
  364. return (lctx->logconfig);
  365. }
  366. isc_result_t
  367. isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg) {
  368. isc_logconfig_t *old_cfg;
  369. isc_result_t result;
  370. REQUIRE(VALID_CONTEXT(lctx));
  371. REQUIRE(VALID_CONFIG(lcfg));
  372. REQUIRE(lcfg->lctx == lctx);
  373. /*
  374. * Ensure that lcfg->channellist_count == lctx->category_count.
  375. * They won't be equal if isc_log_usechannel has not been called
  376. * since any call to isc_log_registercategories.
  377. */
  378. result = sync_channellist(lcfg);
  379. if (result != ISC_R_SUCCESS)
  380. return (result);
  381. LOCK(&lctx->lock);
  382. old_cfg = lctx->logconfig;
  383. lctx->logconfig = lcfg;
  384. UNLOCK(&lctx->lock);
  385. isc_logconfig_destroy(&old_cfg);
  386. return (ISC_R_SUCCESS);
  387. }
  388. void
  389. isc_log_destroy(isc_log_t **lctxp) {
  390. isc_log_t *lctx;
  391. isc_logconfig_t *lcfg;
  392. isc_mem_t *mctx;
  393. isc_logmessage_t *message;
  394. REQUIRE(lctxp != NULL && VALID_CONTEXT(*lctxp));
  395. lctx = *lctxp;
  396. mctx = lctx->mctx;
  397. if (lctx->logconfig != NULL) {
  398. lcfg = lctx->logconfig;
  399. lctx->logconfig = NULL;
  400. isc_logconfig_destroy(&lcfg);
  401. }
  402. DESTROYLOCK(&lctx->lock);
  403. while ((message = ISC_LIST_HEAD(lctx->messages)) != NULL) {
  404. ISC_LIST_UNLINK(lctx->messages, message, link);
  405. isc_mem_put(mctx, message,
  406. sizeof(*message) + strlen(message->text) + 1);
  407. }
  408. lctx->buffer[0] = '\0';
  409. lctx->debug_level = 0;
  410. lctx->categories = NULL;
  411. lctx->category_count = 0;
  412. lctx->modules = NULL;
  413. lctx->module_count = 0;
  414. lctx->mctx = NULL;
  415. lctx->magic = 0;
  416. isc_mem_put(mctx, lctx, sizeof(*lctx));
  417. *lctxp = NULL;
  418. }
  419. void
  420. isc_logconfig_destroy(isc_logconfig_t **lcfgp) {
  421. isc_logconfig_t *lcfg;
  422. isc_mem_t *mctx;
  423. isc_logchannel_t *channel;
  424. isc_logchannellist_t *item;
  425. char *filename;
  426. unsigned int i;
  427. REQUIRE(lcfgp != NULL && VALID_CONFIG(*lcfgp));
  428. lcfg = *lcfgp;
  429. /*
  430. * This function cannot be called with a logconfig that is in
  431. * use by a log context.
  432. */
  433. REQUIRE(lcfg->lctx != NULL && lcfg->lctx->logconfig != lcfg);
  434. mctx = lcfg->lctx->mctx;
  435. while ((channel = ISC_LIST_HEAD(lcfg->channels)) != NULL) {
  436. ISC_LIST_UNLINK(lcfg->channels, channel, link);
  437. if (channel->type == ISC_LOG_TOFILE) {
  438. /*
  439. * The filename for the channel may have ultimately
  440. * started its life in user-land as a const string,
  441. * but in isc_log_createchannel it gets copied
  442. * into writable memory and is not longer truly const.
  443. */
  444. DE_CONST(FILE_NAME(channel), filename);
  445. isc_mem_free(mctx, filename);
  446. if (FILE_STREAM(channel) != NULL)
  447. (void)fclose(FILE_STREAM(channel));
  448. }
  449. isc_mem_free(mctx, channel->name);
  450. isc_mem_put(mctx, channel, sizeof(*channel));
  451. }
  452. for (i = 0; i < lcfg->channellist_count; i++)
  453. while ((item = ISC_LIST_HEAD(lcfg->channellists[i])) != NULL) {
  454. ISC_LIST_UNLINK(lcfg->channellists[i], item, link);
  455. isc_mem_put(mctx, item, sizeof(*item));
  456. }
  457. if (lcfg->channellist_count > 0)
  458. isc_mem_put(mctx, lcfg->channellists,
  459. lcfg->channellist_count *
  460. sizeof(ISC_LIST(isc_logchannellist_t)));
  461. lcfg->dynamic = ISC_FALSE;
  462. if (lcfg->tag != NULL)
  463. isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
  464. lcfg->tag = NULL;
  465. lcfg->highest_level = 0;
  466. lcfg->duplicate_interval = 0;
  467. lcfg->magic = 0;
  468. isc_mem_put(mctx, lcfg, sizeof(*lcfg));
  469. *lcfgp = NULL;
  470. }
  471. void
  472. isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]) {
  473. isc_logcategory_t *catp;
  474. REQUIRE(VALID_CONTEXT(lctx));
  475. REQUIRE(categories != NULL && categories[0].name != NULL);
  476. /*
  477. * XXXDCL This somewhat sleazy situation of using the last pointer
  478. * in one category array to point to the next array exists because
  479. * this registration function returns void and I didn't want to have
  480. * change everything that used it by making it return an isc_result_t.
  481. * It would need to do that if it had to allocate memory to store
  482. * pointers to each array passed in.
  483. */
  484. if (lctx->categories == NULL)
  485. lctx->categories = categories;
  486. else {
  487. /*
  488. * Adjust the last (NULL) pointer of the already registered
  489. * categories to point to the incoming array.
  490. */
  491. for (catp = lctx->categories; catp->name != NULL; )
  492. if (catp->id == UINT_MAX)
  493. /*
  494. * The name pointer points to the next array.
  495. * Ick.
  496. */
  497. DE_CONST(catp->name, catp);
  498. else
  499. catp++;
  500. catp->name = (void *)categories;
  501. catp->id = UINT_MAX;
  502. }
  503. /*
  504. * Update the id number of the category with its new global id.
  505. */
  506. for (catp = categories; catp->name != NULL; catp++)
  507. catp->id = lctx->category_count++;
  508. }
  509. isc_logcategory_t *
  510. isc_log_categorybyname(isc_log_t *lctx, const char *name) {
  511. isc_logcategory_t *catp;
  512. REQUIRE(VALID_CONTEXT(lctx));
  513. REQUIRE(name != NULL);
  514. for (catp = lctx->categories; catp->name != NULL; )
  515. if (catp->id == UINT_MAX)
  516. /*
  517. * catp is neither modified nor returned to the
  518. * caller, so removing its const qualifier is ok.
  519. */
  520. DE_CONST(catp->name, catp);
  521. else {
  522. if (strcmp(catp->name, name) == 0)
  523. return (catp);
  524. catp++;
  525. }
  526. return (NULL);
  527. }
  528. void
  529. isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]) {
  530. isc_logmodule_t *modp;
  531. REQUIRE(VALID_CONTEXT(lctx));
  532. REQUIRE(modules != NULL && modules[0].name != NULL);
  533. /*
  534. * XXXDCL This somewhat sleazy situation of using the last pointer
  535. * in one category array to point to the next array exists because
  536. * this registration function returns void and I didn't want to have
  537. * change everything that used it by making it return an isc_result_t.
  538. * It would need to do that if it had to allocate memory to store
  539. * pointers to each array passed in.
  540. */
  541. if (lctx->modules == NULL)
  542. lctx->modules = modules;
  543. else {
  544. /*
  545. * Adjust the last (NULL) pointer of the already registered
  546. * modules to point to the incoming array.
  547. */
  548. for (modp = lctx->modules; modp->name != NULL; )
  549. if (modp->id == UINT_MAX)
  550. /*
  551. * The name pointer points to the next array.
  552. * Ick.
  553. */
  554. DE_CONST(modp->name, modp);
  555. else
  556. modp++;
  557. modp->name = (void *)modules;
  558. modp->id = UINT_MAX;
  559. }
  560. /*
  561. * Update the id number of the module with its new global id.
  562. */
  563. for (modp = modules; modp->name != NULL; modp++)
  564. modp->id = lctx->module_count++;
  565. }
  566. isc_logmodule_t *
  567. isc_log_modulebyname(isc_log_t *lctx, const char *name) {
  568. isc_logmodule_t *modp;
  569. REQUIRE(VALID_CONTEXT(lctx));
  570. REQUIRE(name != NULL);
  571. for (modp = lctx->modules; modp->name != NULL; )
  572. if (modp->id == UINT_MAX)
  573. /*
  574. * modp is neither modified nor returned to the
  575. * caller, so removing its const qualifier is ok.
  576. */
  577. DE_CONST(modp->name, modp);
  578. else {
  579. if (strcmp(modp->name, name) == 0)
  580. return (modp);
  581. modp++;
  582. }
  583. return (NULL);
  584. }
  585. isc_result_t
  586. isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
  587. unsigned int type, int level,
  588. const isc_logdestination_t *destination,
  589. unsigned int flags)
  590. {
  591. isc_logchannel_t *channel;
  592. isc_mem_t *mctx;
  593. REQUIRE(VALID_CONFIG(lcfg));
  594. REQUIRE(name != NULL);
  595. REQUIRE(type == ISC_LOG_TOSYSLOG || type == ISC_LOG_TOFILE ||
  596. type == ISC_LOG_TOFILEDESC || type == ISC_LOG_TONULL);
  597. REQUIRE(destination != NULL || type == ISC_LOG_TONULL);
  598. REQUIRE(level >= ISC_LOG_CRITICAL);
  599. REQUIRE((flags &
  600. (unsigned int)~(ISC_LOG_PRINTALL | ISC_LOG_DEBUGONLY)) == 0);
  601. /* XXXDCL find duplicate names? */
  602. mctx = lcfg->lctx->mctx;
  603. channel = isc_mem_get(mctx, sizeof(*channel));
  604. if (channel == NULL)
  605. return (ISC_R_NOMEMORY);
  606. channel->name = isc_mem_strdup(mctx, name);
  607. if (channel->name == NULL) {
  608. isc_mem_put(mctx, channel, sizeof(*channel));
  609. return (ISC_R_NOMEMORY);
  610. }
  611. channel->type = type;
  612. channel->level = level;
  613. channel->flags = flags;
  614. ISC_LINK_INIT(channel, link);
  615. switch (type) {
  616. case ISC_LOG_TOSYSLOG:
  617. FACILITY(channel) = destination->facility;
  618. break;
  619. case ISC_LOG_TOFILE:
  620. /*
  621. * The file name is copied because greatest_version wants
  622. * to scribble on it, so it needs to be definitely in
  623. * writable memory.
  624. */
  625. FILE_NAME(channel) =
  626. isc_mem_strdup(mctx, destination->file.name);
  627. FILE_STREAM(channel) = NULL;
  628. FILE_VERSIONS(channel) = destination->file.versions;
  629. FILE_MAXSIZE(channel) = destination->file.maximum_size;
  630. FILE_MAXREACHED(channel) = ISC_FALSE;
  631. break;
  632. case ISC_LOG_TOFILEDESC:
  633. FILE_NAME(channel) = NULL;
  634. FILE_STREAM(channel) = destination->file.stream;
  635. FILE_MAXSIZE(channel) = 0;
  636. FILE_VERSIONS(channel) = ISC_LOG_ROLLNEVER;
  637. break;
  638. case ISC_LOG_TONULL:
  639. /* Nothing. */
  640. break;
  641. default:
  642. isc_mem_put(mctx, channel->name, strlen(channel->name) + 1);
  643. isc_mem_put(mctx, channel, sizeof(*channel));
  644. return (ISC_R_UNEXPECTED);
  645. }
  646. ISC_LIST_PREPEND(lcfg->channels, channel, link);
  647. /*
  648. * If default_stderr was redefined, make the default category
  649. * point to the new default_stderr.
  650. */
  651. if (strcmp(name, "default_stderr") == 0)
  652. default_channel.channel = channel;
  653. return (ISC_R_SUCCESS);
  654. }
  655. isc_result_t
  656. isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
  657. const isc_logcategory_t *category,
  658. const isc_logmodule_t *module)
  659. {
  660. isc_log_t *lctx;
  661. isc_logchannel_t *channel;
  662. isc_result_t result = ISC_R_SUCCESS;
  663. unsigned int i;
  664. REQUIRE(VALID_CONFIG(lcfg));
  665. REQUIRE(name != NULL);
  666. lctx = lcfg->lctx;
  667. REQUIRE(category == NULL || category->id < lctx->category_count);
  668. REQUIRE(module == NULL || module->id < lctx->module_count);
  669. for (channel = ISC_LIST_HEAD(lcfg->channels); channel != NULL;
  670. channel = ISC_LIST_NEXT(channel, link))
  671. if (strcmp(name, channel->name) == 0)
  672. break;
  673. if (channel == NULL)
  674. return (ISC_R_NOTFOUND);
  675. if (category != NULL)
  676. result = assignchannel(lcfg, category->id, module, channel);
  677. else
  678. /*
  679. * Assign to all categories. Note that this includes
  680. * the default channel.
  681. */
  682. for (i = 0; i < lctx->category_count; i++) {
  683. result = assignchannel(lcfg, i, module, channel);
  684. if (result != ISC_R_SUCCESS)
  685. break;
  686. }
  687. return (result);
  688. }
  689. void
  690. isc_log_write(isc_log_t *lctx, isc_logcategory_t *category,
  691. isc_logmodule_t *module, int level, const char *format, ...)
  692. {
  693. va_list args;
  694. /*
  695. * Contract checking is done in isc_log_doit().
  696. */
  697. va_start(args, format);
  698. isc_log_doit(lctx, category, module, level, ISC_FALSE,
  699. NULL, 0, 0, format, args);
  700. va_end(args);
  701. }
  702. void
  703. isc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category,
  704. isc_logmodule_t *module, int level,
  705. const char *format, va_list args)
  706. {
  707. /*
  708. * Contract checking is done in isc_log_doit().
  709. */
  710. isc_log_doit(lctx, category, module, level, ISC_FALSE,
  711. NULL, 0, 0, format, args);
  712. }
  713. void
  714. isc_log_write1(isc_log_t *lctx, isc_logcategory_t *category,
  715. isc_logmodule_t *module, int level, const char *format, ...)
  716. {
  717. va_list args;
  718. /*
  719. * Contract checking is done in isc_log_doit().
  720. */
  721. va_start(args, format);
  722. isc_log_doit(lctx, category, module, level, ISC_TRUE,
  723. NULL, 0, 0, format, args);
  724. va_end(args);
  725. }
  726. void
  727. isc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category,
  728. isc_logmodule_t *module, int level,
  729. const char *format, va_list args)
  730. {
  731. /*
  732. * Contract checking is done in isc_log_doit().
  733. */
  734. isc_log_doit(lctx, category, module, level, ISC_TRUE,
  735. NULL, 0, 0, format, args);
  736. }
  737. void
  738. isc_log_iwrite(isc_log_t *lctx, isc_logcategory_t *category,
  739. isc_logmodule_t *module, int level,
  740. isc_msgcat_t *msgcat, int msgset, int msg,
  741. const char *format, ...)
  742. {
  743. va_list args;
  744. /*
  745. * Contract checking is done in isc_log_doit().
  746. */
  747. va_start(args, format);
  748. isc_log_doit(lctx, category, module, level, ISC_FALSE,
  749. msgcat, msgset, msg, format, args);
  750. va_end(args);
  751. }
  752. void
  753. isc_log_ivwrite(isc_log_t *lctx, isc_logcategory_t *category,
  754. isc_logmodule_t *module, int level,
  755. isc_msgcat_t *msgcat, int msgset, int msg,
  756. const char *format, va_list args)
  757. {
  758. /*
  759. * Contract checking is done in isc_log_doit().
  760. */
  761. isc_log_doit(lctx, category, module, level, ISC_FALSE,
  762. msgcat, msgset, msg, format, args);
  763. }
  764. void
  765. isc_log_iwrite1(isc_log_t *lctx, isc_logcategory_t *category,
  766. isc_logmodule_t *module, int level,
  767. isc_msgcat_t *msgcat, int msgset, int msg,
  768. const char *format, ...)
  769. {
  770. va_list args;
  771. /*
  772. * Contract checking is done in isc_log_doit().
  773. */
  774. va_start(args, format);
  775. isc_log_doit(lctx, category, module, level, ISC_TRUE,
  776. msgcat, msgset, msg, format, args);
  777. va_end(args);
  778. }
  779. void
  780. isc_log_ivwrite1(isc_log_t *lctx, isc_logcategory_t *category,
  781. isc_logmodule_t *module, int level,
  782. isc_msgcat_t *msgcat, int msgset, int msg,
  783. const char *format, va_list args)
  784. {
  785. /*
  786. * Contract checking is done in isc_log_doit().
  787. */
  788. isc_log_doit(lctx, category, module, level, ISC_TRUE,
  789. msgcat, msgset, msg, format, args);
  790. }
  791. void
  792. isc_log_setcontext(isc_log_t *lctx) {
  793. isc_lctx = lctx;
  794. }
  795. void
  796. isc_log_setdebuglevel(isc_log_t *lctx, unsigned int level) {
  797. isc_logchannel_t *channel;
  798. REQUIRE(VALID_CONTEXT(lctx));
  799. LOCK(&lctx->lock);
  800. lctx->debug_level = level;
  801. /*
  802. * Close ISC_LOG_DEBUGONLY channels if level is zero.
  803. */
  804. if (lctx->debug_level == 0)
  805. for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
  806. channel != NULL;
  807. channel = ISC_LIST_NEXT(channel, link))
  808. if (channel->type == ISC_LOG_TOFILE &&
  809. (channel->flags & ISC_LOG_DEBUGONLY) != 0 &&
  810. FILE_STREAM(channel) != NULL) {
  811. (void)fclose(FILE_STREAM(channel));
  812. FILE_STREAM(channel) = NULL;
  813. }
  814. UNLOCK(&lctx->lock);
  815. }
  816. unsigned int
  817. isc_log_getdebuglevel(isc_log_t *lctx) {
  818. REQUIRE(VALID_CONTEXT(lctx));
  819. return (lctx->debug_level);
  820. }
  821. void
  822. isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval) {
  823. REQUIRE(VALID_CONFIG(lcfg));
  824. lcfg->duplicate_interval = interval;
  825. }
  826. unsigned int
  827. isc_log_getduplicateinterval(isc_logconfig_t *lcfg) {
  828. REQUIRE(VALID_CONTEXT(lcfg));
  829. return (lcfg->duplicate_interval);
  830. }
  831. isc_result_t
  832. isc_log_settag(isc_logconfig_t *lcfg, const char *tag) {
  833. REQUIRE(VALID_CONFIG(lcfg));
  834. if (tag != NULL && *tag != '\0') {
  835. if (lcfg->tag != NULL)
  836. isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
  837. lcfg->tag = isc_mem_strdup(lcfg->lctx->mctx, tag);
  838. if (lcfg->tag == NULL)
  839. return (ISC_R_NOMEMORY);
  840. } else {
  841. if (lcfg->tag != NULL)
  842. isc_mem_free(lcfg->lctx->mctx, lcfg->tag);
  843. lcfg->tag = NULL;
  844. }
  845. return (ISC_R_SUCCESS);
  846. }
  847. char *
  848. isc_log_gettag(isc_logconfig_t *lcfg) {
  849. REQUIRE(VALID_CONFIG(lcfg));
  850. return (lcfg->tag);
  851. }
  852. /* XXXDCL NT -- This interface will assuredly be changing. */
  853. void
  854. isc_log_opensyslog(const char *tag, int options, int facility) {
  855. (void)openlog(tag, options, facility);
  856. }
  857. void
  858. isc_log_closefilelogs(isc_log_t *lctx) {
  859. isc_logchannel_t *channel;
  860. REQUIRE(VALID_CONTEXT(lctx));
  861. LOCK(&lctx->lock);
  862. for (channel = ISC_LIST_HEAD(lctx->logconfig->channels);
  863. channel != NULL;
  864. channel = ISC_LIST_NEXT(channel, link))
  865. if (channel->type == ISC_LOG_TOFILE &&
  866. FILE_STREAM(channel) != NULL) {
  867. (void)fclose(FILE_STREAM(channel));
  868. FILE_STREAM(channel) = NULL;
  869. }
  870. UNLOCK(&lctx->lock);
  871. }
  872. /****
  873. **** Internal functions
  874. ****/
  875. static isc_result_t
  876. assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
  877. const isc_logmodule_t *module, isc_logchannel_t *channel)
  878. {
  879. isc_logchannellist_t *new_item;
  880. isc_log_t *lctx;
  881. isc_result_t result;
  882. REQUIRE(VALID_CONFIG(lcfg));
  883. lctx = lcfg->lctx;
  884. REQUIRE(category_id < lctx->category_count);
  885. REQUIRE(module == NULL || module->id < lctx->module_count);
  886. REQUIRE(channel != NULL);
  887. /*
  888. * Ensure lcfg->channellist_count == lctx->category_count.
  889. */
  890. result = sync_channellist(lcfg);
  891. if (result != ISC_R_SUCCESS)
  892. return (result);
  893. new_item = isc_mem_get(lctx->mctx, sizeof(*new_item));
  894. if (new_item == NULL)
  895. return (ISC_R_NOMEMORY);
  896. new_item->channel = channel;
  897. new_item->module = module;
  898. ISC_LIST_INITANDPREPEND(lcfg->channellists[category_id],
  899. new_item, link);
  900. /*
  901. * Remember the highest logging level set by any channel in the
  902. * logging config, so isc_log_doit() can quickly return if the
  903. * message is too high to be logged by any channel.
  904. */
  905. if (channel->type != ISC_LOG_TONULL) {
  906. if (lcfg->highest_level < channel->level)
  907. lcfg->highest_level = channel->level;
  908. if (channel->level == ISC_LOG_DYNAMIC)
  909. lcfg->dynamic = ISC_TRUE;
  910. }
  911. return (ISC_R_SUCCESS);
  912. }
  913. /*
  914. * This would ideally be part of isc_log_registercategories(), except then
  915. * that function would have to return isc_result_t instead of void.
  916. */
  917. static isc_result_t
  918. sync_channellist(isc_logconfig_t *lcfg) {
  919. unsigned int bytes;
  920. isc_log_t *lctx;
  921. void *lists;
  922. REQUIRE(VALID_CONFIG(lcfg));
  923. lctx = lcfg->lctx;
  924. REQUIRE(lctx->category_count != 0);
  925. if (lctx->category_count == lcfg->channellist_count)
  926. return (ISC_R_SUCCESS);
  927. bytes = lctx->category_count * sizeof(ISC_LIST(isc_logchannellist_t));
  928. lists = isc_mem_get(lctx->mctx, bytes);
  929. if (lists == NULL)
  930. return (ISC_R_NOMEMORY);
  931. memset(lists, 0, bytes);
  932. if (lcfg->channellist_count != 0) {
  933. bytes = lcfg->channellist_count *
  934. sizeof(ISC_LIST(isc_logchannellist_t));
  935. memcpy(lists, lcfg->channellists, bytes);
  936. isc_mem_put(lctx->mctx, lcfg->channellists, bytes);
  937. }
  938. lcfg->channellists = lists;
  939. lcfg->channellist_count = lctx->category_count;
  940. return (ISC_R_SUCCESS);
  941. }
  942. static isc_result_t
  943. greatest_version(isc_logchannel_t *channel, int *greatestp) {
  944. /* XXXDCL HIGHLY NT */
  945. char *basename, *digit_end;
  946. const char *dirname;
  947. int version, greatest = -1;
  948. unsigned int basenamelen;
  949. isc_dir_t dir;
  950. isc_result_t result;
  951. char sep = '/';
  952. #ifdef _WIN32
  953. char *basename2;
  954. #endif
  955. REQUIRE(channel->type == ISC_LOG_TOFILE);
  956. /*
  957. * It is safe to DE_CONST the file.name because it was copied
  958. * with isc_mem_strdup in isc_log_createchannel.
  959. */
  960. basename = strrchr(FILE_NAME(channel), sep);
  961. #ifdef _WIN32
  962. basename2 = strrchr(FILE_NAME(channel), '\\');
  963. if ((basename != NULL && basename2 != NULL && basename2 > basename) ||
  964. (basename == NULL && basename2 != NULL)) {
  965. basename = basename2;
  966. sep = '\\';
  967. }
  968. #endif
  969. if (basename != NULL) {
  970. *basename++ = '\0';
  971. dirname = FILE_NAME(channel);
  972. } else {
  973. DE_CONST(FILE_NAME(channel), basename);
  974. dirname = ".";
  975. }
  976. basenamelen = strlen(basename);
  977. isc_dir_init(&dir);
  978. result = isc_dir_open(&dir, dirname);
  979. /*
  980. * Replace the file separator if it was taken out.
  981. */
  982. if (basename != FILE_NAME(channel))
  983. *(basename - 1) = sep;
  984. /*
  985. * Return if the directory open failed.
  986. */
  987. if (result != ISC_R_SUCCESS)
  988. return (result);
  989. while (isc_dir_read(&dir) == ISC_R_SUCCESS) {
  990. if (dir.entry.length > basenamelen &&
  991. strncmp(dir.entry.name, basename, basenamelen) == 0 &&
  992. dir.entry.name[basenamelen] == '.') {
  993. version = strtol(&dir.entry.name[basenamelen + 1],
  994. &digit_end, 10);
  995. if (*digit_end == '\0' && version > greatest)
  996. greatest = version;
  997. }
  998. }
  999. isc_dir_close(&dir);
  1000. *greatestp = ++greatest;
  1001. return (ISC_R_SUCCESS);
  1002. }
  1003. static isc_result_t
  1004. roll_log(isc_logchannel_t *channel) {
  1005. int i, n, greatest;
  1006. char current[PATH_MAX + 1];
  1007. char new[PATH_MAX + 1];
  1008. const char *path;
  1009. isc_result_t result;
  1010. /*
  1011. * Do nothing (not even excess version trimming) if ISC_LOG_ROLLNEVER
  1012. * is specified. Apparently complete external control over the log
  1013. * files is desired.
  1014. */
  1015. if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER)
  1016. return (ISC_R_SUCCESS);
  1017. path = FILE_NAME(channel);
  1018. /*
  1019. * Set greatest_version to the greatest existing version
  1020. * (not the maximum requested version). This is 1 based even
  1021. * though the file names are 0 based, so an oldest log of log.1
  1022. * is a greatest_version of 2.
  1023. */
  1024. result = greatest_version(channel, &greatest);
  1025. if (result != ISC_R_SUCCESS)
  1026. return (result);
  1027. /*
  1028. * Now greatest should be set to the highest version number desired.
  1029. * Since the highest number is one less than FILE_VERSIONS(channel)
  1030. * when not doing infinite log rolling, greatest will need to be
  1031. * decremented when it is equal to -- or greater than --
  1032. * FILE_VERSIONS(channel). When greatest is less than
  1033. * FILE_VERSIONS(channel), it is already suitable for use as
  1034. * the maximum version number.
  1035. */
  1036. if (FILE_VERSIONS(channel) == ISC_LOG_ROLLINFINITE ||
  1037. FILE_VERSIONS(channel) > greatest)
  1038. ; /* Do nothing. */
  1039. else
  1040. /*
  1041. * When greatest is >= FILE_VERSIONS(channel), it needs to
  1042. * be reduced until it is FILE_VERSIONS(channel) - 1.
  1043. * Remove any excess logs on the way to that value.
  1044. */
  1045. while (--greatest >= FILE_VERSIONS(channel)) {
  1046. n = snprintf(current, sizeof(current), "%s.%d",
  1047. path, greatest);
  1048. if (n >= (int)sizeof(current) || n < 0)
  1049. result = ISC_R_NOSPACE;
  1050. else
  1051. result = isc_file_remove(current);
  1052. if (result != ISC_R_SUCCESS &&
  1053. result != ISC_R_FILENOTFOUND)
  1054. syslog(LOG_ERR,
  1055. "unable to remove log file '%s.%d': %s",
  1056. path, greatest,
  1057. isc_result_totext(result));
  1058. }
  1059. for (i = greatest; i > 0; i--) {
  1060. result = ISC_R_SUCCESS;
  1061. n = snprintf(current, sizeof(current), "%s.%d", path, i - 1);
  1062. if (n >= (int)sizeof(current) || n < 0)
  1063. result = ISC_R_NOSPACE;
  1064. if (result == ISC_R_SUCCESS) {
  1065. n = snprintf(new, sizeof(new), "%s.%d", path, i);
  1066. if (n >= (int)sizeof(new) || n < 0)
  1067. result = ISC_R_NOSPACE;
  1068. }
  1069. if (result == ISC_R_SUCCESS)
  1070. result = isc_file_rename(current, new);
  1071. if (result != ISC_R_SUCCESS &&
  1072. result != ISC_R_FILENOTFOUND)
  1073. syslog(LOG_ERR,
  1074. "unable to rename log file '%s.%d' to "
  1075. "'%s.%d': %s", path, i - 1, path, i,
  1076. isc_result_totext(result));
  1077. }
  1078. if (FILE_VERSIONS(channel) != 0) {
  1079. n = snprintf(new, sizeof(new), "%s.0", path);
  1080. if (n >= (int)sizeof(new) || n < 0)
  1081. result = ISC_R_NOSPACE;
  1082. else
  1083. result = isc_file_rename(path, new);
  1084. if (result != ISC_R_SUCCESS &&
  1085. result != ISC_R_FILENOTFOUND)
  1086. syslog(LOG_ERR,
  1087. "unable to rename log file '%s' to '%s.0': %s",
  1088. path, path, isc_result_totext(result));
  1089. } else {
  1090. result = isc_file_remove(path);
  1091. if (result != ISC_R_SUCCESS &&
  1092. result != ISC_R_FILENOTFOUND)
  1093. syslog(LOG_ERR, "unable to remove log file '%s': %s",
  1094. path, isc_result_totext(result));
  1095. }
  1096. return (ISC_R_SUCCESS);
  1097. }
  1098. static isc_result_t
  1099. isc_log_open(isc_logchannel_t *channel) {
  1100. struct stat statbuf;
  1101. isc_boolean_t regular_file;
  1102. isc_boolean_t roll = ISC_FALSE;
  1103. isc_result_t result = ISC_R_SUCCESS;
  1104. const char *path;
  1105. REQUIRE(channel->type == ISC_LOG_TOFILE);
  1106. REQUIRE(FILE_STREAM(channel) == NULL);
  1107. path = FILE_NAME(channel);
  1108. REQUIRE(path != NULL && *path != '\0');
  1109. /*
  1110. * Determine type of file; only regular files will be
  1111. * version renamed, and only if the base file exists
  1112. * and either has no size limit or has reached its size limit.
  1113. */
  1114. if (stat(path, &statbuf) == 0) {
  1115. regular_file = S_ISREG(statbuf.st_mode) ? ISC_TRUE : ISC_FALSE;
  1116. /* XXXDCL if not regular_file complain? */
  1117. if ((FILE_MAXSIZE(channel) == 0 &&
  1118. FILE_VERSIONS(channel) != ISC_LOG_ROLLNEVER) ||
  1119. (FILE_MAXSIZE(channel) > 0 &&
  1120. statbuf.st_size >= FILE_MAXSIZE(channel)))
  1121. roll = regular_file;
  1122. } else if (errno == ENOENT) {
  1123. regular_file = ISC_TRUE;
  1124. POST(regular_file);
  1125. } else
  1126. result = ISC_R_INVALIDFILE;
  1127. /*
  1128. * Version control.
  1129. */
  1130. if (result == ISC_R_SUCCESS && roll) {
  1131. if (FILE_VERSIONS(channel) == ISC_LOG_ROLLNEVER)
  1132. return (ISC_R_MAXSIZE);
  1133. result = roll_log(channel);
  1134. if (result != ISC_R_SUCCESS) {
  1135. if ((channel->flags & ISC_LOG_OPENERR) == 0) {
  1136. syslog(LOG_ERR,
  1137. "isc_log_open: roll_log '%s' "
  1138. "failed: %s",
  1139. FILE_NAME(channel),
  1140. isc_result_totext(result));
  1141. channel->flags |= ISC_LOG_OPENERR;
  1142. }
  1143. return (result);
  1144. }
  1145. }
  1146. result = isc_stdio_open(path, "a", &FILE_STREAM(channel));
  1147. return (result);
  1148. }
  1149. isc_boolean_t
  1150. isc_log_wouldlog(isc_log_t *lctx, int level) {
  1151. /*
  1152. * Try to avoid locking the mutex for messages which can't
  1153. * possibly be logged to any channels -- primarily debugging
  1154. * messages that the debug level is not high enough to print.
  1155. *
  1156. * If the level is (mathematically) less than or equal to the
  1157. * highest_level, or if there is a dynamic channel and the level is
  1158. * less than or equal to the debug level, the main loop must be
  1159. * entered to see if the message should really be output.
  1160. *
  1161. * NOTE: this is UNLOCKED access to the logconfig. However,
  1162. * the worst thing that can happen is that a bad decision is made
  1163. * about returning without logging, and that's not a big concern,
  1164. * because that's a risk anyway if the logconfig is being
  1165. * dynamically changed.
  1166. */
  1167. if (lctx == NULL || lctx->logconfig == NULL)
  1168. return (ISC_FALSE);
  1169. return (ISC_TF(level <= lctx->logconfig->highest_level ||
  1170. (lctx->logconfig->dynamic &&
  1171. level <= lctx->debug_level)));
  1172. }
  1173. static void
  1174. isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
  1175. isc_logmodule_t *module, int level, isc_boolean_t write_once,
  1176. isc_msgcat_t *msgcat, int msgset, int msg,
  1177. const char *format, va_list args)
  1178. {
  1179. int syslog_level;
  1180. char time_string[64];
  1181. char level_string[24];
  1182. const char *iformat;
  1183. struct stat statbuf;
  1184. isc_boolean_t matched = ISC_FALSE;
  1185. isc_boolean_t printtime, printtag;
  1186. isc_boolean_t printcategory, printmodule, printlevel;
  1187. isc_logconfig_t *lcfg;
  1188. isc_logchannel_t *channel;
  1189. isc_logchannellist_t *category_channels;
  1190. isc_result_t result;
  1191. REQUIRE(lctx == NULL || VALID_CONTEXT(lctx));
  1192. REQUIRE(category != NULL);
  1193. REQUIRE(module != NULL);
  1194. REQUIRE(level != ISC_LOG_DYNAMIC);
  1195. REQUIRE(format != NULL);
  1196. /*
  1197. * Programs can use libraries that use this logging code without
  1198. * wanting to do any logging, thus the log context is allowed to
  1199. * be non-existent.
  1200. */
  1201. if (lctx == NULL)
  1202. return;
  1203. REQUIRE(category->id < lctx->category_count);
  1204. REQUIRE(module->id < lctx->module_count);
  1205. if (! isc_log_wouldlog(lctx, level))
  1206. return;
  1207. if (msgcat != NULL)
  1208. iformat = isc_msgcat_get(msgcat, msgset, msg, format);
  1209. else
  1210. iformat = format;
  1211. time_string[0] = '\0';
  1212. level_string[0] = '\0';
  1213. LOCK(&lctx->lock);
  1214. lctx->buffer[0] = '\0';
  1215. lcfg = lctx->logconfig;
  1216. category_channels = ISC_LIST_HEAD(lcfg->channellists[category->id]);
  1217. /*
  1218. * XXXDCL add duplicate filtering? (To not write multiple times to
  1219. * the same source via various channels).
  1220. */
  1221. do {
  1222. /*
  1223. * If the channel list end was reached and a match was made,
  1224. * everything is finished.
  1225. */
  1226. if (category_channels == NULL && matched)
  1227. break;
  1228. if (category_channels == NULL && ! matched &&
  1229. category_channels != ISC_LIST_HEAD(lcfg->channellists[0]))
  1230. /*
  1231. * No category/module pair was explicitly configured.
  1232. * Try the category named "default".
  1233. */
  1234. category_channels =
  1235. ISC_LIST_HEAD(lcfg->channellists[0]);
  1236. if (category_channels == NULL && ! matched)
  1237. /*
  1238. * No matching module was explicitly configured
  1239. * for the category named "default". Use the internal
  1240. * default channel.
  1241. */
  1242. category_channels = &default_channel;
  1243. if (category_channels->module != NULL &&
  1244. category_channels->module != module) {
  1245. category_channels = ISC_LIST_NEXT(category_channels,
  1246. link);
  1247. continue;
  1248. }
  1249. matched = ISC_TRUE;
  1250. channel = category_channels->channel;
  1251. category_channels = ISC_LIST_NEXT(category_channels, link);
  1252. if (((channel->flags & ISC_LOG_DEBUGONLY) != 0) &&
  1253. lctx->debug_level == 0)
  1254. continue;
  1255. if (channel->level == ISC_LOG_DYNAMIC) {
  1256. if (lctx->debug_level < level)
  1257. continue;
  1258. } else if (channel->level < level)
  1259. continue;
  1260. if ((channel->flags & ISC_LOG_PRINTTIME) != 0 &&
  1261. time_string[0] == '\0') {
  1262. isc_time_t isctime;
  1263. TIME_NOW(&isctime);
  1264. isc_time_formattimestamp(&isctime, time_string,
  1265. sizeof(time_string));
  1266. }
  1267. if ((channel->flags & ISC_LOG_PRINTLEVEL) != 0 &&
  1268. level_string[0] == '\0') {
  1269. if (level < ISC_LOG_CRITICAL)
  1270. snprintf(level_string, sizeof(level_string),
  1271. isc_msgcat_get(isc_msgcat,
  1272. ISC_MSGSET_LOG,
  1273. ISC_MSG_LEVEL,
  1274. "level %d: "),
  1275. level);
  1276. else if (level > ISC_LOG_DYNAMIC)
  1277. snprintf(level_string, sizeof(level_string),
  1278. "%s %d: ", log_level_strings[0],
  1279. level);
  1280. else
  1281. snprintf(level_string, sizeof(level_string),
  1282. "%s: ", log_level_strings[-level]);
  1283. }
  1284. /*
  1285. * Only format the message once.
  1286. */
  1287. if (lctx->buffer[0] == '\0') {
  1288. (void)vsnprintf(lctx->buffer, sizeof(lctx->buffer),
  1289. iformat, args);
  1290. /*
  1291. * Check for duplicates.
  1292. */
  1293. if (write_once) {
  1294. isc_logmessage_t *message, *new;
  1295. isc_time_t oldest;
  1296. isc_interval_t interval;
  1297. isc_interval_set(&interval,
  1298. lcfg->duplicate_interval, 0);
  1299. /*
  1300. * 'oldest' is the age of the oldest messages
  1301. * which fall within the duplicate_interval
  1302. * range.
  1303. */
  1304. TIME_NOW(&oldest);
  1305. if (isc_time_subtract(&oldest, &interval, &oldest)
  1306. != ISC_R_SUCCESS)
  1307. /*
  1308. * Can't effectively do the checking
  1309. * without having a valid time.
  1310. */
  1311. message = NULL;
  1312. else
  1313. message =ISC_LIST_HEAD(lctx->messages);
  1314. while (message != NULL) {
  1315. if (isc_time_compare(&message->time,
  1316. &oldest) < 0) {
  1317. /*
  1318. * This message is older
  1319. * than the duplicate_interval,
  1320. * so it should be dropped from
  1321. * the history.
  1322. *
  1323. * Setting the interval to be
  1324. * to be longer will obviously
  1325. * not cause the expired
  1326. * message to spring back into
  1327. * existence.
  1328. */
  1329. new = ISC_LIST_NEXT(message,
  1330. link);
  1331. ISC_LIST_UNLINK(lctx->messages,
  1332. message, link);
  1333. isc_mem_put(lctx->mctx,
  1334. message,
  1335. sizeof(*message) + 1 +
  1336. strlen(message->text));
  1337. message = new;
  1338. continue;
  1339. }
  1340. /*
  1341. * This message is in the duplicate
  1342. * filtering interval ...
  1343. */
  1344. if (strcmp(lctx->buffer, message->text)
  1345. == 0) {
  1346. /*
  1347. * ... and it is a duplicate.
  1348. * Unlock the mutex and
  1349. * get the hell out of Dodge.
  1350. */
  1351. UNLOCK(&lctx->lock);
  1352. return;
  1353. }
  1354. message = ISC_LIST_NEXT(message, link);
  1355. }
  1356. /*
  1357. * It wasn't in the duplicate interval,
  1358. * so add it to the message list.
  1359. */
  1360. new = isc_mem_get(lctx->mctx,
  1361. sizeof(isc_logmessage_t) +
  1362. strlen(lctx->buffer) + 1);
  1363. if (new != NULL) {
  1364. /*
  1365. * Put the text immediately after
  1366. * the struct. The strcpy is safe.
  1367. */
  1368. new->text = (char *)(new + 1);
  1369. strcpy(new->text, lctx->buffer);
  1370. TIME_NOW(&new->time);
  1371. ISC_LIST_APPEND(lctx->messages,
  1372. new, link);
  1373. }
  1374. }
  1375. }
  1376. printtime = ISC_TF((channel->flags & ISC_LOG_PRINTTIME)
  1377. != 0);
  1378. printtag = ISC_TF((channel->flags & ISC_LOG_PRINTTAG)
  1379. != 0 && lcfg->tag != NULL);
  1380. printcategory = ISC_TF((channel->flags & ISC_LOG_PRINTCATEGORY)
  1381. != 0);
  1382. printmodule = ISC_TF((channel->flags & ISC_LOG_PRINTMODULE)
  1383. != 0);
  1384. printlevel = ISC_TF((channel->flags & ISC_LOG_PRINTLEVEL)
  1385. != 0);
  1386. switch (channel->type) {
  1387. case ISC_LOG_TOFILE:
  1388. if (FILE_MAXREACHED(channel)) {
  1389. /*
  1390. * If the file can be rolled, OR
  1391. * If the file no longer exists, OR
  1392. * If the file is less than the maximum size,
  1393. * (such as if it had been renamed and
  1394. * a new one touched, or it was truncated
  1395. * in place)
  1396. * ... then close it to trigger reopening.
  1397. */
  1398. if (FILE_VERSIONS(channel) !=
  1399. ISC_LOG_ROLLNEVER ||
  1400. (stat(FILE_NAME(channel), &statbuf) != 0 &&
  1401. errno == ENOENT) ||
  1402. statbuf.st_size < FILE_MAXSIZE(channel)) {
  1403. (void)fclose(FILE_STREAM(channel));
  1404. FILE_STREAM(channel) = NULL;
  1405. FILE_MAXREACHED(channel) = ISC_FALSE;
  1406. } else
  1407. /*
  1408. * Eh, skip it.
  1409. */
  1410. break;
  1411. }
  1412. if (FILE_STREAM(channel) == NULL) {
  1413. result = isc_log_open(channel);
  1414. if (result != ISC_R_SUCCESS &&
  1415. result != ISC_R_MAXSIZE &&
  1416. (channel->flags & ISC_LOG_OPENERR) == 0) {
  1417. syslog(LOG_ERR,
  1418. "isc_log_open '%s' failed: %s",
  1419. FILE_NAME(channel),
  1420. isc_result_totext(result));
  1421. channel->flags |= ISC_LOG_OPENERR;
  1422. }
  1423. if (result != ISC_R_SUCCESS)
  1424. break;
  1425. channel->flags &= ~ISC_LOG_OPENERR;
  1426. }
  1427. /* FALLTHROUGH */
  1428. case ISC_LOG_TOFILEDESC:
  1429. fprintf(FILE_STREAM(channel), "%s%s%s%s%s%s%s%s%s%s\n",
  1430. printtime ? time_string : "",
  1431. printtime ? " " : "",
  1432. printtag ? lcfg->tag : "",
  1433. printtag ? ": " : "",
  1434. printcategory ? category->name : "",
  1435. printcategory ? ": " : "",
  1436. printmodule ? (module != NULL ? module->name
  1437. : "no_module")
  1438. : "",
  1439. printmodule ? ": " : "",
  1440. printlevel ? level_string : "",
  1441. lctx->buffer);
  1442. fflush(FILE_STREAM(channel));
  1443. /*
  1444. * If the file now exceeds its maximum size
  1445. * threshold, note it so that it will not be logged
  1446. * to any more.
  1447. */
  1448. if (FILE_MAXSIZE(channel) > 0) {
  1449. INSIST(channel->type == ISC_LOG_TOFILE);
  1450. /* XXXDCL NT fstat/fileno */
  1451. /* XXXDCL complain if fstat fails? */
  1452. if (fstat(fileno(FILE_STREAM(channel)),
  1453. &statbuf) >= 0 &&
  1454. statbuf.st_size > FILE_MAXSIZE(channel))
  1455. FILE_MAXREACHED(channel) = ISC_TRUE;
  1456. }
  1457. break;
  1458. case ISC_LOG_TOSYSLOG:
  1459. if (level > 0)
  1460. syslog_level = LOG_DEBUG;
  1461. else if (level < ISC_LOG_CRITICAL)
  1462. syslog_level = LOG_CRIT;
  1463. else
  1464. syslog_level = syslog_map[-level];
  1465. (void)syslog(FACILITY(channel) | syslog_level,
  1466. "%s%s%s%s%s%s%s%s%s%s",
  1467. printtime ? time_string : "",
  1468. printtime ? " " : "",
  1469. printtag ? lcfg->tag : "",
  1470. printtag ? ": " : "",
  1471. printcategory ? category->name : "",
  1472. printcategory ? ": " : "",
  1473. printmodule ? (module != NULL ? module->name
  1474. : "no_module")
  1475. : "",
  1476. printmodule ? ": " : "",
  1477. printlevel ? level_string : "",
  1478. lctx->buffer);
  1479. break;
  1480. case ISC_LOG_TONULL:
  1481. break;
  1482. }
  1483. } while (1);
  1484. UNLOCK(&lctx->lock);
  1485. }