xref: /minix3/external/bsd/tmux/dist/log.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1 /* Id */
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) __printflike(1, 0);
38 __dead void	 log_vfatal(const char *, va_list);
39 
40 /* Log callback for libevent. */
41 void
log_event_cb(unused int severity,const char * msg)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
log_open(int level,const char * path)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
log_close(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
log_vwrite(const char * msg,va_list ap)74 log_vwrite(const char *msg, va_list ap)
75 {
76 	if (log_file == NULL)
77 		return;
78 
79 	if (vfprintf(log_file, msg, ap) == -1)
80 		exit(1);
81 	if (fprintf(log_file, "\n") == -1)
82 		exit(1);
83 	fflush(log_file);
84 }
85 
86 /* Log a warning with error string. */
87 #if __GNUC_PREREQ__(4, 6) || defined(__clang__)
88 #pragma GCC diagnostic push
89 #endif
90 #if __GNUC_PREREQ__(4, 5) || defined(__clang__)
91 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
92 #endif
93 void printflike1
log_warn(const char * msg,...)94 log_warn(const char *msg, ...)
95 {
96 	va_list	 ap;
97 	char	*fmt;
98 
99 	va_start(ap, msg);
100 	if (asprintf(&fmt, "%s: %s", msg, strerror(errno)) == -1)
101 		exit(1);
102 	log_vwrite(fmt, ap);
103 	free(fmt);
104 	va_end(ap);
105 }
106 #if __GNUC_PREREQ__(4, 6) || defined(__clang__)
107 #pragma GCC diagnostic push
108 #endif
109 
110 /* Log a warning. */
111 void printflike1
log_warnx(const char * msg,...)112 log_warnx(const char *msg, ...)
113 {
114 	va_list	ap;
115 
116 	va_start(ap, msg);
117 	log_vwrite(msg, ap);
118 	va_end(ap);
119 }
120 
121 /* Log an informational message. */
122 void printflike1
log_info(const char * msg,...)123 log_info(const char *msg, ...)
124 {
125 	va_list	ap;
126 
127 	if (log_level > -1) {
128 		va_start(ap, msg);
129 		log_vwrite(msg, ap);
130 		va_end(ap);
131 	}
132 }
133 
134 /* Log a debug message. */
135 void printflike1
log_debug(const char * msg,...)136 log_debug(const char *msg, ...)
137 {
138 	va_list	ap;
139 
140 	if (log_level > 0) {
141 		va_start(ap, msg);
142 		log_vwrite(msg, ap);
143 		va_end(ap);
144 	}
145 }
146 
147 /* Log a debug message at level 2. */
148 void printflike1
log_debug2(const char * msg,...)149 log_debug2(const char *msg, ...)
150 {
151 	va_list	ap;
152 
153 	if (log_level > 1) {
154 		va_start(ap, msg);
155 		log_vwrite(msg, ap);
156 		va_end(ap);
157 	}
158 }
159 
160 /* Log a critical error, with error string if necessary, and die. */
161 __dead void
log_vfatal(const char * msg,va_list ap)162 log_vfatal(const char *msg, va_list ap)
163 {
164 	char	*fmt;
165 
166 	if (errno != 0) {
167 		if (asprintf(&fmt, "fatal: %s: %s", msg, strerror(errno)) == -1)
168 			exit(1);
169 		log_vwrite(fmt, ap);
170 	} else {
171 		if (asprintf(&fmt, "fatal: %s", msg) == -1)
172 			exit(1);
173 		log_vwrite(fmt, ap);
174 	}
175 	free(fmt);
176 
177 	exit(1);
178 }
179 
180 /* Log a critical error, with error string, and die. */
181 __dead void printflike1
log_fatal(const char * msg,...)182 log_fatal(const char *msg, ...)
183 {
184 	va_list	ap;
185 
186 	va_start(ap, msg);
187 	log_vfatal(msg, ap);
188 }
189 
190 /* Log a critical error and die. */
191 __dead void printflike1
log_fatalx(const char * msg,...)192 log_fatalx(const char *msg, ...)
193 {
194 	va_list	ap;
195 
196 	errno = 0;
197 	va_start(ap, msg);
198 	log_vfatal(msg, ap);
199 }
200