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>