📄 log.c++
字号:
// Copyright (C) 1999-2002 Silicon Graphics, Inc. All Rights Reserved.//// This program is free software; you can redistribute it and/or modify it// under the terms of version 2 of the GNU General Public License as// published by the Free Software Foundation.//// This program is distributed in the hope that it would be useful, but// WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any// license provided herein, whether implied or otherwise, is limited to// this program in accordance with the express provisions of the GNU// General Public License. Patent licenses, if any, provided herein do not// apply to combinations of this program with other product or programs, or// any other product whatsoever. This program is distributed without any// warranty that the program is delivered free of the rightful claim of any// third person by way of infringement or the like. See the GNU General// Public License for more details.//// You should have received a copy of the GNU General Public License along// with this program; if not, write the Free Software Foundation, Inc., 59// Temple Place - Suite 330, Boston MA 02111-1307, USA.#include "Log.h"#include <assert.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <syslog.h>#include <sys/resource.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/types.h>#include <unistd.h>#ifdef HAVE_AUDIT#include <sat.h>#endifLog::LogLevel Log::level = ERROR;bool Log::log_to_stderr = false;const char *Log::program_name = "fam";bool Log::syslog_open = false;unsigned Log::count = 0;#ifdef HAVE_AUDITbool Log::audit_enabled = true;#endifvoidLog::debug(){ level = DEBUG; info("log level is LOG_DEBUG");}voidLog::info(){ level = INFO; info("log level is LOG_INFO");}voidLog::error(){ level = INFO; info("log level is LOG_ERR"); level = ERROR;}voidLog::disable_audit(){#ifdef HAVE_AUDIT audit_enabled = false; info("disabling security audit trail");#endif}voidLog::foreground(){ log_to_stderr = true; if (syslog_open) { closelog(); syslog_open = false; }}voidLog::background(){ log_to_stderr = false;}voidLog::name(const char *newname){ program_name = newname; audit(true, "fam changing process name to \"%s\"", newname);}voidLog::debug(const char *fmt, ...){ if (level >= DEBUG) { va_list a; va_start(a, fmt); vlog(DEBUG, fmt, a); va_end(a); }}voidLog::info(const char *fmt, ...){ if (level >= INFO) { va_list a; va_start(a, fmt); vlog(INFO, fmt, a); va_end(a); }}voidLog::error(const char *fmt, ...){ if (level >= ERROR) { va_list a; va_start(a, fmt); vlog(ERROR, fmt, a); va_end(a); }}voidLog::critical(const char *fmt, ...){ if (level >= CRITICAL) { va_list a; va_start(a, fmt); vlog(CRITICAL, fmt, a); va_end(a); }}voidLog::perror(const char *format, ...){ if (level >= ERROR) { char * buf = new char[strlen(format) + 5]; (void) strcpy(buf, format); (void) strcat(buf, ": %m"); va_list args; va_start(args, format); vlog(ERROR, buf, args); va_end(args); delete[] buf; }}voidLog::audit(bool success, const char *format, ...){#ifdef HAVE_AUDIT if (audit_enabled) { // This is not so good. If there were a version of satwrite // which took a va_list, this buffer would not need to be here. char buf[SAT_MAX_USER_REC]; va_list args; va_start(args, format); int len = vsnprintf(buf, SAT_MAX_USER_REC, format, args); va_end(args); if(len > 0) satwrite(SAT_AE_CUSTOM, success ? SAT_SUCCESS : SAT_FAILURE, buf, len); }#endif}// This is like debug(), info(), & error(), but it logs regardless of the// current log level.voidLog::log(LogLevel l, const char *fmt, ...){ va_list a; va_start(a, fmt); vlog(l, fmt, a); va_end(a);}voidLog::vlog(LogLevel l, const char *format, va_list args){ if (log_to_stderr) vfglog(format, args); else { if (!syslog_open) { openlog(program_name, LOG_PID, LOG_DAEMON); syslog_open = true; } int ll; switch (l) { case DEBUG: ll = LOG_DEBUG; break; case INFO: ll = LOG_INFO; break; case ERROR: ll = LOG_ERR; break; case CRITICAL: default: ll = LOG_CRIT; break; } vsyslog(ll, format, args); }}voidLog::vfglog(const char *format, va_list args){ // Count number of %'s in the format string. That's the max // number of %m's that there can be. int numPercents = 0; const char *pt = format; while(*pt) { if (*pt++ == '%') numPercents++; } char * err; // Only get the error string if there's a chance we'll use it. if (numPercents > 0) { err = strerror(errno); if (err == NULL) { err = "Unknown error"; } } else { err = ""; } // This 2 is for the \n and the null terminator added by the strcpy. char *buf = new char[strlen(format) + 2 + strlen(err) * numPercents]; char *p = buf; while (*format) { if (format[0] == '%' && format[1] == 'm') { p += strlen(strcpy(p, err)); format += 2; } else { *p++ = *format++; } } (void) strcpy(p, "\n"); (void) fprintf(stderr, "%s[%d]: ", program_name, getpid()); (void) vfprintf(stderr, buf, args); delete[] buf;}#ifndef NDEBUG// New back end for assert() will log to syslog, put core file// in known directory.void __assert(const char *msg, const char *file, int line){ char *dirname = new char[strlen(Log::getName()) + 20]; (void) sprintf(dirname, "/usr/tmp/%s.%d", Log::getName(), getpid()); Log::error("Assertion failed at %s line %d: %s", file, line, msg); Log::error("Dumping core in %s/core", dirname); if (setreuid(0, 0) < 0) Log::perror("setreuid"); if (mkdir(dirname, 0755) < 0) Log::perror("mkdir"); if (chdir(dirname) < 0) Log::perror("chdir"); struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; if (setrlimit(RLIMIT_CORE, &rl) < 0) Log::perror("setrlimit(RLIMIT_CORE)"); delete[] dirname; abort();}#endif /* !NDEBUG */#ifdef HAPPY_PURIFYLog::Log(){ count++;}Log::~Log(){ if (!--count) { if (syslog_open) { closelog(); syslog_open = false; } }}#endif /* HAPPY_PURIFY */#ifdef UNIT_TEST_Log#include <fcntl.h>#include <sys/stat.h>intmain(){ Log::name("unit test"); Log::debug(); Log::foreground(); Log::debug("De bug is in %s.", "de rug"); Log::info("Thank %s for sharing %s.", "you", "that"); Log::error("The %s in %s falls.", "rain", "Spain"); if (open("/foo%bar", 0) < 0) Log::perror("/foo%c%s", '%', "bar"); if (chmod("/", 0777) < 0) Log::error("%m on chmod(\"%s\", 0%o)", "/", 0777); return 0;}#endif /* UNIT_TEST_Log */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -