2 chronyd/chronyc - Programs for keeping computer clocks accurate.
4 **********************************************************************
5 * Copyright (C) Richard P. Curnow 1997-2003
6 * Copyright (C) Miroslav Lichvar 2011-2014, 2018
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.
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.
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.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 **********************************************************************
23 =======================================================================
25 Module to handle logging of diagnostic information
38 /* This is used by DEBUG_LOG macro */
39 LOG_Severity log_min_severity
= LOGS_INFO
;
41 /* ================================================== */
42 /* Flag indicating we have initialised */
43 static int initialised
= 0;
45 static FILE *file_log
= NULL
;
46 static int system_log
= 0;
48 static int parent_fd
= 0;
57 static int n_filelogs
= 0;
59 /* Increase this when adding a new logfile */
60 #define MAX_FILELOGS 6
62 static struct LogFile logfiles
[MAX_FILELOGS
];
64 /* ================================================== */
71 LOG_OpenFileLog(NULL
);
74 /* ================================================== */
91 /* ================================================== */
93 static void log_message(int fatal
, LOG_Severity severity
, const char *message
)
105 priority
= LOG_WARNING
;
116 syslog(priority
, fatal
? "Fatal error : %s" : "%s", message
);
117 } else if (file_log
) {
118 fprintf(file_log
, fatal
? "Fatal error : %s\n" : "%s\n", message
);
122 /* ================================================== */
124 void LOG_Message(LOG_Severity severity
,
126 int line_number
, const char *filename
, const char *function_name
,
128 const char *format
, ...)
135 if (!system_log
&& file_log
&& severity
>= log_min_severity
) {
136 /* Don't clutter up syslog with timestamps and internal debugging info */
140 strftime(buf
, sizeof (buf
), "%Y-%m-%dT%H:%M:%SZ", tm
);
141 fprintf(file_log
, "%s ", buf
);
144 if (log_min_severity
<= LOGS_DEBUG
)
145 fprintf(file_log
, "%s:%d:(%s) ", filename
, line_number
, function_name
);
149 va_start(other_args
, format
);
150 vsnprintf(buf
, sizeof(buf
), format
, other_args
);
158 if (severity
>= log_min_severity
)
159 log_message(0, severity
, buf
);
162 if (severity
>= log_min_severity
)
163 log_message(1, severity
, buf
);
165 /* Send the message also to the foreground process if it is
166 still running, or stderr if it is still open */
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) {
172 log_message(1, severity
, buf
);
181 /* ================================================== */
184 LOG_OpenFileLog(const char *log_file
)
189 f
= UTI_OpenFile(NULL
, log_file
, NULL
, 'A', 0640);
194 /* Enable line buffering */
195 setvbuf(f
, NULL
, _IOLBF
, BUFSIZ
);
197 if (file_log
&& file_log
!= stderr
)
204 /* ================================================== */
207 LOG_OpenSystemLog(void)
210 openlog("chronyd", LOG_PID
, LOG_DAEMON
);
213 /* ================================================== */
215 void LOG_SetMinSeverity(LOG_Severity severity
)
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
);
221 /* ================================================== */
224 LOG_SetParentFd(int fd
)
227 if (file_log
== stderr
)
231 /* ================================================== */
241 /* ================================================== */
244 LOG_FileOpen(const char *name
, const char *banner
)
246 assert(n_filelogs
< MAX_FILELOGS
);
248 logfiles
[n_filelogs
].name
= name
;
249 logfiles
[n_filelogs
].banner
= banner
;
250 logfiles
[n_filelogs
].file
= NULL
;
251 logfiles
[n_filelogs
].writes
= 0;
256 /* ================================================== */
259 LOG_FileWrite(LOG_FileID id
, const char *format
, ...)
264 if (id
< 0 || id
>= n_filelogs
|| !logfiles
[id
].name
)
267 if (!logfiles
[id
].file
) {
268 char *logdir
= CNF_GetLogDir();
270 if (logdir
[0] == '\0') {
271 LOG(LOGS_WARN
, "logdir not specified");
272 logfiles
[id
].name
= NULL
;
276 logfiles
[id
].file
= UTI_OpenFile(logdir
, logfiles
[id
].name
, ".log", 'a', 0644);
277 if (!logfiles
[id
].file
) {
278 /* Disable the log */
279 logfiles
[id
].name
= NULL
;
284 banner
= CNF_GetLogBanner();
285 if (banner
&& logfiles
[id
].writes
++ % banner
== 0) {
286 char bannerline
[256];
289 bannerlen
= MIN(strlen(logfiles
[id
].banner
), sizeof (bannerline
) - 1);
291 for (i
= 0; i
< bannerlen
; i
++)
293 bannerline
[i
] = '\0';
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
);
300 va_start(other_args
, format
);
301 vfprintf(logfiles
[id
].file
, format
, other_args
);
303 fprintf(logfiles
[id
].file
, "\n");
305 fflush(logfiles
[id
].file
);
308 /* ================================================== */
311 LOG_CycleLogFiles(void)
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;
323 /* ================================================== */