Terminate strftime buffer properly even if a really long format string
[tmux-openbsd.git] / log.c
blob35728855a2bc6c359f63ffdf63cec1ee587f8e3c
1 /* $OpenBSD$ */
3 /*
4 * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
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.
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.
19 #include <sys/types.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <syslog.h>
26 #include <time.h>
28 #include "tmux.h"
30 /* Logging type. */
31 #define LOG_TYPE_OFF 0
32 #define LOG_TYPE_TTY 1
33 #define LOG_TYPE_FILE 2
34 int log_type = LOG_TYPE_OFF;
36 /* Log file, if needed. */
37 FILE *log_file;
39 /* Debug level. */
40 int log_level;
42 void log_vwrite(int, const char *, va_list);
43 __dead void log_vfatal(const char *, va_list);
45 /* Open logging to tty. */
46 void
47 log_open_tty(int level)
49 log_type = LOG_TYPE_TTY;
50 log_level = level;
52 setlinebuf(stderr);
53 setlinebuf(stdout);
55 tzset();
58 /* Open logging to file. */
59 void
60 log_open_file(int level, const char *path)
62 log_file = fopen(path, "w");
63 if (log_file == NULL)
64 return;
66 log_type = LOG_TYPE_FILE;
67 log_level = level;
69 setlinebuf(log_file);
71 tzset();
74 /* Close logging. */
75 void
76 log_close(void)
78 if (log_type == LOG_TYPE_FILE)
79 fclose(log_file);
81 log_type = LOG_TYPE_OFF;
84 /* Write a log message. */
85 void
86 log_vwrite(int pri, const char *msg, va_list ap)
88 char *fmt;
89 FILE *f = log_file;
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;
109 /* Log a warning with error string. */
110 void printflike1
111 log_warn(const char *msg, ...)
113 va_list ap;
114 char *fmt;
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);
124 /* Log a warning. */
125 void printflike1
126 log_warnx(const char *msg, ...)
128 va_list ap;
130 va_start(ap, msg);
131 log_vwrite(LOG_CRIT, msg, ap);
132 va_end(ap);
135 /* Log an informational message. */
136 void printflike1
137 log_info(const char *msg, ...)
139 va_list ap;
141 if (log_level > -1) {
142 va_start(ap, msg);
143 log_vwrite(LOG_INFO, msg, ap);
144 va_end(ap);
148 /* Log a debug message. */
149 void printflike1
150 log_debug(const char *msg, ...)
152 va_list ap;
154 if (log_level > 0) {
155 va_start(ap, msg);
156 log_vwrite(LOG_DEBUG, msg, ap);
157 va_end(ap);
161 /* Log a debug message at level 2. */
162 void printflike1
163 log_debug2(const char *msg, ...)
165 va_list ap;
167 if (log_level > 1) {
168 va_start(ap, msg);
169 log_vwrite(LOG_DEBUG, msg, ap);
170 va_end(ap);
174 /* Log a critical error, with error string if necessary, and die. */
175 __dead void
176 log_vfatal(const char *msg, va_list ap)
178 char *fmt;
180 if (errno != 0) {
181 if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1)
182 exit(1);
183 log_vwrite(LOG_CRIT, fmt, ap);
184 } else {
185 if (asprintf(&fmt, "fatal: %s", msg) == -1)
186 exit(1);
187 log_vwrite(LOG_CRIT, fmt, ap);
189 free(fmt);
191 exit(1);
194 /* Log a critical error, with error string, and die. */
195 __dead void printflike1
196 log_fatal(const char *msg, ...)
198 va_list ap;
200 va_start(ap, msg);
201 log_vfatal(msg, ap);
204 /* Log a critical error and die. */
205 __dead void printflike1
206 log_fatalx(const char *msg, ...)
208 va_list ap;
210 errno = 0;
211 va_start(ap, msg);
212 log_vfatal(msg, ap);