Restore previous behaviour or writing to stdout if available.
[tmux.git] / log.c
blobede6e2577b11ad9982ba6eb0e0777770aadf3e8c
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>
26 #include <vis.h>
28 #include "tmux.h"
30 static FILE *log_file;
31 static int log_level;
33 /* Log callback for libevent. */
34 static void
35 log_event_cb(__unused int severity, const char *msg)
37 log_debug("%s", msg);
40 /* Increment log level. */
41 void
42 log_add_level(void)
44 log_level++;
47 /* Get log level. */
48 int
49 log_get_level(void)
51 return (log_level);
54 /* Open logging to file. */
55 void
56 log_open(const char *name)
58 char *path;
60 if (log_level == 0)
61 return;
62 log_close();
64 xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid());
65 log_file = fopen(path, "a");
66 free(path);
67 if (log_file == NULL)
68 return;
70 setvbuf(log_file, NULL, _IOLBF, 0);
71 event_set_log_callback(log_event_cb);
74 /* Toggle logging. */
75 void
76 log_toggle(const char *name)
78 if (log_level == 0) {
79 log_level = 1;
80 log_open(name);
81 log_debug("log opened");
82 } else {
83 log_debug("log closed");
84 log_level = 0;
85 log_close();
89 /* Close logging. */
90 void
91 log_close(void)
93 if (log_file != NULL)
94 fclose(log_file);
95 log_file = NULL;
97 event_set_log_callback(NULL);
100 /* Write a log message. */
101 static void printflike(1, 0)
102 log_vwrite(const char *msg, va_list ap, const char *prefix)
104 char *s, *out;
105 struct timeval tv;
107 if (log_file == NULL)
108 return;
110 if (vasprintf(&s, msg, ap) == -1)
111 return;
112 if (stravis(&out, s, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1) {
113 free(s);
114 return;
116 free(s);
118 gettimeofday(&tv, NULL);
119 if (fprintf(log_file, "%lld.%06d %s%s\n", (long long)tv.tv_sec,
120 (int)tv.tv_usec, prefix, out) != -1)
121 fflush(log_file);
122 free(out);
125 /* Log a debug message. */
126 void
127 log_debug(const char *msg, ...)
129 va_list ap;
131 if (log_file == NULL)
132 return;
134 va_start(ap, msg);
135 log_vwrite(msg, ap, "");
136 va_end(ap);
139 /* Log a critical error with error string and die. */
140 __dead void
141 fatal(const char *msg, ...)
143 char tmp[256];
144 va_list ap;
146 if (snprintf(tmp, sizeof tmp, "fatal: %s: ", strerror(errno)) < 0)
147 exit(1);
149 va_start(ap, msg);
150 log_vwrite(msg, ap, tmp);
151 va_end(ap);
153 exit(1);
156 /* Log a critical error and die. */
157 __dead void
158 fatalx(const char *msg, ...)
160 va_list ap;
162 va_start(ap, msg);
163 log_vwrite(msg, ap, "fatal: ");
164 va_end(ap);
166 exit(1);