if (log_to_file) {
if (msyslog_include_timestamp)
fprintf(syslog_file, "%s ", human_time);
fprintf(syslog_file, "%s[%d]: %s%s", prog, pid, msg,
nl_or_empty);
fflush(syslog_file);
}
}
int
mvsnprintf(
char * buf,
size_t bufsiz,
const char * fmt,
va_list ap
)
{
#ifndef VSNPRINTF_PERCENT_M
char fmtbuf[256];
#endif
int errval;
/*
* Save the error value as soon as possible
*/
#ifdef SYS_WINNT
errval = GetLastError();
if (NO_ERROR == errval)
#endif /* SYS_WINNT */
errval = errno;
int
mvfprintf(
FILE * fp,
const char * fmt,
va_list ap
)
{
#ifndef VSNPRINTF_PERCENT_M
char fmtbuf[256];
#endif
int errval;
/*
* Save the error value as soon as possible
*/
#ifdef SYS_WINNT
errval = GetLastError();
if (NO_ERROR == errval)
#endif /* SYS_WINNT */
errval = errno;
/*
* Initialize the logging
*
* Called once per process, including forked children.
*/
void
init_logging(
const char * name,
u_int32 def_syslogmask,
int is_daemon
)
{
static int was_daemon;
char * cp;
const char * pname;
/*
* ntpd defaults to only logging sync-category events, when
* NLOG() is used to conditionalize. Other libntp clients
* leave it alone so that all NLOG() conditionals will fire.
* This presumes all bits lit in ntp_syslogmask can't be
* configured via logconfig and all lit is thereby a sentinel
* that ntp_syslogmask is still at its default from libntp,
* keeping in mind this function is called in forked children
* where it has already been called in the parent earlier.
* Forked children pass 0 for def_syslogmask.
*/
if (INIT_NTP_SYSLOGMASK == ntp_syslogmask &&
0 != def_syslogmask)
ntp_syslogmask = def_syslogmask; /* set more via logconfig */
/*
* Logging. This may actually work on the gizmo board. Find a name
* to log with by using the basename
*/
cp = strrchr(name, DIR_SEP);
if (NULL == cp)
pname = name;
else
pname = 1 + cp; /* skip DIR_SEP */
progname = estrdup(pname);
#ifdef SYS_WINNT /* strip ".exe" */
cp = strrchr(progname, '.');
if (NULL != cp && !strcasecmp(cp, ".exe"))
*cp = '\0';
#endif
/*
* change_logfile()
*
* Used to change from syslog to a logfile, or from one logfile to
* another, and to reopen logfiles after forking. On systems where
* ntpd forks, deals with converting relative logfile paths to
* absolute (root-based) because we reopen logfiles after the current
* directory has changed.
*/
int
change_logfile(
const char * fname,
int leave_crumbs
)
{
FILE * new_file;
const char * log_fname;
char * abs_fname;
#if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS)
char curdir[512];
size_t cd_octets;
size_t octets;
#endif /* POSIX */
REQUIRE(fname != NULL);
log_fname = fname;
/*
* In a forked child of a parent which is logging to a file
* instead of syslog, syslog_file will be NULL and both
* syslog_fname and syslog_abs_fname will be non-NULL.
* If we are given the same filename previously opened
* and it's still open, there's nothing to do here.
*/
if (syslog_file != NULL && syslog_fname != NULL &&
0 == strcmp(syslog_fname, log_fname))
return 0;
if (NULL == new_file) {
free(abs_fname);
return -1;
}
/* leave a pointer in the old log */
if (leave_crumbs && (syslogit || log_fname != syslog_abs_fname))
msyslog(LOG_NOTICE, "switching logging to file %s",
abs_fname);
/*
* setup_logfile()
*
* Redirect logging to a file if requested with -l/--logfile or via
* ntp.conf logfile directive.
*
* This routine is invoked three different times in the sequence of a
* typical daemon ntpd with DNS lookups to do. First it is invoked in
* the original ntpd process, then again in the daemon after closing
* all descriptors. In both of those cases, ntp.conf has not been
* processed, so only -l/--logfile will trigger logfile redirection in
* those invocations. Finally, if DNS names are resolved, the worker
* child invokes this routine after its fork and close of all
* descriptors. In this case, ntp.conf has been processed and any
* "logfile" directive needs to be honored in the child as well.
*/
void
setup_logfile(
const char * name
)
{
if (NULL == syslog_fname && NULL != name) {
if (-1 == change_logfile(name, TRUE))
msyslog(LOG_ERR, "Cannot open log file %s, %m",
name);
return ;
}
if (NULL == syslog_fname)
return;
/*
* Helper for unit tests, where stdout + stderr are piped to the same
* stream. This works moderately reliably only if both streams are
* unbuffered or line buffered. Unfortunately stdout can be fully
* buffered on pipes or files...
*/
int
change_iobufs(
int how
)
{
int retv = 0;
# ifdef HAVE_SETVBUF
int mode;
switch (how) {
case 0 : mode = _IONBF; break; /* no buffering */
case 1 : mode = _IOLBF; break; /* line buffering */
case 2 : mode = _IOFBF; break; /* full buffering */
default: mode = _IOLBF; break; /* line buffering */
}