Annotation of fam/fam/Log.c++, Revision 1.1
1.1 ! trev 1: // Copyright (C) 1999-2002 Silicon Graphics, Inc. All Rights Reserved.
! 2: //
! 3: // This program is free software; you can redistribute it and/or modify it
! 4: // under the terms of version 2 of the GNU General Public License as
! 5: // published by the Free Software Foundation.
! 6: //
! 7: // This program is distributed in the hope that it would be useful, but
! 8: // WITHOUT ANY WARRANTY; without even the implied warranty of
! 9: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any
! 10: // license provided herein, whether implied or otherwise, is limited to
! 11: // this program in accordance with the express provisions of the GNU
! 12: // General Public License. Patent licenses, if any, provided herein do not
! 13: // apply to combinations of this program with other product or programs, or
! 14: // any other product whatsoever. This program is distributed without any
! 15: // warranty that the program is delivered free of the rightful claim of any
! 16: // third person by way of infringement or the like. See the GNU General
! 17: // Public License for more details.
! 18: //
! 19: // You should have received a copy of the GNU General Public License along
! 20: // with this program; if not, write the Free Software Foundation, Inc., 59
! 21: // Temple Place - Suite 330, Boston MA 02111-1307, USA.
! 22:
! 23: #include "Log.h"
! 24:
! 25: #include <assert.h>
! 26: #include <errno.h>
! 27: #include <stdio.h>
! 28: #include <stdlib.h>
! 29: #include <string.h>
! 30: #include <syslog.h>
! 31: #include <sys/resource.h>
! 32: #include <sys/stat.h>
! 33: #include <sys/time.h>
! 34: #include <sys/types.h>
! 35: #include <unistd.h>
! 36: #ifdef HAVE_AUDIT
! 37: #include <sat.h>
! 38: #endif
! 39:
! 40: Log::LogLevel Log::level = ERROR;
! 41: bool Log::log_to_stderr = false;
! 42: const char *Log::program_name = "fam";
! 43: bool Log::syslog_open = false;
! 44: unsigned Log::count = 0;
! 45: #ifdef HAVE_AUDIT
! 46: bool Log::audit_enabled = true;
! 47: #endif
! 48:
! 49: void
! 50: Log::debug()
! 51: {
! 52: level = DEBUG;
! 53: info("log level is LOG_DEBUG");
! 54: }
! 55:
! 56: void
! 57: Log::info()
! 58: {
! 59: level = INFO;
! 60: info("log level is LOG_INFO");
! 61: }
! 62:
! 63: void
! 64: Log::error()
! 65: {
! 66: level = INFO;
! 67: info("log level is LOG_ERR");
! 68: level = ERROR;
! 69: }
! 70:
! 71: void
! 72: Log::disable_audit()
! 73: {
! 74: #ifdef HAVE_AUDIT
! 75: audit_enabled = false;
! 76: info("disabling security audit trail");
! 77: #endif
! 78: }
! 79:
! 80: void
! 81: Log::foreground()
! 82: {
! 83: log_to_stderr = true;
! 84: if (syslog_open)
! 85: { closelog();
! 86: syslog_open = false;
! 87: }
! 88: }
! 89:
! 90: void
! 91: Log::background()
! 92: {
! 93: log_to_stderr = false;
! 94: }
! 95:
! 96: void
! 97: Log::name(const char *newname)
! 98: {
! 99: program_name = newname;
! 100: audit(true, "fam changing process name to \"%s\"", newname);
! 101: }
! 102:
! 103: void
! 104: Log::debug(const char *fmt, ...)
! 105: {
! 106: if (level >= DEBUG)
! 107: {
! 108: va_list a;
! 109: va_start(a, fmt);
! 110: vlog(DEBUG, fmt, a);
! 111: va_end(a);
! 112: }
! 113: }
! 114:
! 115: void
! 116: Log::info(const char *fmt, ...)
! 117: {
! 118: if (level >= INFO)
! 119: {
! 120: va_list a;
! 121: va_start(a, fmt);
! 122: vlog(INFO, fmt, a);
! 123: va_end(a);
! 124: }
! 125: }
! 126:
! 127: void
! 128: Log::error(const char *fmt, ...)
! 129: {
! 130: if (level >= ERROR)
! 131: {
! 132: va_list a;
! 133: va_start(a, fmt);
! 134: vlog(ERROR, fmt, a);
! 135: va_end(a);
! 136: }
! 137: }
! 138:
! 139: void
! 140: Log::critical(const char *fmt, ...)
! 141: {
! 142: if (level >= CRITICAL)
! 143: {
! 144: va_list a;
! 145: va_start(a, fmt);
! 146: vlog(CRITICAL, fmt, a);
! 147: va_end(a);
! 148: }
! 149: }
! 150:
! 151: void
! 152: Log::perror(const char *format, ...)
! 153: {
! 154: if (level >= ERROR)
! 155: { char * buf = new char[strlen(format) + 5];
! 156: (void) strcpy(buf, format);
! 157: (void) strcat(buf, ": %m");
! 158: va_list args;
! 159: va_start(args, format);
! 160: vlog(ERROR, buf, args);
! 161: va_end(args);
! 162: delete[] buf;
! 163: }
! 164: }
! 165:
! 166: void
! 167: Log::audit(bool success, const char *format, ...)
! 168: {
! 169: #ifdef HAVE_AUDIT
! 170: if (audit_enabled)
! 171: {
! 172: // This is not so good. If there were a version of satwrite
! 173: // which took a va_list, this buffer would not need to be here.
! 174: char buf[SAT_MAX_USER_REC];
! 175: va_list args;
! 176: va_start(args, format);
! 177: int len = vsnprintf(buf, SAT_MAX_USER_REC, format, args);
! 178: va_end(args);
! 179: if(len > 0) satwrite(SAT_AE_CUSTOM, success ? SAT_SUCCESS : SAT_FAILURE,
! 180: buf, len);
! 181: }
! 182: #endif
! 183: }
! 184:
! 185: // This is like debug(), info(), & error(), but it logs regardless of the
! 186: // current log level.
! 187: void
! 188: Log::log(LogLevel l, const char *fmt, ...)
! 189: {
! 190: va_list a;
! 191: va_start(a, fmt);
! 192: vlog(l, fmt, a);
! 193: va_end(a);
! 194: }
! 195:
! 196: void
! 197: Log::vlog(LogLevel l, const char *format, va_list args)
! 198: {
! 199: if (log_to_stderr)
! 200: vfglog(format, args);
! 201: else {
! 202: if (!syslog_open) {
! 203: openlog(program_name, LOG_PID, LOG_DAEMON);
! 204: syslog_open = true;
! 205: }
! 206: int ll;
! 207: switch (l) {
! 208: case DEBUG:
! 209: ll = LOG_DEBUG; break;
! 210: case INFO:
! 211: ll = LOG_INFO; break;
! 212: case ERROR:
! 213: ll = LOG_ERR; break;
! 214: case CRITICAL:
! 215: default:
! 216: ll = LOG_CRIT; break;
! 217: }
! 218: vsyslog(ll, format, args);
! 219: }
! 220: }
! 221:
! 222: void
! 223: Log::vfglog(const char *format, va_list args)
! 224: {
! 225: // Count number of %'s in the format string. That's the max
! 226: // number of %m's that there can be.
! 227: int numPercents = 0;
! 228: const char *pt = format;
! 229: while(*pt) {
! 230: if (*pt++ == '%') numPercents++;
! 231: }
! 232: char * err;
! 233:
! 234: // Only get the error string if there's a chance we'll use it.
! 235: if (numPercents > 0) {
! 236: err = strerror(errno);
! 237: if (err == NULL) {
! 238: err = "Unknown error";
! 239: }
! 240: } else {
! 241: err = "";
! 242: }
! 243:
! 244: // This 2 is for the \n and the null terminator added by the strcpy.
! 245: char *buf = new char[strlen(format) + 2 + strlen(err) *
! 246: numPercents];
! 247: char *p = buf;
! 248: while (*format) {
! 249: if (format[0] == '%' && format[1] == 'm') {
! 250: p += strlen(strcpy(p, err));
! 251: format += 2;
! 252: } else {
! 253: *p++ = *format++;
! 254: }
! 255: }
! 256: (void) strcpy(p, "\n");
! 257: (void) fprintf(stderr, "%s[%d]: ", program_name, getpid());
! 258: (void) vfprintf(stderr, buf, args);
! 259: delete[] buf;
! 260: }
! 261:
! 262: #ifndef NDEBUG
! 263:
! 264: // New back end for assert() will log to syslog, put core file
! 265: // in known directory.
! 266:
! 267: void __assert(const char *msg, const char *file, int line)
! 268: {
! 269: char *dirname = new char[strlen(Log::getName()) + 20];
! 270: (void) sprintf(dirname, "/usr/tmp/%s.%d", Log::getName(), getpid());
! 271: Log::error("Assertion failed at %s line %d: %s", file, line, msg);
! 272: Log::error("Dumping core in %s/core", dirname);
! 273:
! 274: if (setreuid(0, 0) < 0)
! 275: Log::perror("setreuid");
! 276: if (mkdir(dirname, 0755) < 0)
! 277: Log::perror("mkdir");
! 278: if (chdir(dirname) < 0)
! 279: Log::perror("chdir");
! 280: struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY };
! 281: if (setrlimit(RLIMIT_CORE, &rl) < 0)
! 282: Log::perror("setrlimit(RLIMIT_CORE)");
! 283: delete[] dirname;
! 284: abort();
! 285: }
! 286:
! 287: #endif /* !NDEBUG */
! 288:
! 289: #ifdef HAPPY_PURIFY
! 290:
! 291: Log::Log()
! 292: {
! 293: count++;
! 294: }
! 295:
! 296: Log::~Log()
! 297: {
! 298: if (!--count)
! 299: { if (syslog_open)
! 300: { closelog();
! 301: syslog_open = false;
! 302: }
! 303: }
! 304: }
! 305:
! 306: #endif /* HAPPY_PURIFY */
! 307:
! 308: #ifdef UNIT_TEST_Log
! 309:
! 310: #include <fcntl.h>
! 311: #include <sys/stat.h>
! 312:
! 313: int
! 314: main()
! 315: {
! 316: Log::name("unit test");
! 317: Log::debug();
! 318: Log::foreground();
! 319: Log::debug("De bug is in %s.", "de rug");
! 320: Log::info("Thank %s for sharing %s.", "you", "that");
! 321: Log::error("The %s in %s falls.", "rain", "Spain");
! 322: if (open("/foo%bar", 0) < 0)
! 323: Log::perror("/foo%c%s", '%', "bar");
! 324: if (chmod("/", 0777) < 0)
! 325: Log::error("%m on chmod(\"%s\", 0%o)", "/", 0777);
! 326: return 0;
! 327: }
! 328:
! 329: #endif /* UNIT_TEST_Log */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>