xref: /openbsd-src/usr.bin/tmux/log.c (revision 91f110e064cd7c194e59e019b83bb7496c1c84d4)
1 /* $OpenBSD: log.c,v 1.8 2012/05/30 15:01:21 nicm Exp $ */
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 /* Log file, if needed. */
31 FILE		*log_file;
32 
33 /* Debug level. */
34 int		 log_level = 0;
35 
36 void		 log_event_cb(int, const char *);
37 void		 log_vwrite(const char *, va_list);
38 __dead void	 log_vfatal(const char *, va_list);
39 
40 /* Log callback for libevent. */
41 void
42 log_event_cb(unused int severity, const char *msg)
43 {
44 	log_warnx("%s", msg);
45 }
46 
47 /* Open logging to file. */
48 void
49 log_open(int level, const char *path)
50 {
51 	log_file = fopen(path, "w");
52 	if (log_file == NULL)
53 		return;
54 	log_level = level;
55 
56 	setlinebuf(log_file);
57 	event_set_log_callback(log_event_cb);
58 
59 	tzset();
60 }
61 
62 /* Close logging. */
63 void
64 log_close(void)
65 {
66 	if (log_file != NULL)
67 		fclose(log_file);
68 
69 	event_set_log_callback(NULL);
70 }
71 
72 /* Write a log message. */
73 void
74 log_vwrite(const char *msg, va_list ap)
75 {
76 	char	*fmt;
77 
78 	if (log_file == NULL)
79 		return;
80 
81 	if (asprintf(&fmt, "%s\n", msg) == -1)
82 		exit(1);
83 	if (vfprintf(log_file, fmt, ap) == -1)
84 		exit(1);
85 	fflush(log_file);
86 	free(fmt);
87 }
88 
89 /* Log a warning with error string. */
90 void printflike1
91 log_warn(const char *msg, ...)
92 {
93 	va_list	 ap;
94 	char	*fmt;
95 
96 	va_start(ap, msg);
97 	if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1)
98 		exit(1);
99 	log_vwrite(fmt, ap);
100 	free(fmt);
101 	va_end(ap);
102 }
103 
104 /* Log a warning. */
105 void printflike1
106 log_warnx(const char *msg, ...)
107 {
108 	va_list	ap;
109 
110 	va_start(ap, msg);
111 	log_vwrite(msg, ap);
112 	va_end(ap);
113 }
114 
115 /* Log an informational message. */
116 void printflike1
117 log_info(const char *msg, ...)
118 {
119 	va_list	ap;
120 
121 	if (log_level > -1) {
122 		va_start(ap, msg);
123 		log_vwrite(msg, ap);
124 		va_end(ap);
125 	}
126 }
127 
128 /* Log a debug message. */
129 void printflike1
130 log_debug(const char *msg, ...)
131 {
132 	va_list	ap;
133 
134 	if (log_level > 0) {
135 		va_start(ap, msg);
136 		log_vwrite(msg, ap);
137 		va_end(ap);
138 	}
139 }
140 
141 /* Log a debug message at level 2. */
142 void printflike1
143 log_debug2(const char *msg, ...)
144 {
145 	va_list	ap;
146 
147 	if (log_level > 1) {
148 		va_start(ap, msg);
149 		log_vwrite(msg, ap);
150 		va_end(ap);
151 	}
152 }
153 
154 /* Log a critical error, with error string if necessary, and die. */
155 __dead void
156 log_vfatal(const char *msg, va_list ap)
157 {
158 	char	*fmt;
159 
160 	if (errno != 0) {
161 		if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1)
162 			exit(1);
163 		log_vwrite(fmt, ap);
164 	} else {
165 		if (asprintf(&fmt, "fatal: %s", msg) == -1)
166 			exit(1);
167 		log_vwrite(fmt, ap);
168 	}
169 	free(fmt);
170 
171 	exit(1);
172 }
173 
174 /* Log a critical error, with error string, and die. */
175 __dead void printflike1
176 log_fatal(const char *msg, ...)
177 {
178 	va_list	ap;
179 
180 	va_start(ap, msg);
181 	log_vfatal(msg, ap);
182 }
183 
184 /* Log a critical error and die. */
185 __dead void printflike1
186 log_fatalx(const char *msg, ...)
187 {
188 	va_list	ap;
189 
190 	errno = 0;
191 	va_start(ap, msg);
192 	log_vfatal(msg, ap);
193 }
194