📄 logging.c
字号:
/* * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 1996-1999 by Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */#if !defined(LINT) && !defined(CODECENTER)static const char rcsid[] = "$Id: logging.c,v 1.3.2.1.4.2 2004/03/17 01:49:42 marka Exp $";#endif /* not lint */#include "port_before.h"#include <sys/types.h>#include <sys/time.h>#include <sys/stat.h>#include <fcntl.h>#include <limits.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdarg.h>#include <syslog.h>#include <errno.h>#include <time.h>#include <unistd.h>#include <isc/assertions.h>#include <isc/logging.h>#include <isc/memcluster.h>#include <isc/misc.h>#include "port_after.h"#ifdef VSPRINTF_CHAR# define VSPRINTF(x) strlen(vsprintf/**/x)#else# define VSPRINTF(x) ((size_t)vsprintf x)#endif#include "logging_p.h"static const int syslog_priority[] = { LOG_DEBUG, LOG_INFO, LOG_NOTICE, LOG_WARNING, LOG_ERR, LOG_CRIT };static const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };static const char *level_text[] = { "info: ", "notice: ", "warning: ", "error: ", "critical: "};static voidversion_rename(log_channel chan) { unsigned int ver; char old_name[PATH_MAX+1]; char new_name[PATH_MAX+1]; ver = chan->out.file.versions; if (ver < 1) return; if (ver > LOG_MAX_VERSIONS) ver = LOG_MAX_VERSIONS; /* * Need to have room for '.nn' (XXX assumes LOG_MAX_VERSIONS < 100) */ if (strlen(chan->out.file.name) > (size_t)(PATH_MAX-3)) return; for (ver--; ver > 0; ver--) { sprintf(old_name, "%s.%d", chan->out.file.name, ver-1); sprintf(new_name, "%s.%d", chan->out.file.name, ver); (void)isc_movefile(old_name, new_name); } sprintf(new_name, "%s.0", chan->out.file.name); (void)isc_movefile(chan->out.file.name, new_name);}FILE *log_open_stream(log_channel chan) { FILE *stream; int fd, flags; struct stat sb; int regular; if (chan == NULL || chan->type != log_file) { errno = EINVAL; return (NULL); } /* * Don't open already open streams */ if (chan->out.file.stream != NULL) return (chan->out.file.stream); if (stat(chan->out.file.name, &sb) < 0) { if (errno != ENOENT) { syslog(LOG_ERR, "log_open_stream: stat of %s failed: %s", chan->out.file.name, strerror(errno)); chan->flags |= LOG_CHANNEL_BROKEN; return (NULL); } regular = 1; } else regular = (sb.st_mode & S_IFREG); if (chan->out.file.versions) { if (!regular) { syslog(LOG_ERR, "log_open_stream: want versions but %s isn't a regular file", chan->out.file.name); chan->flags |= LOG_CHANNEL_BROKEN; errno = EINVAL; return (NULL); } } flags = O_WRONLY|O_CREAT|O_APPEND; if ((chan->flags & LOG_TRUNCATE) != 0) { if (regular) { (void)unlink(chan->out.file.name); flags |= O_EXCL; } else { syslog(LOG_ERR, "log_open_stream: want truncation but %s isn't a regular file", chan->out.file.name); chan->flags |= LOG_CHANNEL_BROKEN; errno = EINVAL; return (NULL); } } fd = open(chan->out.file.name, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); if (fd < 0) { syslog(LOG_ERR, "log_open_stream: open(%s) failed: %s", chan->out.file.name, strerror(errno)); chan->flags |= LOG_CHANNEL_BROKEN; return (NULL); } stream = fdopen(fd, "a"); if (stream == NULL) { syslog(LOG_ERR, "log_open_stream: fdopen() failed"); chan->flags |= LOG_CHANNEL_BROKEN; return (NULL); } (void) fchown(fd, chan->out.file.owner, chan->out.file.group); chan->out.file.stream = stream; return (stream);}intlog_close_stream(log_channel chan) { FILE *stream; if (chan == NULL || chan->type != log_file) { errno = EINVAL; return (0); } stream = chan->out.file.stream; chan->out.file.stream = NULL; if (stream != NULL && fclose(stream) == EOF) return (-1); return (0);}voidlog_close_debug_channels(log_context lc) { log_channel_list lcl; int i; for (i = 0; i < lc->num_categories; i++) for (lcl = lc->categories[i]; lcl != NULL; lcl = lcl->next) if (lcl->channel->type == log_file && lcl->channel->out.file.stream != NULL && lcl->channel->flags & LOG_REQUIRE_DEBUG) (void)log_close_stream(lcl->channel);}FILE *log_get_stream(log_channel chan) { if (chan == NULL || chan->type != log_file) { errno = EINVAL; return (NULL); } return (chan->out.file.stream);}char *log_get_filename(log_channel chan) { if (chan == NULL || chan->type != log_file) { errno = EINVAL; return (NULL); } return (chan->out.file.name);}intlog_check_channel(log_context lc, int level, log_channel chan) { int debugging, chan_level; REQUIRE(lc != NULL); debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); /* * If not debugging, short circuit debugging messages very early. */ if (level > 0 && !debugging) return (0); if ((chan->flags & (LOG_CHANNEL_BROKEN|LOG_CHANNEL_OFF)) != 0) return (0); /* Some channels only log when debugging is on. */ if ((chan->flags & LOG_REQUIRE_DEBUG) && !debugging) return (0); /* Some channels use the global level. */ if ((chan->flags & LOG_USE_CONTEXT_LEVEL) != 0) { chan_level = lc->level; } else chan_level = chan->level; if (level > chan_level) return (0); return (1);}int log_check(log_context lc, int category, int level) { log_channel_list lcl; int debugging; REQUIRE(lc != NULL); debugging = ((lc->flags & LOG_OPTION_DEBUG) != 0); /* * If not debugging, short circuit debugging messages very early. */ if (level > 0 && !debugging) return (0); if (category < 0 || category > lc->num_categories) category = 0; /* use default */ lcl = lc->categories[category]; if (lcl == NULL) { category = 0; lcl = lc->categories[0]; } for ( /* nothing */; lcl != NULL; lcl = lcl->next) { if (log_check_channel(lc, level, lcl->channel)) return (1); } return (0);}voidlog_vwrite(log_context lc, int category, int level, const char *format, va_list args) { log_channel_list lcl; int pri, debugging, did_vsprintf = 0; int original_category; FILE *stream; log_channel chan; struct timeval tv; struct tm *local_tm;#ifdef HAVE_TIME_R struct tm tm_tmp;#endif time_t tt; const char *category_name; const char *level_str; char time_buf[256]; char level_buf[256]; REQUIRE(lc != NULL); debugging = (lc->flags & LOG_OPTION_DEBUG); /* * If not debugging, short circuit debugging messages very early. */ if (level > 0 && !debugging) return; if (category < 0 || category > lc->num_categories) category = 0; /* use default */ original_category = category; lcl = lc->categories[category]; if (lcl == NULL) { category = 0; lcl = lc->categories[0]; } /* * Get the current time and format it. */ time_buf[0]='\0'; if (gettimeofday(&tv, NULL) < 0) { syslog(LOG_INFO, "gettimeofday failed in log_vwrite()"); } else { tt = tv.tv_sec;#ifdef HAVE_TIME_R local_tm = localtime_r(&tt, &tm_tmp);#else local_tm = localtime(&tt);#endif if (local_tm != NULL) { sprintf(time_buf, "%02d-%s-%4d %02d:%02d:%02d.%03ld ", local_tm->tm_mday, months[local_tm->tm_mon], local_tm->tm_year+1900, local_tm->tm_hour, local_tm->tm_min, local_tm->tm_sec, (long)tv.tv_usec/1000); } } /* * Make a string representation of the current category and level */ if (lc->category_names != NULL && lc->category_names[original_category] != NULL) category_name = lc->category_names[original_category]; else category_name = ""; if (level >= log_critical) { if (level >= 0) { sprintf(level_buf, "debug %d: ", level); level_str = level_buf; } else level_str = level_text[-level-1]; } else { sprintf(level_buf, "level %d: ", level); level_str = level_buf; } /* * Write the message to channels. */ for ( /* nothing */; lcl != NULL; lcl = lcl->next) { chan = lcl->channel;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -