]>
Commit | Line | Data |
---|---|---|
88840341 | 1 | /* |
88840341 RC |
2 | chronyd/chronyc - Programs for keeping computer clocks accurate. |
3 | ||
4 | ********************************************************************** | |
6672f045 | 5 | * Copyright (C) Richard P. Curnow 1997-2003 |
5dc86c23 | 6 | * Copyright (C) Miroslav Lichvar 2011-2014, 2018 |
88840341 RC |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of version 2 of the GNU General Public License as | |
10 | * published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License along | |
18 | * with this program; if not, write to the Free Software Foundation, Inc., | |
8e23110a | 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
88840341 RC |
20 | * |
21 | ********************************************************************** | |
22 | ||
23 | ======================================================================= | |
24 | ||
25 | Module to handle logging of diagnostic information | |
26 | */ | |
27 | ||
da2c8d90 ML |
28 | #include "config.h" |
29 | ||
88840341 RC |
30 | #include "sysincl.h" |
31 | ||
903fa247 ML |
32 | #include <syslog.h> |
33 | ||
e78e65ef | 34 | #include "conf.h" |
88840341 | 35 | #include "logging.h" |
9d35b5de | 36 | #include "util.h" |
88840341 | 37 | |
0dea8d97 | 38 | /* This is used by DEBUG_LOG macro */ |
1227873b | 39 | LOG_Severity log_min_severity = LOGS_INFO; |
0dea8d97 | 40 | |
88840341 RC |
41 | /* ================================================== */ |
42 | /* Flag indicating we have initialised */ | |
43 | static int initialised = 0; | |
44 | ||
d05e9fb2 | 45 | static FILE *file_log = NULL; |
fe4b661f | 46 | static int system_log = 0; |
88840341 | 47 | |
1d2a0856 ML |
48 | static int parent_fd = 0; |
49 | ||
e78e65ef ML |
50 | struct LogFile { |
51 | const char *name; | |
52 | const char *banner; | |
53 | FILE *file; | |
54 | unsigned long writes; | |
55 | }; | |
56 | ||
57 | static int n_filelogs = 0; | |
58 | ||
59 | /* Increase this when adding a new logfile */ | |
c386d117 | 60 | #define MAX_FILELOGS 6 |
e78e65ef ML |
61 | |
62 | static struct LogFile logfiles[MAX_FILELOGS]; | |
63 | ||
88840341 RC |
64 | /* ================================================== */ |
65 | /* Init function */ | |
66 | ||
67 | void | |
68 | LOG_Initialise(void) | |
69 | { | |
70 | initialised = 1; | |
d05e9fb2 | 71 | LOG_OpenFileLog(NULL); |
88840341 RC |
72 | } |
73 | ||
74 | /* ================================================== */ | |
75 | /* Fini function */ | |
76 | ||
77 | void | |
78 | LOG_Finalise(void) | |
79 | { | |
7b98443a | 80 | if (system_log) |
88840341 | 81 | closelog(); |
7b98443a ML |
82 | |
83 | if (file_log) | |
6cbeb107 | 84 | fclose(file_log); |
88840341 | 85 | |
e78e65ef ML |
86 | LOG_CycleLogFiles(); |
87 | ||
88840341 | 88 | initialised = 0; |
88840341 RC |
89 | } |
90 | ||
91 | /* ================================================== */ | |
92 | ||
cd7bfa25 | 93 | static void log_message(int fatal, LOG_Severity severity, const char *message) |
88840341 | 94 | { |
fe4b661f | 95 | if (system_log) { |
cd7bfa25 | 96 | int priority; |
88840341 | 97 | switch (severity) { |
4bbc5520 ML |
98 | case LOGS_DEBUG: |
99 | priority = LOG_DEBUG; | |
100 | break; | |
88840341 | 101 | case LOGS_INFO: |
cd7bfa25 | 102 | priority = LOG_INFO; |
88840341 RC |
103 | break; |
104 | case LOGS_WARN: | |
cd7bfa25 | 105 | priority = LOG_WARNING; |
88840341 RC |
106 | break; |
107 | case LOGS_ERR: | |
cd7bfa25 ML |
108 | priority = LOG_ERR; |
109 | break; | |
110 | case LOGS_FATAL: | |
111 | priority = LOG_CRIT; | |
88840341 | 112 | break; |
cd7bfa25 ML |
113 | default: |
114 | assert(0); | |
88840341 | 115 | } |
cd7bfa25 | 116 | syslog(priority, fatal ? "Fatal error : %s" : "%s", message); |
7b98443a | 117 | } else if (file_log) { |
6cbeb107 | 118 | fprintf(file_log, fatal ? "Fatal error : %s\n" : "%s\n", message); |
88840341 | 119 | } |
88840341 RC |
120 | } |
121 | ||
122 | /* ================================================== */ | |
123 | ||
7b2430fc ML |
124 | void LOG_Message(LOG_Severity severity, |
125 | #if DEBUG > 0 | |
f282856c | 126 | int line_number, const char *filename, const char *function_name, |
7b2430fc ML |
127 | #endif |
128 | const char *format, ...) | |
88840341 RC |
129 | { |
130 | char buf[2048]; | |
131 | va_list other_args; | |
cd7bfa25 | 132 | time_t t; |
63fe34e8 | 133 | struct tm *tm; |
88840341 | 134 | |
1227873b | 135 | if (!system_log && file_log && severity >= log_min_severity) { |
788e7fcd | 136 | /* Don't clutter up syslog with timestamps and internal debugging info */ |
88840341 | 137 | time(&t); |
63fe34e8 ML |
138 | tm = gmtime(&t); |
139 | if (tm) { | |
140 | strftime(buf, sizeof (buf), "%Y-%m-%dT%H:%M:%SZ", tm); | |
141 | fprintf(file_log, "%s ", buf); | |
142 | } | |
7b2430fc | 143 | #if DEBUG > 0 |
1227873b | 144 | if (log_min_severity <= LOGS_DEBUG) |
6cbeb107 | 145 | fprintf(file_log, "%s:%d:(%s) ", filename, line_number, function_name); |
7b2430fc | 146 | #endif |
88840341 | 147 | } |
cd7bfa25 ML |
148 | |
149 | va_start(other_args, format); | |
150 | vsnprintf(buf, sizeof(buf), format, other_args); | |
151 | va_end(other_args); | |
152 | ||
153 | switch (severity) { | |
4bbc5520 | 154 | case LOGS_DEBUG: |
cd7bfa25 ML |
155 | case LOGS_INFO: |
156 | case LOGS_WARN: | |
157 | case LOGS_ERR: | |
1227873b ML |
158 | if (severity >= log_min_severity) |
159 | log_message(0, severity, buf); | |
cd7bfa25 ML |
160 | break; |
161 | case LOGS_FATAL: | |
1227873b ML |
162 | if (severity >= log_min_severity) |
163 | log_message(1, severity, buf); | |
cd7bfa25 | 164 | |
7b98443a ML |
165 | /* Send the message also to the foreground process if it is |
166 | still running, or stderr if it is still open */ | |
167 | if (parent_fd > 0) { | |
168 | if (write(parent_fd, buf, strlen(buf) + 1) < 0) | |
169 | ; /* Not much we can do here */ | |
170 | } else if (system_log && parent_fd == 0) { | |
171 | system_log = 0; | |
172 | log_message(1, severity, buf); | |
cd7bfa25 | 173 | } |
f4c6a00b | 174 | exit(1); |
cd7bfa25 ML |
175 | break; |
176 | default: | |
177 | assert(0); | |
178 | } | |
88840341 RC |
179 | } |
180 | ||
6cbeb107 ML |
181 | /* ================================================== */ |
182 | ||
183 | void | |
184 | LOG_OpenFileLog(const char *log_file) | |
185 | { | |
186 | FILE *f; | |
187 | ||
eb8c9ad6 | 188 | if (log_file) { |
794cbfbb | 189 | f = UTI_OpenFile(NULL, log_file, NULL, 'A', 0640); |
eb8c9ad6 ML |
190 | } else { |
191 | f = stderr; | |
192 | } | |
6cbeb107 | 193 | |
d70df3da ML |
194 | /* Enable line buffering */ |
195 | setvbuf(f, NULL, _IOLBF, BUFSIZ); | |
196 | ||
68475366 ML |
197 | if (file_log && file_log != stderr) |
198 | fclose(file_log); | |
199 | ||
6cbeb107 ML |
200 | file_log = f; |
201 | } | |
202 | ||
203 | ||
88840341 RC |
204 | /* ================================================== */ |
205 | ||
206 | void | |
fe4b661f | 207 | LOG_OpenSystemLog(void) |
88840341 | 208 | { |
fe4b661f ML |
209 | system_log = 1; |
210 | openlog("chronyd", LOG_PID, LOG_DAEMON); | |
88840341 RC |
211 | } |
212 | ||
032ac800 ML |
213 | /* ================================================== */ |
214 | ||
1227873b | 215 | void LOG_SetMinSeverity(LOG_Severity severity) |
4bbc5520 | 216 | { |
c7223f4c ML |
217 | /* Don't print any debug messages in a non-debug build */ |
218 | log_min_severity = CLAMP(DEBUG > 0 ? LOGS_DEBUG : LOGS_INFO, severity, LOGS_FATAL); | |
4bbc5520 ML |
219 | } |
220 | ||
221 | /* ================================================== */ | |
222 | ||
1d2a0856 ML |
223 | void |
224 | LOG_SetParentFd(int fd) | |
225 | { | |
226 | parent_fd = fd; | |
7b98443a ML |
227 | if (file_log == stderr) |
228 | file_log = NULL; | |
1d2a0856 ML |
229 | } |
230 | ||
231 | /* ================================================== */ | |
232 | ||
233 | void | |
234 | LOG_CloseParentFd() | |
235 | { | |
236 | if (parent_fd > 0) | |
237 | close(parent_fd); | |
ed0ac6e3 | 238 | parent_fd = -1; |
1d2a0856 ML |
239 | } |
240 | ||
241 | /* ================================================== */ | |
242 | ||
e78e65ef ML |
243 | LOG_FileID |
244 | LOG_FileOpen(const char *name, const char *banner) | |
245 | { | |
246 | assert(n_filelogs < MAX_FILELOGS); | |
247 | ||
248 | logfiles[n_filelogs].name = name; | |
249 | logfiles[n_filelogs].banner = banner; | |
250 | logfiles[n_filelogs].file = NULL; | |
251 | logfiles[n_filelogs].writes = 0; | |
252 | ||
253 | return n_filelogs++; | |
254 | } | |
255 | ||
256 | /* ================================================== */ | |
257 | ||
258 | void | |
259 | LOG_FileWrite(LOG_FileID id, const char *format, ...) | |
260 | { | |
261 | va_list other_args; | |
7ab2c0e4 | 262 | int banner; |
e78e65ef ML |
263 | |
264 | if (id < 0 || id >= n_filelogs || !logfiles[id].name) | |
265 | return; | |
266 | ||
267 | if (!logfiles[id].file) { | |
e18903a6 | 268 | char *logdir = CNF_GetLogDir(); |
fb5d4f1d ML |
269 | |
270 | if (logdir[0] == '\0') { | |
f282856c | 271 | LOG(LOGS_WARN, "logdir not specified"); |
fb5d4f1d ML |
272 | logfiles[id].name = NULL; |
273 | return; | |
274 | } | |
e78e65ef | 275 | |
e18903a6 ML |
276 | logfiles[id].file = UTI_OpenFile(logdir, logfiles[id].name, ".log", 'a', 0644); |
277 | if (!logfiles[id].file) { | |
278 | /* Disable the log */ | |
e78e65ef ML |
279 | logfiles[id].name = NULL; |
280 | return; | |
281 | } | |
282 | } | |
283 | ||
7ab2c0e4 ML |
284 | banner = CNF_GetLogBanner(); |
285 | if (banner && logfiles[id].writes++ % banner == 0) { | |
e78e65ef ML |
286 | char bannerline[256]; |
287 | int i, bannerlen; | |
288 | ||
96771d68 | 289 | bannerlen = MIN(strlen(logfiles[id].banner), sizeof (bannerline) - 1); |
e78e65ef ML |
290 | |
291 | for (i = 0; i < bannerlen; i++) | |
292 | bannerline[i] = '='; | |
293 | bannerline[i] = '\0'; | |
294 | ||
295 | fprintf(logfiles[id].file, "%s\n", bannerline); | |
296 | fprintf(logfiles[id].file, "%s\n", logfiles[id].banner); | |
297 | fprintf(logfiles[id].file, "%s\n", bannerline); | |
298 | } | |
299 | ||
300 | va_start(other_args, format); | |
301 | vfprintf(logfiles[id].file, format, other_args); | |
302 | va_end(other_args); | |
303 | fprintf(logfiles[id].file, "\n"); | |
304 | ||
305 | fflush(logfiles[id].file); | |
306 | } | |
307 | ||
308 | /* ================================================== */ | |
309 | ||
e78e65ef ML |
310 | void |
311 | LOG_CycleLogFiles(void) | |
312 | { | |
313 | LOG_FileID i; | |
314 | ||
315 | for (i = 0; i < n_filelogs; i++) { | |
316 | if (logfiles[i].file) | |
317 | fclose(logfiles[i].file); | |
318 | logfiles[i].file = NULL; | |
319 | logfiles[i].writes = 0; | |
320 | } | |
321 | } | |
322 | ||
323 | /* ================================================== */ |