Line | Count | Source (jump to first uncovered line) |
1 | | /* $OpenBSD$ */ |
2 | | |
3 | | /* |
4 | | * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com> |
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 <unistd.h> |
26 | | |
27 | | #include "tmux.h" |
28 | | |
29 | | static FILE *log_file; |
30 | | static int log_level; |
31 | | |
32 | | /* Log callback for libevent. */ |
33 | | static void |
34 | | log_event_cb(__unused int severity, const char *msg) |
35 | 0 | { |
36 | 0 | log_debug("%s", msg); |
37 | 0 | } |
38 | | |
39 | | /* Increment log level. */ |
40 | | void |
41 | | log_add_level(void) |
42 | 0 | { |
43 | 0 | log_level++; |
44 | 0 | } |
45 | | |
46 | | /* Get log level. */ |
47 | | int |
48 | | log_get_level(void) |
49 | 20.2k | { |
50 | 20.2k | return (log_level); |
51 | 20.2k | } |
52 | | |
53 | | /* Open logging to file. */ |
54 | | void |
55 | | log_open(const char *name) |
56 | 0 | { |
57 | 0 | char *path; |
58 | |
|
59 | 0 | if (log_level == 0) |
60 | 0 | return; |
61 | 0 | log_close(); |
62 | |
|
63 | 0 | xasprintf(&path, "tmux-%s-%ld.log", name, (long)getpid()); |
64 | 0 | log_file = fopen(path, "a"); |
65 | 0 | free(path); |
66 | 0 | if (log_file == NULL) |
67 | 0 | return; |
68 | | |
69 | 0 | setvbuf(log_file, NULL, _IOLBF, 0); |
70 | 0 | event_set_log_callback(log_event_cb); |
71 | 0 | } |
72 | | |
73 | | /* Toggle logging. */ |
74 | | void |
75 | | log_toggle(const char *name) |
76 | 0 | { |
77 | 0 | if (log_level == 0) { |
78 | 0 | log_level = 1; |
79 | 0 | log_open(name); |
80 | 0 | log_debug("log opened"); |
81 | 0 | } else { |
82 | 0 | log_debug("log closed"); |
83 | 0 | log_level = 0; |
84 | 0 | log_close(); |
85 | 0 | } |
86 | 0 | } |
87 | | |
88 | | /* Close logging. */ |
89 | | void |
90 | | log_close(void) |
91 | 0 | { |
92 | 0 | if (log_file != NULL) |
93 | 0 | fclose(log_file); |
94 | 0 | log_file = NULL; |
95 | |
|
96 | 0 | event_set_log_callback(NULL); |
97 | 0 | } |
98 | | |
99 | | /* Write a log message. */ |
100 | | static void printflike(1, 0) |
101 | | log_vwrite(const char *msg, va_list ap, const char *prefix) |
102 | 0 | { |
103 | 0 | char *s, *out; |
104 | 0 | struct timeval tv; |
105 | |
|
106 | 0 | if (log_file == NULL) |
107 | 0 | return; |
108 | | |
109 | 0 | if (vasprintf(&s, msg, ap) == -1) |
110 | 0 | return; |
111 | 0 | if (stravis(&out, s, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL) == -1) { |
112 | 0 | free(s); |
113 | 0 | return; |
114 | 0 | } |
115 | 0 | free(s); |
116 | |
|
117 | 0 | gettimeofday(&tv, NULL); |
118 | 0 | if (fprintf(log_file, "%lld.%06d %s%s\n", (long long)tv.tv_sec, |
119 | 0 | (int)tv.tv_usec, prefix, out) != -1) |
120 | 0 | fflush(log_file); |
121 | 0 | free(out); |
122 | 0 | } |
123 | | |
124 | | /* Log a debug message. */ |
125 | | void |
126 | | log_debug(const char *msg, ...) |
127 | 1.32M | { |
128 | 1.32M | va_list ap; |
129 | | |
130 | 1.32M | if (log_file == NULL) |
131 | 1.32M | return; |
132 | | |
133 | 0 | va_start(ap, msg); |
134 | 0 | log_vwrite(msg, ap, ""); |
135 | 0 | va_end(ap); |
136 | 0 | } |
137 | | |
138 | | /* Log a critical error with error string and die. */ |
139 | | __dead void |
140 | | fatal(const char *msg, ...) |
141 | 0 | { |
142 | 0 | char tmp[256]; |
143 | 0 | va_list ap; |
144 | |
|
145 | 0 | if (snprintf(tmp, sizeof tmp, "fatal: %s: ", strerror(errno)) < 0) |
146 | 0 | exit(1); |
147 | | |
148 | 0 | va_start(ap, msg); |
149 | 0 | log_vwrite(msg, ap, tmp); |
150 | 0 | va_end(ap); |
151 | |
|
152 | 0 | exit(1); |
153 | 0 | } |
154 | | |
155 | | /* Log a critical error and die. */ |
156 | | __dead void |
157 | | fatalx(const char *msg, ...) |
158 | 0 | { |
159 | 0 | va_list ap; |
160 | |
|
161 | 0 | va_start(ap, msg); |
162 | 0 | log_vwrite(msg, ap, "fatal: "); |
163 | 0 | va_end(ap); |
164 | |
|
165 | 0 | exit(1); |
166 | 0 | } |