2 * msyslog - either send a message to the terminal or print it on
5 * Converted to use varargs, much better ... jks
12 #include <sys/types.h>
18 #include "ntp_string.h"
20 #include "ntp_debug.h"
21 #include "ntp_syslog.h"
25 # include "..\ports\winnt\libntp\messages.h"
30 int msyslog_term = FALSE; /* duplicate to stdout/err */
31 int msyslog_term_pid = TRUE;
32 int msyslog_include_timestamp = TRUE;
35 char * syslog_abs_fname;
37 /* libntp default ntp_syslogmask is all bits lit */
38 #define INIT_NTP_SYSLOGMASK ~(u_int32)0
39 u_int32 ntp_syslogmask = INIT_NTP_SYSLOGMASK;
41 extern char * progname;
43 /* Declare the local functions */
44 void addto_syslog (int, const char *);
45 #ifndef VSNPRINTF_PERCENT_M
46 void format_errmsg (char *, size_t, const char *, int);
48 /* format_errmsg() is under #ifndef VSNPRINTF_PERCENT_M above */
65 while ((c = *f++) != '\0' && n < (nfmt + lennfmt - 1)) {
70 if ((c = *f++) != 'm') {
77 errno_to_str(errval, errmsg, sizeof(errmsg));
80 /* Make sure we have enough space for the error message */
81 if ((n + len) < (nfmt + lennfmt - 1)) {
82 memcpy(n, errmsg, len);
88 #endif /* VSNPRINTF_PERCENT_M */
92 * errno_to_str() - a thread-safe strerror() replacement.
93 * Hides the varied signatures of strerror_r().
94 * For Windows, we have:
95 * #define errno_to_str isc_strerror
105 # if defined(STRERROR_R_CHAR_P) || !HAVE_DECL_STRERROR_R
109 # ifdef STRERROR_R_CHAR_P
110 pstatic = strerror_r(err, buf, bufsiz);
112 pstatic = strerror(err);
114 if (NULL == pstatic && '\0' == buf[0])
115 snprintf(buf, bufsiz, "%s(%d): errno %d",
116 # ifdef STRERROR_R_CHAR_P
122 /* protect against believing an int return is a pointer */
123 else if (pstatic != buf && pstatic > (char *)bufsiz)
124 strlcpy(buf, pstatic, bufsiz);
128 rc = strerror_r(err, buf, bufsiz);
130 snprintf(buf, bufsiz, "strerror_r(%d): errno %d",
134 #endif /* errno_to_str */
139 * This routine adds the contents of a buffer to the syslog or an
140 * application-specific logfile.
148 static char * prevcall_progname;
150 const char nl[] = "\n";
151 const char empty[] = "";
156 const char * nl_or_empty;
157 const char * human_time;
159 /* setup program basename static var prog if needed */
160 if (progname != prevcall_progname) {
161 prevcall_progname = progname;
162 prog = strrchr(progname, DIR_SEP);
169 log_to_term = msyslog_term;
171 #if !defined(VMS) && !defined(SYS_VXWORKS)
173 syslog(level, "%s", msg);
176 if (syslog_file != NULL)
184 if (!(log_to_file || log_to_term))
187 /* syslog() adds the timestamp, name, and pid */
188 if (msyslog_include_timestamp)
189 human_time = humanlogtime();
190 else /* suppress gcc pot. uninit. warning */
192 if (msyslog_term_pid || log_to_file)
194 else /* suppress gcc pot. uninit. warning */
197 /* syslog() adds trailing \n if not present */
198 if ('\n' != msg[strlen(msg) - 1])
204 term_file = (level <= LOG_ERR)
207 if (msyslog_include_timestamp)
208 fprintf(term_file, "%s ", human_time);
209 if (msyslog_term_pid)
210 fprintf(term_file, "%s[%d]: ", prog, pid);
211 fprintf(term_file, "%s%s", msg, nl_or_empty);
216 if (msyslog_include_timestamp)
217 fprintf(syslog_file, "%s ", human_time);
218 fprintf(syslog_file, "%s[%d]: %s%s", prog, pid, msg,
233 #ifndef VSNPRINTF_PERCENT_M
236 const char * nfmt = fmt;
241 * Save the error value as soon as possible
244 errval = GetLastError();
245 if (NO_ERROR == errval)
246 #endif /* SYS_WINNT */
249 #ifndef VSNPRINTF_PERCENT_M
250 format_errmsg(nfmt, sizeof(nfmt), fmt, errval);
254 return vsnprintf(buf, bufsiz, nfmt, ap);
265 #ifndef VSNPRINTF_PERCENT_M
268 const char * nfmt = fmt;
273 * Save the error value as soon as possible
276 errval = GetLastError();
277 if (NO_ERROR == errval)
278 #endif /* SYS_WINNT */
281 #ifndef VSNPRINTF_PERCENT_M
282 format_errmsg(nfmt, sizeof(nfmt), fmt, errval);
286 return vfprintf(fp, nfmt, ap);
301 rc = mvfprintf(fp, fmt, ap);
318 rc = mvfprintf(stdout, fmt, ap);
337 rc = mvsnprintf(buf, bufsiz, fmt, ap);
355 mvsnprintf(buf, sizeof(buf), fmt, ap);
357 addto_syslog(level, buf);
362 * Initialize the logging
364 * Called once per process, including forked children.
369 u_int32 def_syslogmask,
373 static int was_daemon;
378 * ntpd defaults to only logging sync-category events, when
379 * NLOG() is used to conditionalize. Other libntp clients
380 * leave it alone so that all NLOG() conditionals will fire.
381 * This presumes all bits lit in ntp_syslogmask can't be
382 * configured via logconfig and all lit is thereby a sentinel
383 * that ntp_syslogmask is still at its default from libntp,
384 * keeping in mind this function is called in forked children
385 * where it has already been called in the parent earlier.
386 * Forked children pass 0 for def_syslogmask.
388 if (INIT_NTP_SYSLOGMASK == ntp_syslogmask &&
390 ntp_syslogmask = def_syslogmask; /* set more via logconfig */
393 * Logging. This may actually work on the gizmo board. Find a name
394 * to log with by using the basename
396 cp = strrchr(name, DIR_SEP);
400 pname = 1 + cp; /* skip DIR_SEP */
401 progname = estrdup(pname);
402 #ifdef SYS_WINNT /* strip ".exe" */
403 cp = strrchr(progname, '.');
404 if (NULL != cp && !strcasecmp(cp, ".exe"))
405 progname[cp - progname] = '\0';
413 openlog(progname, LOG_PID);
414 # else /* LOG_DAEMON */
417 # define LOG_NTP LOG_DAEMON
419 openlog(progname, LOG_PID | LOG_NDELAY, (was_daemon)
424 setlogmask(LOG_UPTO(LOG_DEBUG));
427 setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
428 # endif /* LOG_DAEMON */
436 * Used to change from syslog to a logfile, or from one logfile to
437 * another, and to reopen logfiles after forking. On systems where
438 * ntpd forks, deals with converting relative logfile paths to
439 * absolute (root-based) because we reopen logfiles after the current
440 * directory has changed.
449 const char * log_fname;
451 #if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS)
457 NTP_REQUIRE(fname != NULL);
461 * In a forked child of a parent which is logging to a file
462 * instead of syslog, syslog_file will be NULL and both
463 * syslog_fname and syslog_abs_fname will be non-NULL.
464 * If we are given the same filename previously opened
465 * and it's still open, there's nothing to do here.
467 if (syslog_file != NULL && syslog_fname != NULL &&
468 0 == strcmp(syslog_fname, log_fname))
471 if (0 == strcmp(log_fname, "stderr")) {
473 abs_fname = estrdup(log_fname);
474 } else if (0 == strcmp(log_fname, "stdout")) {
476 abs_fname = estrdup(log_fname);
478 if (syslog_fname != NULL &&
479 0 == strcmp(log_fname, syslog_fname))
480 log_fname = syslog_abs_fname;
481 #if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS)
482 if (log_fname != syslog_abs_fname &&
483 DIR_SEP != log_fname[0] &&
484 0 != strcmp(log_fname, "stderr") &&
485 0 != strcmp(log_fname, "stdout") &&
486 NULL != getcwd(curdir, sizeof(curdir))) {
487 cd_octets = strlen(curdir);
488 /* trim any trailing '/' */
490 DIR_SEP == curdir[cd_octets - 1])
493 octets += 1; /* separator '/' */
494 octets += strlen(log_fname);
495 octets += 1; /* NUL terminator */
496 abs_fname = emalloc(octets);
497 snprintf(abs_fname, octets, "%.*s%c%s",
498 (int)cd_octets, curdir, DIR_SEP,
502 abs_fname = estrdup(log_fname);
503 TRACE(1, ("attempting to open log %s\n", abs_fname));
504 new_file = fopen(abs_fname, "a");
507 if (NULL == new_file) {
512 /* leave a pointer in the old log */
513 if (leave_crumbs && (syslogit || log_fname != syslog_abs_fname))
514 msyslog(LOG_NOTICE, "switching logging to file %s",
517 if (syslog_file != NULL &&
518 syslog_file != stderr && syslog_file != stdout &&
519 fileno(syslog_file) != fileno(new_file))
521 syslog_file = new_file;
522 if (log_fname == syslog_abs_fname) {
525 if (syslog_abs_fname != NULL &&
526 syslog_abs_fname != syslog_fname)
527 free(syslog_abs_fname);
528 if (syslog_fname != NULL)
530 syslog_fname = estrdup(log_fname);
531 syslog_abs_fname = abs_fname;
542 * Redirect logging to a file if requested with -l/--logfile or via
543 * ntp.conf logfile directive.
545 * This routine is invoked three different times in the sequence of a
546 * typical daemon ntpd with DNS lookups to do. First it is invoked in
547 * the original ntpd process, then again in the daemon after closing
548 * all descriptors. In both of those cases, ntp.conf has not been
549 * processed, so only -l/--logfile will trigger logfile redirection in
550 * those invocations. Finally, if DNS names are resolved, the worker
551 * child invokes this routine after its fork and close of all
552 * descriptors. In this case, ntp.conf has been processed and any
553 * "logfile" directive needs to be honored in the child as well.
560 if (NULL == syslog_fname && NULL != name) {
561 if (-1 == change_logfile(name, TRUE))
562 msyslog(LOG_ERR, "Cannot open log file %s, %m",
566 if (NULL == syslog_fname)
569 if (-1 == change_logfile(syslog_fname, FALSE))
570 msyslog(LOG_ERR, "Cannot reopen log file %s, %m",