📄 log.c
字号:
* Ick. */ DE_CONST(catp->name, catp); else catp++; catp->name = (void *)categories; catp->id = UINT_MAX; } /* * Update the id number of the category with its new global id. */ for (catp = categories; catp->name != NULL; catp++) catp->id = lctx->category_count++;}isc_logcategory_t *isc_log_categorybyname(isc_log_t *lctx, const char *name) { isc_logcategory_t *catp; REQUIRE(VALID_CONTEXT(lctx)); REQUIRE(name != NULL); for (catp = lctx->categories; catp->name != NULL; ) if (catp->id == UINT_MAX) /* * catp is neither modified nor returned to the * caller, so removing its const qualifier is ok. */ DE_CONST(catp->name, catp); else { if (strcmp(catp->name, name) == 0) return (catp); catp++; } return (NULL);}voidisc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]) { isc_logmodule_t *modp; REQUIRE(VALID_CONTEXT(lctx)); REQUIRE(modules != NULL && modules[0].name != NULL); /* * XXXDCL This somewhat sleazy situation of using the last pointer * in one category array to point to the next array exists because * this registration function returns void and I didn't want to have * change everything that used it by making it return an isc_result_t. * It would need to do that if it had to allocate memory to store * pointers to each array passed in. */ if (lctx->modules == NULL) lctx->modules = modules; else { /* * Adjust the last (NULL) pointer of the already registered * modules to point to the incoming array. */ for (modp = lctx->modules; modp->name != NULL; ) if (modp->id == UINT_MAX) /* * The name pointer points to the next array. * Ick. */ DE_CONST(modp->name, modp); else modp++; modp->name = (void *)modules; modp->id = UINT_MAX; } /* * Update the id number of the module with its new global id. */ for (modp = modules; modp->name != NULL; modp++) modp->id = lctx->module_count++;}isc_logmodule_t *isc_log_modulebyname(isc_log_t *lctx, const char *name) { isc_logmodule_t *modp; REQUIRE(VALID_CONTEXT(lctx)); REQUIRE(name != NULL); for (modp = lctx->modules; modp->name != NULL; ) if (modp->id == UINT_MAX) /* * modp is neither modified nor returned to the * caller, so removing its const qualifier is ok. */ DE_CONST(modp->name, modp); else { if (strcmp(modp->name, name) == 0) return (modp); modp++; } return (NULL);}isc_result_tisc_log_createchannel(isc_logconfig_t *lcfg, const char *name, unsigned int type, int level, const isc_logdestination_t *destination, unsigned int flags){ isc_logchannel_t *channel; isc_mem_t *mctx; REQUIRE(VALID_CONFIG(lcfg)); REQUIRE(name != NULL); REQUIRE(type == ISC_LOG_TOSYSLOG || type == ISC_LOG_TOFILE || type == ISC_LOG_TOFILEDESC || type == ISC_LOG_TONULL); REQUIRE(destination != NULL || type == ISC_LOG_TONULL); REQUIRE(level >= ISC_LOG_CRITICAL); REQUIRE((flags & (unsigned int)~(ISC_LOG_PRINTALL | ISC_LOG_DEBUGONLY)) == 0); /* XXXDCL find duplicate names? */ mctx = lcfg->lctx->mctx; channel = isc_mem_get(mctx, sizeof(*channel)); if (channel == NULL) return (ISC_R_NOMEMORY); channel->name = isc_mem_strdup(mctx, name); if (channel->name == NULL) { isc_mem_put(mctx, channel, sizeof(*channel)); return (ISC_R_NOMEMORY); } channel->type = type; channel->level = level; channel->flags = flags; ISC_LINK_INIT(channel, link); switch (type) { case ISC_LOG_TOSYSLOG: FACILITY(channel) = destination->facility; break; case ISC_LOG_TOFILE: /* * The file name is copied because greatest_version wants * to scribble on it, so it needs to be definitely in * writable memory. */ FILE_NAME(channel) = isc_mem_strdup(mctx, destination->file.name); FILE_STREAM(channel) = NULL; FILE_VERSIONS(channel) = destination->file.versions; FILE_MAXSIZE(channel) = destination->file.maximum_size; FILE_MAXREACHED(channel) = ISC_FALSE; break; case ISC_LOG_TOFILEDESC: FILE_NAME(channel) = NULL; FILE_STREAM(channel) = destination->file.stream; FILE_MAXSIZE(channel) = 0; FILE_VERSIONS(channel) = ISC_LOG_ROLLNEVER; break; case ISC_LOG_TONULL: /* Nothing. */ break; default: isc_mem_put(mctx, channel->name, strlen(channel->name) + 1); isc_mem_put(mctx, channel, sizeof(*channel)); return (ISC_R_UNEXPECTED); } ISC_LIST_PREPEND(lcfg->channels, channel, link); /* * If default_stderr was redefined, make the default category * point to the new default_stderr. */ if (strcmp(name, "default_stderr") == 0) default_channel.channel = channel; return (ISC_R_SUCCESS);}isc_result_tisc_log_usechannel(isc_logconfig_t *lcfg, const char *name, const isc_logcategory_t *category, const isc_logmodule_t *module){ isc_log_t *lctx; isc_logchannel_t *channel; isc_result_t result = ISC_R_SUCCESS; unsigned int i; REQUIRE(VALID_CONFIG(lcfg)); REQUIRE(name != NULL); lctx = lcfg->lctx; REQUIRE(category == NULL || category->id < lctx->category_count); REQUIRE(module == NULL || module->id < lctx->module_count); for (channel = ISC_LIST_HEAD(lcfg->channels); channel != NULL; channel = ISC_LIST_NEXT(channel, link)) if (strcmp(name, channel->name) == 0) break; if (channel == NULL) return (ISC_R_NOTFOUND); if (category != NULL) result = assignchannel(lcfg, category->id, module, channel); else /* * Assign to all categories. Note that this includes * the default channel. */ for (i = 0; i < lctx->category_count; i++) { result = assignchannel(lcfg, i, module, channel); if (result != ISC_R_SUCCESS) break; } return (result);}voidisc_log_write(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *format, ...){ va_list args; /* * Contract checking is done in isc_log_doit(). */ va_start(args, format); isc_log_doit(lctx, category, module, level, ISC_FALSE, NULL, 0, 0, format, args); va_end(args);}voidisc_log_vwrite(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *format, va_list args){ /* * Contract checking is done in isc_log_doit(). */ isc_log_doit(lctx, category, module, level, ISC_FALSE, NULL, 0, 0, format, args);}voidisc_log_write1(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *format, ...){ va_list args; /* * Contract checking is done in isc_log_doit(). */ va_start(args, format); isc_log_doit(lctx, category, module, level, ISC_TRUE, NULL, 0, 0, format, args); va_end(args);}voidisc_log_vwrite1(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, const char *format, va_list args){ /* * Contract checking is done in isc_log_doit(). */ isc_log_doit(lctx, category, module, level, ISC_TRUE, NULL, 0, 0, format, args);}voidisc_log_iwrite(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, isc_msgcat_t *msgcat, int msgset, int msg, const char *format, ...){ va_list args; /* * Contract checking is done in isc_log_doit(). */ va_start(args, format); isc_log_doit(lctx, category, module, level, ISC_FALSE, msgcat, msgset, msg, format, args); va_end(args);}voidisc_log_ivwrite(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, isc_msgcat_t *msgcat, int msgset, int msg, const char *format, va_list args){ /* * Contract checking is done in isc_log_doit(). */ isc_log_doit(lctx, category, module, level, ISC_FALSE, msgcat, msgset, msg, format, args);}voidisc_log_iwrite1(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, isc_msgcat_t *msgcat, int msgset, int msg, const char *format, ...){ va_list args; /* * Contract checking is done in isc_log_doit(). */ va_start(args, format); isc_log_doit(lctx, category, module, level, ISC_TRUE, msgcat, msgset, msg, format, args); va_end(args);}voidisc_log_ivwrite1(isc_log_t *lctx, isc_logcategory_t *category, isc_logmodule_t *module, int level, isc_msgcat_t *msgcat, int msgset, int msg, const char *format, va_list args){ /* * Contract checking is done in isc_log_doit(). */ isc_log_doit(lctx, category, module, level, ISC_TRUE, msgcat, msgset, msg, format, args);}voidisc_log_setcontext(isc_log_t *lctx) { isc_lctx = lctx;}voidisc_log_setdebuglevel(isc_log_t *lctx, unsigned int level) { isc_logchannel_t *channel; REQUIRE(VALID_CONTEXT(lctx)); LOCK(&lctx->lock); lctx->debug_level = level; /* * Close ISC_LOG_DEBUGONLY channels if level is zero. */ if (lctx->debug_level == 0) for (channel = ISC_LIST_HEAD(lctx->logconfig->channels); channel != NULL; channel = ISC_LIST_NEXT(channel, link)) if (channel->type == ISC_LOG_TOFILE && (channel->flags & ISC_LOG_DEBUGONLY) != 0 && FILE_STREAM(channel) != NULL) { (void)fclose(FILE_STREAM(channel)); FILE_STREAM(channel) = NULL; } UNLOCK(&lctx->lock);}unsigned intisc_log_getdebuglevel(isc_log_t *lctx) { REQUIRE(VALID_CONTEXT(lctx)); return (lctx->debug_level);}voidisc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval) { REQUIRE(VALID_CONFIG(lcfg)); lcfg->duplicate_interval = interval;}unsigned intisc_log_getduplicateinterval(isc_logconfig_t *lcfg) { REQUIRE(VALID_CONTEXT(lcfg)); return (lcfg->duplicate_interval);}isc_result_tisc_log_settag(isc_logconfig_t *lcfg, const char *tag) { REQUIRE(VALID_CONFIG(lcfg)); if (tag != NULL && *tag != '\0') { if (lcfg->tag != NULL) isc_mem_free(lcfg->lctx->mctx, lcfg->tag); lcfg->tag = isc_mem_strdup(lcfg->lctx->mctx, tag); if (lcfg->tag == NULL) return (ISC_R_NOMEMORY); } else { if (lcfg->tag != NULL) isc_mem_free(lcfg->lctx->mctx, lcfg->tag); lcfg->tag = NULL; } return (ISC_R_SUCCESS);}char *isc_log_gettag(isc_logconfig_t *lcfg) { REQUIRE(VALID_CONFIG(lcfg)); return (lcfg->tag);}/* XXXDCL NT -- This interface will assuredly be changing. */voidisc_log_opensyslog(const char *tag, int options, int facility) { (void)openlog(tag, options, facility);}voidisc_log_closefilelogs(isc_log_t *lctx) { isc_logchannel_t *channel; REQUIRE(VALID_CONTEXT(lctx)); LOCK(&lctx->lock); for (channel = ISC_LIST_HEAD(lctx->logconfig->channels); channel != NULL; channel = ISC_LIST_NEXT(channel, link)) if (channel->type == ISC_LOG_TOFILE && FILE_STREAM(channel) != NULL) { (void)fclose(FILE_STREAM(channel)); FILE_STREAM(channel) = NULL; } UNLOCK(&lctx->lock);}/**** **** Internal functions ****/static isc_result_tassignchannel(isc_logconfig_t *lcfg, unsigned int category_id, const isc_logmodule_t *module, isc_logchannel_t *channel){ isc_logchannellist_t *new_item; isc_log_t *lctx; isc_result_t result; REQUIRE(VALID_CONFIG(lcfg)); lctx = lcfg->lctx; REQUIRE(category_id < lctx->category_count); REQUIRE(module == NULL || module->id < lctx->module_count); REQUIRE(channel != NULL); /* * Ensure lcfg->channellist_count == lctx->category_count. */ result = sync_channellist(lcfg); if (result != ISC_R_SUCCESS) return (result); new_item = isc_mem_get(lctx->mctx, sizeof(*new_item)); if (new_item == NULL) return (ISC_R_NOMEMORY); new_item->channel = channel; new_item->module = module; ISC_LIST_INITANDPREPEND(lcfg->channellists[category_id], new_item, link); /* * Remember the highest logging level set by any channel in the * logging config, so isc_log_doit() can quickly return if the * message is too high to be logged by any channel. */ if (channel->type != ISC_LOG_TONULL) { if (lcfg->highest_level < channel->level) lcfg->highest_level = channel->level; if (channel->level == ISC_LOG_DYNAMIC) lcfg->dynamic = ISC_TRUE; } return (ISC_R_SUCCESS);}/* * This would ideally be part of isc_log_registercategories(), except then * that function would have to return isc_result_t instead of void. */static isc_result_tsync_channellist(isc_logconfig_t *lcfg) { unsigned int bytes; isc_log_t *lctx; void *lists; REQUIRE(VALID_CONFIG(lcfg)); lctx = lcfg->lctx; REQUIRE(lctx->category_count != 0); if (lctx->category_count == lcfg->channellist_count) return (ISC_R_SUCCESS); bytes = lctx->category_count * sizeof(ISC_LIST(isc_logchannellist_t)); lists = isc_mem_get(lctx->mctx, bytes); if (lists == NULL) return (ISC_R_NOMEMORY); memset(lists, 0, bytes); if (lcfg->channellist_count != 0) { bytes = lcfg->channellist_count * sizeof(ISC_LIST(isc_logchannellist_t)); memcpy(lists, lcfg->channellists, bytes); isc_mem_put(lctx->mctx, lcfg->channellists, bytes); } lcfg->channellists = lists; lcfg->channellist_count = lctx->category_count; return (ISC_R_SUCCESS);}static isc_result_tgreatest_version(isc_logchannel_t *channel, int *greatestp) { /* XXXDCL HIGHLY NT */ char *basename, *digit_end; const char *dirname; int version, greatest = -1; unsigned int basenamelen; isc_dir_t dir; isc_result_t result; char sep = '/';#ifdef _WIN32 char *basename2;#endif REQUIRE(channel->type == ISC_LOG_TOFILE); /* * It is safe to DE_CONST the file.name because it was copied * with isc_mem_strdup in isc_log_createchannel. */ basename = strrchr(FILE_NAME(channel), sep);#ifdef _WIN32 basename2 = strrchr(FILE_NAME(channel), '\\'); if ((basename != NULL && basename2 != NULL && basename2 > basename) || (basename == NULL && basename2 != NULL)) { basename = basename2; sep = '\\'; }#endif if (basename != NULL) { *basename++ = '\0'; dirname = FILE_NAME(channel); } else { DE_CONST(FILE_NAME(channel), basename); dirname = "."; } basenamelen = strlen(basename);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -