xref: /openbsd-src/usr.bin/tmux/log.c (revision 3e8355bd15d76a0b1ae5fe25085a5e74afed9b73)
1*3e8355bdSnicm /* $OpenBSD: log.c,v 1.31 2022/05/30 12:55:25 nicm Exp $ */
2311827fbSnicm 
3311827fbSnicm /*
498ca8272Snicm  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
5311827fbSnicm  *
6311827fbSnicm  * Permission to use, copy, modify, and distribute this software for any
7311827fbSnicm  * purpose with or without fee is hereby granted, provided that the above
8311827fbSnicm  * copyright notice and this permission notice appear in all copies.
9311827fbSnicm  *
10311827fbSnicm  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11311827fbSnicm  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12311827fbSnicm  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13311827fbSnicm  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14311827fbSnicm  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15311827fbSnicm  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16311827fbSnicm  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17311827fbSnicm  */
18311827fbSnicm 
19311827fbSnicm #include <sys/types.h>
20311827fbSnicm 
21311827fbSnicm #include <errno.h>
22311827fbSnicm #include <stdio.h>
23311827fbSnicm #include <stdlib.h>
24311827fbSnicm #include <string.h>
250a607e68Snicm #include <unistd.h>
26511c01a4Snicm #include <vis.h>
27311827fbSnicm 
28311827fbSnicm #include "tmux.h"
29311827fbSnicm 
300a607e68Snicm static FILE	*log_file;
310a607e68Snicm static int	 log_level;
32311827fbSnicm 
33522c38a2Snicm /* Log callback for libevent. */
340a607e68Snicm static void
log_event_cb(__unused int severity,const char * msg)35d0e2e7f1Snicm log_event_cb(__unused int severity, const char *msg)
36522c38a2Snicm {
3740639ef8Snicm 	log_debug("%s", msg);
38522c38a2Snicm }
39522c38a2Snicm 
400a607e68Snicm /* Increment log level. */
410a607e68Snicm void
log_add_level(void)420a607e68Snicm log_add_level(void)
430a607e68Snicm {
440a607e68Snicm 	log_level++;
450a607e68Snicm }
460a607e68Snicm 
470a607e68Snicm /* Get log level. */
480a607e68Snicm int
log_get_level(void)490a607e68Snicm log_get_level(void)
500a607e68Snicm {
510a607e68Snicm 	return (log_level);
520a607e68Snicm }
530a607e68Snicm 
54311827fbSnicm /* Open logging to file. */
55311827fbSnicm void
log_open(const char * name)560a607e68Snicm log_open(const char *name)
57311827fbSnicm {
580a607e68Snicm 	char	*path;
590a607e68Snicm 
600a607e68Snicm 	if (log_level == 0)
610a607e68Snicm 		return;
6279c9b201Snicm 	log_close();
63b6ec4ef1Snicm 
640a607e68Snicm 	xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid());
6579c9b201Snicm 	log_file = fopen(path, "a");
660a607e68Snicm 	free(path);
67311827fbSnicm 	if (log_file == NULL)
68311827fbSnicm 		return;
69311827fbSnicm 
70b9a887b6Smillert 	setvbuf(log_file, NULL, _IOLBF, 0);
71522c38a2Snicm 	event_set_log_callback(log_event_cb);
72311827fbSnicm }
73311827fbSnicm 
7479c9b201Snicm /* Toggle logging. */
7579c9b201Snicm void
log_toggle(const char * name)7679c9b201Snicm log_toggle(const char *name)
7779c9b201Snicm {
7879c9b201Snicm 	if (log_level == 0) {
7979c9b201Snicm 		log_level = 1;
8079c9b201Snicm 		log_open(name);
8179c9b201Snicm 		log_debug("log opened");
8279c9b201Snicm 	} else {
8379c9b201Snicm 		log_debug("log closed");
8479c9b201Snicm 		log_level = 0;
8579c9b201Snicm 		log_close();
8679c9b201Snicm 	}
8779c9b201Snicm }
8879c9b201Snicm 
89311827fbSnicm /* Close logging. */
90311827fbSnicm void
log_close(void)91311827fbSnicm log_close(void)
92311827fbSnicm {
93f5639e04Snicm 	if (log_file != NULL)
94311827fbSnicm 		fclose(log_file);
9546b1c757Snicm 	log_file = NULL;
96311827fbSnicm 
97522c38a2Snicm 	event_set_log_callback(NULL);
98311827fbSnicm }
99311827fbSnicm 
100311827fbSnicm /* Write a log message. */
101ceb4a27fSnicm static void printflike(1, 0)
log_vwrite(const char * msg,va_list ap,const char * prefix)102554405bcSnicm log_vwrite(const char *msg, va_list ap, const char *prefix)
103311827fbSnicm {
104554405bcSnicm 	char		*s, *out;
1052d378871Snicm 	struct timeval	 tv;
106311827fbSnicm 
107f5639e04Snicm 	if (log_file == NULL)
108f5639e04Snicm 		return;
109f5639e04Snicm 
110554405bcSnicm 	if (vasprintf(&s, msg, ap) == -1)
111b96171b1Snicm 		return;
112554405bcSnicm 	if (stravis(&out, s, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1) {
113554405bcSnicm 		free(s);
114b96171b1Snicm 		return;
115b96171b1Snicm 	}
116554405bcSnicm 	free(s);
117511c01a4Snicm 
118511c01a4Snicm 	gettimeofday(&tv, NULL);
119554405bcSnicm 	if (fprintf(log_file, "%lld.%06d %s%s\n", (long long)tv.tv_sec,
120554405bcSnicm 	    (int)tv.tv_usec, prefix, out) != -1)
12136fa3172Snicm 		fflush(log_file);
122511c01a4Snicm 	free(out);
123311827fbSnicm }
124311827fbSnicm 
125311827fbSnicm /* Log a debug message. */
12674d4b937Snicm void
log_debug(const char * msg,...)127311827fbSnicm log_debug(const char *msg, ...)
128311827fbSnicm {
129311827fbSnicm 	va_list	ap;
130311827fbSnicm 
13126a51baaSnicm 	if (log_file == NULL)
13226a51baaSnicm 		return;
13326a51baaSnicm 
134311827fbSnicm 	va_start(ap, msg);
135554405bcSnicm 	log_vwrite(msg, ap, "");
136311827fbSnicm 	va_end(ap);
137311827fbSnicm }
138311827fbSnicm 
13946b1c757Snicm /* Log a critical error with error string and die. */
14074d4b937Snicm __dead void
fatal(const char * msg,...)1413baad57eSnicm fatal(const char *msg, ...)
142311827fbSnicm {
143554405bcSnicm 	char	 tmp[256];
144311827fbSnicm 	va_list	 ap;
145311827fbSnicm 
146554405bcSnicm 	if (snprintf(tmp, sizeof tmp, "fatal: %s: ", strerror(errno)) < 0)
14746b1c757Snicm 		exit(1);
148554405bcSnicm 
149554405bcSnicm 	va_start(ap, msg);
150554405bcSnicm 	log_vwrite(msg, ap, tmp);
1510222b1e4Snicm 	va_end(ap);
152554405bcSnicm 
15346b1c757Snicm 	exit(1);
154311827fbSnicm }
155311827fbSnicm 
156311827fbSnicm /* Log a critical error and die. */
15774d4b937Snicm __dead void
fatalx(const char * msg,...)1583baad57eSnicm fatalx(const char *msg, ...)
159311827fbSnicm {
160311827fbSnicm 	va_list	 ap;
161311827fbSnicm 
162311827fbSnicm 	va_start(ap, msg);
163554405bcSnicm 	log_vwrite(msg, ap, "fatal: ");
1640222b1e4Snicm 	va_end(ap);
165554405bcSnicm 
16646b1c757Snicm 	exit(1);
167311827fbSnicm }
168