Merge branch 'obsd-master'
[tmux.git] / log.c
blob0e0d1d1a1ca4b9767620457b076c889aac1e178b
1 /* $OpenBSD$ */
3 /*
4 * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
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 <unistd.h>
27 #include "tmux.h"
29 static FILE *log_file;
30 static int log_level;
32 /* Log callback for libevent. */
33 static void
34 log_event_cb(__unused int severity, const char *msg)
36 log_debug("%s", msg);
39 /* Increment log level. */
40 void
41 log_add_level(void)
43 log_level++;
46 /* Get log level. */
47 int
48 log_get_level(void)
50 return (log_level);
53 /* Open logging to file. */
54 void
55 log_open(const char *name)
57 char *path;
59 if (log_level == 0)
60 return;
61 log_close();
63 xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid());
64 log_file = fopen(path, "a");
65 free(path);
66 if (log_file == NULL)
67 return;
69 setvbuf(log_file, NULL, _IOLBF, 0);
70 event_set_log_callback(log_event_cb);
73 /* Toggle logging. */
74 void
75 log_toggle(const char *name)
77 if (log_level == 0) {
78 log_level = 1;
79 log_open(name);
80 log_debug("log opened");
81 } else {
82 log_debug("log closed");
83 log_level = 0;
84 log_close();
88 /* Close logging. */
89 void
90 log_close(void)
92 if (log_file != NULL)
93 fclose(log_file);
94 log_file = NULL;
96 event_set_log_callback(NULL);
99 /* Write a log message. */
100 static void printflike(1, 0)
101 log_vwrite(const char *msg, va_list ap, const char *prefix)
103 char *s, *out;
104 struct timeval tv;
106 if (log_file == NULL)
107 return;
109 if (vasprintf(&s, msg, ap) == -1)
110 return;
111 if (stravis(&out, s, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1) {
112 free(s);
113 return;
115 free(s);
117 gettimeofday(&tv, NULL);
118 if (fprintf(log_file, "%lld.%06d %s%s\n", (long long)tv.tv_sec,
119 (int)tv.tv_usec, prefix, out) != -1)
120 fflush(log_file);
121 free(out);
124 /* Log a debug message. */
125 void
126 log_debug(const char *msg, ...)
128 va_list ap;
130 if (log_file == NULL)
131 return;
133 va_start(ap, msg);
134 log_vwrite(msg, ap, "");
135 va_end(ap);
138 /* Log a critical error with error string and die. */
139 __dead void
140 fatal(const char *msg, ...)
142 char tmp[256];
143 va_list ap;
145 if (snprintf(tmp, sizeof tmp, "fatal: %s: ", strerror(errno)) < 0)
146 exit(1);
148 va_start(ap, msg);
149 log_vwrite(msg, ap, tmp);
150 va_end(ap);
152 exit(1);
155 /* Log a critical error and die. */
156 __dead void
157 fatalx(const char *msg, ...)
159 va_list ap;
161 va_start(ap, msg);
162 log_vwrite(msg, ap, "fatal: ");
163 va_end(ap);
165 exit(1);