[BACK]Return to Log.c++ CVS log [TXT][DIR] Up to [Development] / fam / fam

Annotation of fam/fam/Log.c++, Revision 1.1.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>