#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <sys/types.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <stdio.h>
#include "ntp_string.h"
#include "ntp.h"
#include "ntp_debug.h"
#include "ntp_syslog.h"
#ifdef SYS_WINNT
# include <stdarg.h>
# include "..\ports\winnt\libntp\messages.h"
#endif
int syslogit = TRUE;
int msyslog_term = FALSE;
int msyslog_term_pid = TRUE;
int msyslog_include_timestamp = TRUE;
FILE * syslog_file;
char * syslog_fname;
char * syslog_abs_fname;
#define INIT_NTP_SYSLOGMASK ~(u_int32)0
u_int32 ntp_syslogmask = INIT_NTP_SYSLOGMASK;
extern char const * progname;
void addto_syslog (int, const char *);
#ifndef VSNPRINTF_PERCENT_M
void format_errmsg (char *, size_t, const char *, int);
void
format_errmsg(
char * nfmt,
size_t lennfmt,
const char * fmt,
int errval
)
{
char errmsg[256];
char c;
char *n;
const char *f;
size_t len;
n = nfmt;
f = fmt;
while ((c = *f++) != '\0' && n < (nfmt + lennfmt - 1)) {
if (c != '%') {
*n++ = c;
continue;
}
if ((c = *f++) != 'm') {
*n++ = '%';
if ('\0' == c)
break;
*n++ = c;
continue;
}
errno_to_str(errval, errmsg, sizeof(errmsg));
len = strlen(errmsg);
if ((n + len) < (nfmt + lennfmt - 1)) {
memcpy(n, errmsg, len);
n += len;
}
}
*n = '\0';
}
#endif
#ifndef errno_to_str
void
errno_to_str(
int err,
char * buf,
size_t bufsiz
)
{
# if defined(STRERROR_R_CHAR_P) || !HAVE_DECL_STRERROR_R
char * pstatic;
buf[0] = '\0';
# ifdef STRERROR_R_CHAR_P
pstatic = strerror_r(err, buf, bufsiz);
# else
pstatic = strerror(err);
# endif
if (NULL == pstatic && '\0' == buf[0])
snprintf(buf, bufsiz, "%s(%d): errno %d",
# ifdef STRERROR_R_CHAR_P
"strerror_r",
# else
"strerror",
# endif
err, errno);
else if (pstatic != buf && pstatic > (char *)bufsiz)
strlcpy(buf, pstatic, bufsiz);
# else
int rc;
rc = strerror_r(err, buf, bufsiz);
if (rc < 0)
snprintf(buf, bufsiz, "strerror_r(%d): errno %d",
err, errno);
# endif
}
#endif
void
addto_syslog(
int level,
const char * msg
)
{
static char const * prevcall_progname;
static char const * prog;
const char nl[] = "\n";
const char empty[] = "";
FILE * term_file;
int log_to_term;
int log_to_file;
int pid;
const char * nl_or_empty;
const char * human_time;
if (progname != prevcall_progname) {
prevcall_progname = progname;
prog = strrchr(progname, DIR_SEP);
if (prog != NULL)
prog++;
else
prog = progname;
}
log_to_term = msyslog_term;
log_to_file = FALSE;
#if !defined(VMS) && !defined(SYS_VXWORKS)
if (syslogit)
syslog(level, "%s", msg);
else
#endif
if (syslog_file != NULL)
log_to_file = TRUE;
else
log_to_term = TRUE;
#if DEBUG
if (debug > 0)
log_to_term = TRUE;
#endif
if (!(log_to_file || log_to_term))
return;
if (msyslog_include_timestamp)
human_time = humanlogtime();
else
human_time = NULL;
if (msyslog_term_pid || log_to_file)
pid = getpid();
else
pid = -1;
if ('\n' != msg[strlen(msg) - 1])
nl_or_empty = nl;
else
nl_or_empty = empty;
if (log_to_term) {
term_file = (level <= LOG_ERR)
? stderr
: stdout;
if (msyslog_include_timestamp)
fprintf(term_file, "%s ", human_time);
if (msyslog_term_pid)
fprintf(term_file, "%s[%d]: ", prog, pid);
fprintf(term_file, "%s%s", msg, nl_or_empty);
fflush(term_file);
}
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 nfmt[256];
#else
const char * nfmt = fmt;
#endif
int errval;
#ifdef SYS_WINNT
errval = GetLastError();
if (NO_ERROR == errval)
#endif
errval = errno;
#ifndef VSNPRINTF_PERCENT_M
format_errmsg(nfmt, sizeof(nfmt), fmt, errval);
#else
errno = errval;
#endif
return vsnprintf(buf, bufsiz, nfmt, ap);
}
int
mvfprintf(
FILE * fp,
const char * fmt,
va_list ap
)
{
#ifndef VSNPRINTF_PERCENT_M
char nfmt[256];
#else
const char * nfmt = fmt;
#endif
int errval;
#ifdef SYS_WINNT
errval = GetLastError();
if (NO_ERROR == errval)
#endif
errval = errno;
#ifndef VSNPRINTF_PERCENT_M
format_errmsg(nfmt, sizeof(nfmt), fmt, errval);
#else
errno = errval;
#endif
return vfprintf(fp, nfmt, ap);
}
int
mfprintf(
FILE * fp,
const char * fmt,
...
)
{
va_list ap;
int rc;
va_start(ap, fmt);
rc = mvfprintf(fp, fmt, ap);
va_end(ap);
return rc;
}
int
mprintf(
const char * fmt,
...
)
{
va_list ap;
int rc;
va_start(ap, fmt);
rc = mvfprintf(stdout, fmt, ap);
va_end(ap);
return rc;
}
int
msnprintf(
char * buf,
size_t bufsiz,
const char * fmt,
...
)
{
va_list ap;
int rc;
va_start(ap, fmt);
rc = mvsnprintf(buf, bufsiz, fmt, ap);
va_end(ap);
return rc;
}
void
msyslog(
int level,
const char * fmt,
...
)
{
char buf[1024];
va_list ap;
va_start(ap, fmt);
mvsnprintf(buf, sizeof(buf), fmt, ap);
va_end(ap);
addto_syslog(level, buf);
}
void
mvsyslog(
int level,
const char * fmt,
va_list ap
)
{
char buf[1024];
mvsnprintf(buf, sizeof(buf), fmt, ap);
addto_syslog(level, buf);
}
void
init_logging(
const char * name,
u_int32 def_syslogmask,
int is_daemon
)
{
static int was_daemon;
char * cp;
const char * pname;
if (INIT_NTP_SYSLOGMASK == ntp_syslogmask &&
0 != def_syslogmask)
ntp_syslogmask = def_syslogmask;
cp = strrchr(name, DIR_SEP);
if (NULL == cp)
pname = name;
else
pname = 1 + cp;
progname = estrdup(pname);
#ifdef SYS_WINNT
cp = strrchr(progname, '.');
if (NULL != cp && !strcasecmp(cp, ".exe"))
*cp = '\0';
#endif
#if !defined(VMS)
if (is_daemon)
was_daemon = TRUE;
# ifndef LOG_DAEMON
openlog(progname, LOG_PID);
# else
# ifndef LOG_NTP
# define LOG_NTP LOG_DAEMON
# endif
openlog(progname, LOG_PID | LOG_NDELAY, (was_daemon)
? LOG_NTP
: 0);
# ifdef DEBUG
if (debug)
setlogmask(LOG_UPTO(LOG_DEBUG));
else
# endif
setlogmask(LOG_UPTO(LOG_DEBUG));
# endif
#endif
}
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
REQUIRE(fname != NULL);
log_fname = fname;
if (syslog_file != NULL && syslog_fname != NULL &&
0 == strcmp(syslog_fname, log_fname))
return 0;
if (0 == strcmp(log_fname, "stderr")) {
new_file = stderr;
abs_fname = estrdup(log_fname);
} else if (0 == strcmp(log_fname, "stdout")) {
new_file = stdout;
abs_fname = estrdup(log_fname);
} else {
if (syslog_fname != NULL &&
0 == strcmp(log_fname, syslog_fname))
log_fname = syslog_abs_fname;
#if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS)
if (log_fname != syslog_abs_fname &&
DIR_SEP != log_fname[0] &&
0 != strcmp(log_fname, "stderr") &&
0 != strcmp(log_fname, "stdout") &&
NULL != getcwd(curdir, sizeof(curdir))) {
cd_octets = strlen(curdir);
if (cd_octets > 1 &&
DIR_SEP == curdir[cd_octets - 1])
cd_octets--;
octets = cd_octets;
octets += 1;
octets += strlen(log_fname);
octets += 1;
abs_fname = emalloc(octets);
snprintf(abs_fname, octets, "%.*s%c%s",
(int)cd_octets, curdir, DIR_SEP,
log_fname);
} else
#endif
abs_fname = estrdup(log_fname);
TRACE(1, ("attempting to open log %s\n", abs_fname));
new_file = fopen(abs_fname, "a");
}
if (NULL == new_file) {
free(abs_fname);
return -1;
}
if (leave_crumbs && (syslogit || log_fname != syslog_abs_fname))
msyslog(LOG_NOTICE, "switching logging to file %s",
abs_fname);
if (syslog_file != NULL &&
syslog_file != stderr && syslog_file != stdout &&
fileno(syslog_file) != fileno(new_file))
fclose(syslog_file);
syslog_file = new_file;
if (log_fname == syslog_abs_fname) {
free(abs_fname);
} else {
if (syslog_abs_fname != NULL &&
syslog_abs_fname != syslog_fname)
free(syslog_abs_fname);
if (syslog_fname != NULL)
free(syslog_fname);
syslog_fname = estrdup(log_fname);
syslog_abs_fname = abs_fname;
}
syslogit = FALSE;
return 0;
}
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;
if (-1 == change_logfile(syslog_fname, FALSE))
msyslog(LOG_ERR, "Cannot reopen log file %s, %m",
syslog_fname);
}