Annotation of src/usr.bin/tmux/log.c, Revision 1.6
1.6 ! nicm 1: /* $OpenBSD: log.c,v 1.5 2012/03/17 18:23:03 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15: * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16: * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: #include <sys/types.h>
20:
21: #include <errno.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <string.h>
25: #include <syslog.h>
26: #include <time.h>
27:
28: #include "tmux.h"
29:
30: /* Logging type. */
31: #define LOG_TYPE_OFF 0
1.2 nicm 32: #define LOG_TYPE_TTY 1
33: #define LOG_TYPE_FILE 2
1.1 nicm 34: int log_type = LOG_TYPE_OFF;
35:
36: /* Log file, if needed. */
37: FILE *log_file;
38:
39: /* Debug level. */
40: int log_level;
41:
1.6 ! nicm 42: void log_event_cb(int, const char *);
1.2 nicm 43: void log_vwrite(int, const char *, va_list);
44: __dead void log_vfatal(const char *, va_list);
1.1 nicm 45:
1.5 nicm 46: /* Log callback for libevent. */
47: void
48: log_event_cb(unused int severity, const char *msg)
49: {
1.6 ! nicm 50: log_warnx("%s", msg);
1.5 nicm 51: }
52:
1.1 nicm 53: /* Open logging to tty. */
54: void
55: log_open_tty(int level)
56: {
57: log_type = LOG_TYPE_TTY;
58: log_level = level;
59:
60: setlinebuf(stderr);
61: setlinebuf(stdout);
1.5 nicm 62: event_set_log_callback(log_event_cb);
1.1 nicm 63:
64: tzset();
65: }
66:
67: /* Open logging to file. */
68: void
69: log_open_file(int level, const char *path)
70: {
71: log_file = fopen(path, "w");
72: if (log_file == NULL)
73: return;
74:
75: log_type = LOG_TYPE_FILE;
76: log_level = level;
77:
78: setlinebuf(log_file);
1.5 nicm 79: event_set_log_callback(log_event_cb);
1.1 nicm 80:
81: tzset();
82: }
83:
84: /* Close logging. */
85: void
86: log_close(void)
87: {
88: if (log_type == LOG_TYPE_FILE)
89: fclose(log_file);
1.5 nicm 90:
91: event_set_log_callback(NULL);
1.1 nicm 92:
93: log_type = LOG_TYPE_OFF;
94: }
95:
96: /* Write a log message. */
97: void
98: log_vwrite(int pri, const char *msg, va_list ap)
99: {
100: char *fmt;
101: FILE *f = log_file;
102:
103: switch (log_type) {
104: case LOG_TYPE_TTY:
105: if (pri == LOG_INFO)
106: f = stdout;
107: else
108: f = stderr;
109: /* FALLTHROUGH */
110: case LOG_TYPE_FILE:
111: if (asprintf(&fmt, "%s\n", msg) == -1)
112: exit(1);
113: if (vfprintf(f, fmt, ap) == -1)
114: exit(1);
115: fflush(f);
116: free(fmt);
117: break;
118: }
119: }
120:
121: /* Log a warning with error string. */
122: void printflike1
123: log_warn(const char *msg, ...)
124: {
125: va_list ap;
126: char *fmt;
127:
128: va_start(ap, msg);
129: if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1)
130: exit(1);
131: log_vwrite(LOG_CRIT, fmt, ap);
132: free(fmt);
133: va_end(ap);
134: }
135:
136: /* Log a warning. */
137: void printflike1
138: log_warnx(const char *msg, ...)
139: {
140: va_list ap;
141:
142: va_start(ap, msg);
143: log_vwrite(LOG_CRIT, msg, ap);
144: va_end(ap);
145: }
146:
147: /* Log an informational message. */
148: void printflike1
149: log_info(const char *msg, ...)
150: {
151: va_list ap;
152:
153: if (log_level > -1) {
154: va_start(ap, msg);
155: log_vwrite(LOG_INFO, msg, ap);
156: va_end(ap);
157: }
158: }
159:
160: /* Log a debug message. */
161: void printflike1
162: log_debug(const char *msg, ...)
163: {
164: va_list ap;
165:
166: if (log_level > 0) {
167: va_start(ap, msg);
168: log_vwrite(LOG_DEBUG, msg, ap);
169: va_end(ap);
170: }
171: }
172:
173: /* Log a debug message at level 2. */
174: void printflike1
175: log_debug2(const char *msg, ...)
176: {
177: va_list ap;
178:
179: if (log_level > 1) {
180: va_start(ap, msg);
181: log_vwrite(LOG_DEBUG, msg, ap);
182: va_end(ap);
183: }
184: }
185:
186: /* Log a critical error, with error string if necessary, and die. */
187: __dead void
188: log_vfatal(const char *msg, va_list ap)
189: {
190: char *fmt;
191:
192: if (errno != 0) {
193: if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1)
194: exit(1);
195: log_vwrite(LOG_CRIT, fmt, ap);
196: } else {
197: if (asprintf(&fmt, "fatal: %s", msg) == -1)
1.4 nicm 198: exit(1);
1.1 nicm 199: log_vwrite(LOG_CRIT, fmt, ap);
200: }
201: free(fmt);
202:
203: exit(1);
204: }
205:
206: /* Log a critical error, with error string, and die. */
207: __dead void printflike1
208: log_fatal(const char *msg, ...)
209: {
210: va_list ap;
211:
212: va_start(ap, msg);
213: log_vfatal(msg, ap);
214: }
215:
216: /* Log a critical error and die. */
217: __dead void printflike1
218: log_fatalx(const char *msg, ...)
219: {
220: va_list ap;
221:
222: errno = 0;
223: va_start(ap, msg);
224: log_vfatal(msg, ap);
225: }