Annotation of src/usr.bin/tmux/log.c, Revision 1.2
1.2 ! nicm 1: /* $OpenBSD: log.c,v 1.1 2009/06/01 22:58:49 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.2 ! nicm 42: void log_vwrite(int, const char *, va_list);
! 43: __dead void log_vfatal(const char *, va_list);
1.1 nicm 44:
45: /* Open logging to tty. */
46: void
47: log_open_tty(int level)
48: {
49: log_type = LOG_TYPE_TTY;
50: log_level = level;
51:
52: setlinebuf(stderr);
53: setlinebuf(stdout);
54:
55: tzset();
56: }
57:
58: /* Open logging to file. */
59: void
60: log_open_file(int level, const char *path)
61: {
62: log_file = fopen(path, "w");
63: if (log_file == NULL)
64: return;
65:
66: log_type = LOG_TYPE_FILE;
67: log_level = level;
68:
69: setlinebuf(log_file);
70:
71: tzset();
72: }
73:
74: /* Close logging. */
75: void
76: log_close(void)
77: {
78: if (log_type == LOG_TYPE_FILE)
79: fclose(log_file);
80:
81: log_type = LOG_TYPE_OFF;
82: }
83:
84: /* Write a log message. */
85: void
86: log_vwrite(int pri, const char *msg, va_list ap)
87: {
88: char *fmt;
89: FILE *f = log_file;
90:
91: switch (log_type) {
92: case LOG_TYPE_TTY:
93: if (pri == LOG_INFO)
94: f = stdout;
95: else
96: f = stderr;
97: /* FALLTHROUGH */
98: case LOG_TYPE_FILE:
99: if (asprintf(&fmt, "%s\n", msg) == -1)
100: exit(1);
101: if (vfprintf(f, fmt, ap) == -1)
102: exit(1);
103: fflush(f);
104: free(fmt);
105: break;
106: }
107: }
108:
109: /* Log a warning with error string. */
110: void printflike1
111: log_warn(const char *msg, ...)
112: {
113: va_list ap;
114: char *fmt;
115:
116: va_start(ap, msg);
117: if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1)
118: exit(1);
119: log_vwrite(LOG_CRIT, fmt, ap);
120: free(fmt);
121: va_end(ap);
122: }
123:
124: /* Log a warning. */
125: void printflike1
126: log_warnx(const char *msg, ...)
127: {
128: va_list ap;
129:
130: va_start(ap, msg);
131: log_vwrite(LOG_CRIT, msg, ap);
132: va_end(ap);
133: }
134:
135: /* Log an informational message. */
136: void printflike1
137: log_info(const char *msg, ...)
138: {
139: va_list ap;
140:
141: if (log_level > -1) {
142: va_start(ap, msg);
143: log_vwrite(LOG_INFO, msg, ap);
144: va_end(ap);
145: }
146: }
147:
148: /* Log a debug message. */
149: void printflike1
150: log_debug(const char *msg, ...)
151: {
152: va_list ap;
153:
154: if (log_level > 0) {
155: va_start(ap, msg);
156: log_vwrite(LOG_DEBUG, msg, ap);
157: va_end(ap);
158: }
159: }
160:
161: /* Log a debug message at level 2. */
162: void printflike1
163: log_debug2(const char *msg, ...)
164: {
165: va_list ap;
166:
167: if (log_level > 1) {
168: va_start(ap, msg);
169: log_vwrite(LOG_DEBUG, msg, ap);
170: va_end(ap);
171: }
172: }
173:
174: /* Log a debug message at level 3. */
175: void printflike1
176: log_debug3(const char *msg, ...)
177: {
178: va_list ap;
179:
180: if (log_level > 2) {
181: va_start(ap, msg);
182: log_vwrite(LOG_DEBUG, msg, ap);
183: va_end(ap);
184: }
185: }
186:
187: /* Log a critical error, with error string if necessary, and die. */
188: __dead void
189: log_vfatal(const char *msg, va_list ap)
190: {
191: char *fmt;
192:
193: if (errno != 0) {
194: if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1)
195: exit(1);
196: log_vwrite(LOG_CRIT, fmt, ap);
197: } else {
198: if (asprintf(&fmt, "fatal: %s", msg) == -1)
199: exit(1);
200: log_vwrite(LOG_CRIT, fmt, ap);
201: }
202: free(fmt);
203:
204: exit(1);
205: }
206:
207: /* Log a critical error, with error string, and die. */
208: __dead void printflike1
209: log_fatal(const char *msg, ...)
210: {
211: va_list ap;
212:
213: va_start(ap, msg);
214: log_vfatal(msg, ap);
215: }
216:
217: /* Log a critical error and die. */
218: __dead void printflike1
219: log_fatalx(const char *msg, ...)
220: {
221: va_list ap;
222:
223: errno = 0;
224: va_start(ap, msg);
225: log_vfatal(msg, ap);
226: }