1*eabc0478Schristos /* $NetBSD: msyslog.c,v 1.8 2024/08/18 20:47:13 christos Exp $ */ 2abb0f93cSkardel 3abb0f93cSkardel /* 4abb0f93cSkardel * msyslog - either send a message to the terminal or print it on 5abb0f93cSkardel * the standard output. 6abb0f93cSkardel * 7abb0f93cSkardel * Converted to use varargs, much better ... jks 8abb0f93cSkardel */ 9abb0f93cSkardel 10abb0f93cSkardel #ifdef HAVE_CONFIG_H 11abb0f93cSkardel # include <config.h> 12abb0f93cSkardel #endif 13abb0f93cSkardel 14abb0f93cSkardel #include <sys/types.h> 15abb0f93cSkardel #ifdef HAVE_UNISTD_H 16abb0f93cSkardel # include <unistd.h> 17abb0f93cSkardel #endif 18abb0f93cSkardel #include <stdio.h> 19abb0f93cSkardel 20abb0f93cSkardel #include "ntp_string.h" 218585484eSchristos #include "ntp.h" 228585484eSchristos #include "ntp_debug.h" 23abb0f93cSkardel #include "ntp_syslog.h" 24abb0f93cSkardel 25abb0f93cSkardel #ifdef SYS_WINNT 26abb0f93cSkardel # include <stdarg.h> 27abb0f93cSkardel # include "..\ports\winnt\libntp\messages.h" 28abb0f93cSkardel #endif 29abb0f93cSkardel 30f003fb54Skardel 318585484eSchristos int syslogit = TRUE; 32f003fb54Skardel int msyslog_term = FALSE; /* duplicate to stdout/err */ 338585484eSchristos int msyslog_term_pid = TRUE; 348585484eSchristos int msyslog_include_timestamp = TRUE; 35f003fb54Skardel FILE * syslog_file; 368585484eSchristos char * syslog_fname; 378585484eSchristos char * syslog_abs_fname; 38abb0f93cSkardel 398585484eSchristos /* libntp default ntp_syslogmask is all bits lit */ 408585484eSchristos #define INIT_NTP_SYSLOGMASK ~(u_int32)0 418585484eSchristos u_int32 ntp_syslogmask = INIT_NTP_SYSLOGMASK; 42abb0f93cSkardel 43af12ab5eSchristos extern char const * progname; 44abb0f93cSkardel 45abb0f93cSkardel /* Declare the local functions */ 46f003fb54Skardel void addto_syslog (int, const char *); 4722eebdc3Schristos #ifdef VSNPRINTF_PERCENT_M 4822eebdc3Schristos #define format_errmsg(buf, len, fmt, error) (fmt) 4922eebdc3Schristos #else 5022eebdc3Schristos static const char *format_errmsg(char *, size_t, const char *, int) 5122eebdc3Schristos NTP_FORMAT_ARG(3); 52abb0f93cSkardel 538585484eSchristos /* format_errmsg() is under #ifndef VSNPRINTF_PERCENT_M above */ 5422eebdc3Schristos static const char * 558585484eSchristos format_errmsg( 568585484eSchristos char * nfmt, 578585484eSchristos size_t lennfmt, 588585484eSchristos const char * fmt, 598585484eSchristos int errval 608585484eSchristos ) 618585484eSchristos { 628585484eSchristos char errmsg[256]; 638585484eSchristos char c; 648585484eSchristos char *n; 658585484eSchristos const char *f; 668585484eSchristos size_t len; 678585484eSchristos 688585484eSchristos n = nfmt; 698585484eSchristos f = fmt; 708585484eSchristos while ((c = *f++) != '\0' && n < (nfmt + lennfmt - 1)) { 718585484eSchristos if (c != '%') { 728585484eSchristos *n++ = c; 738585484eSchristos continue; 748585484eSchristos } 758585484eSchristos if ((c = *f++) != 'm') { 768585484eSchristos *n++ = '%'; 778585484eSchristos if ('\0' == c) 788585484eSchristos break; 798585484eSchristos *n++ = c; 808585484eSchristos continue; 818585484eSchristos } 828585484eSchristos errno_to_str(errval, errmsg, sizeof(errmsg)); 838585484eSchristos len = strlen(errmsg); 848585484eSchristos 858585484eSchristos /* Make sure we have enough space for the error message */ 868585484eSchristos if ((n + len) < (nfmt + lennfmt - 1)) { 878585484eSchristos memcpy(n, errmsg, len); 888585484eSchristos n += len; 898585484eSchristos } 908585484eSchristos } 918585484eSchristos *n = '\0'; 9222eebdc3Schristos return nfmt; 938585484eSchristos } 948585484eSchristos #endif /* VSNPRINTF_PERCENT_M */ 958585484eSchristos 96abb0f93cSkardel 97abb0f93cSkardel /* 988585484eSchristos * errno_to_str() - a thread-safe strerror() replacement. 998585484eSchristos * Hides the varied signatures of strerror_r(). 1008585484eSchristos * For Windows, we have: 101*eabc0478Schristos * #define errno_to_str isc__strerror 1028585484eSchristos */ 1038585484eSchristos #ifndef errno_to_str 1048585484eSchristos void 1058585484eSchristos errno_to_str( 1068585484eSchristos int err, 1078585484eSchristos char * buf, 1088585484eSchristos size_t bufsiz 1098585484eSchristos ) 1108585484eSchristos { 1118585484eSchristos # if defined(STRERROR_R_CHAR_P) || !HAVE_DECL_STRERROR_R 1128585484eSchristos char * pstatic; 1138585484eSchristos 1148585484eSchristos buf[0] = '\0'; 1158585484eSchristos # ifdef STRERROR_R_CHAR_P 1168585484eSchristos pstatic = strerror_r(err, buf, bufsiz); 1178585484eSchristos # else 1188585484eSchristos pstatic = strerror(err); 1198585484eSchristos # endif 1208585484eSchristos if (NULL == pstatic && '\0' == buf[0]) 1218585484eSchristos snprintf(buf, bufsiz, "%s(%d): errno %d", 1228585484eSchristos # ifdef STRERROR_R_CHAR_P 1238585484eSchristos "strerror_r", 1248585484eSchristos # else 1258585484eSchristos "strerror", 1268585484eSchristos # endif 1278585484eSchristos err, errno); 1288585484eSchristos /* protect against believing an int return is a pointer */ 1298585484eSchristos else if (pstatic != buf && pstatic > (char *)bufsiz) 1308585484eSchristos strlcpy(buf, pstatic, bufsiz); 1318585484eSchristos # else 1328585484eSchristos int rc; 1338585484eSchristos 1348585484eSchristos rc = strerror_r(err, buf, bufsiz); 1358585484eSchristos if (rc < 0) 1368585484eSchristos snprintf(buf, bufsiz, "strerror_r(%d): errno %d", 1378585484eSchristos err, errno); 1388585484eSchristos # endif 1398585484eSchristos } 1408585484eSchristos #endif /* errno_to_str */ 1418585484eSchristos 1428585484eSchristos 1438585484eSchristos /* 1448585484eSchristos * addto_syslog() 145f003fb54Skardel * This routine adds the contents of a buffer to the syslog or an 146f003fb54Skardel * application-specific logfile. 147abb0f93cSkardel */ 148abb0f93cSkardel void 149f003fb54Skardel addto_syslog( 150f003fb54Skardel int level, 151f003fb54Skardel const char * msg 152f003fb54Skardel ) 153abb0f93cSkardel { 154af12ab5eSchristos static char const * prevcall_progname; 155af12ab5eSchristos static char const * prog; 156f003fb54Skardel const char nl[] = "\n"; 157f003fb54Skardel const char empty[] = ""; 158f003fb54Skardel FILE * term_file; 159f003fb54Skardel int log_to_term; 160f003fb54Skardel int log_to_file; 1618585484eSchristos int pid; 162f003fb54Skardel const char * nl_or_empty; 163f003fb54Skardel const char * human_time; 164abb0f93cSkardel 165f003fb54Skardel /* setup program basename static var prog if needed */ 166f003fb54Skardel if (progname != prevcall_progname) { 167f003fb54Skardel prevcall_progname = progname; 168f003fb54Skardel prog = strrchr(progname, DIR_SEP); 169f003fb54Skardel if (prog != NULL) 170f003fb54Skardel prog++; 171f003fb54Skardel else 172f003fb54Skardel prog = progname; 173f003fb54Skardel } 174f003fb54Skardel 175f003fb54Skardel log_to_term = msyslog_term; 176f003fb54Skardel log_to_file = FALSE; 177abb0f93cSkardel #if !defined(VMS) && !defined(SYS_VXWORKS) 178abb0f93cSkardel if (syslogit) 179f003fb54Skardel syslog(level, "%s", msg); 180abb0f93cSkardel else 181abb0f93cSkardel #endif 182f003fb54Skardel if (syslog_file != NULL) 183f003fb54Skardel log_to_file = TRUE; 184f003fb54Skardel else 185f003fb54Skardel log_to_term = TRUE; 186f003fb54Skardel #if DEBUG 187f003fb54Skardel if (debug > 0) 188f003fb54Skardel log_to_term = TRUE; 189f003fb54Skardel #endif 190f003fb54Skardel if (!(log_to_file || log_to_term)) 191f003fb54Skardel return; 192f003fb54Skardel 193f003fb54Skardel /* syslog() adds the timestamp, name, and pid */ 1948585484eSchristos if (msyslog_include_timestamp) 195f003fb54Skardel human_time = humanlogtime(); 1968585484eSchristos else /* suppress gcc pot. uninit. warning */ 1978585484eSchristos human_time = NULL; 1988585484eSchristos if (msyslog_term_pid || log_to_file) 1998585484eSchristos pid = getpid(); 2008585484eSchristos else /* suppress gcc pot. uninit. warning */ 2018585484eSchristos pid = -1; 202f003fb54Skardel 203f003fb54Skardel /* syslog() adds trailing \n if not present */ 204f003fb54Skardel if ('\n' != msg[strlen(msg) - 1]) 205f003fb54Skardel nl_or_empty = nl; 206f003fb54Skardel else 207f003fb54Skardel nl_or_empty = empty; 208f003fb54Skardel 209f003fb54Skardel if (log_to_term) { 210f003fb54Skardel term_file = (level <= LOG_ERR) 211f003fb54Skardel ? stderr 212f003fb54Skardel : stdout; 2138585484eSchristos if (msyslog_include_timestamp) 2148585484eSchristos fprintf(term_file, "%s ", human_time); 2158585484eSchristos if (msyslog_term_pid) 2168585484eSchristos fprintf(term_file, "%s[%d]: ", prog, pid); 2178585484eSchristos fprintf(term_file, "%s%s", msg, nl_or_empty); 218f003fb54Skardel fflush(term_file); 219abb0f93cSkardel } 220f003fb54Skardel 221f003fb54Skardel if (log_to_file) { 2228585484eSchristos if (msyslog_include_timestamp) 2238585484eSchristos fprintf(syslog_file, "%s ", human_time); 2248585484eSchristos fprintf(syslog_file, "%s[%d]: %s%s", prog, pid, msg, 2258585484eSchristos nl_or_empty); 226f003fb54Skardel fflush(syslog_file); 227f003fb54Skardel } 228f003fb54Skardel } 229f003fb54Skardel 230f003fb54Skardel 231f003fb54Skardel int 232f003fb54Skardel mvsnprintf( 233f003fb54Skardel char * buf, 234f003fb54Skardel size_t bufsiz, 235f003fb54Skardel const char * fmt, 236f003fb54Skardel va_list ap 237f003fb54Skardel ) 238abb0f93cSkardel { 239f003fb54Skardel #ifndef VSNPRINTF_PERCENT_M 24022eebdc3Schristos char fmtbuf[256]; 241abb0f93cSkardel #endif 242abb0f93cSkardel int errval; 243abb0f93cSkardel 244abb0f93cSkardel /* 245abb0f93cSkardel * Save the error value as soon as possible 246abb0f93cSkardel */ 247abb0f93cSkardel #ifdef SYS_WINNT 248abb0f93cSkardel errval = GetLastError(); 249abb0f93cSkardel if (NO_ERROR == errval) 250abb0f93cSkardel #endif /* SYS_WINNT */ 251f003fb54Skardel errval = errno; 252abb0f93cSkardel 25322eebdc3Schristos #ifdef VSNPRINTF_PERCENT_M 254f003fb54Skardel errno = errval; 255f003fb54Skardel #endif 25622eebdc3Schristos return vsnprintf(buf, bufsiz, 25722eebdc3Schristos format_errmsg(fmtbuf, sizeof(fmtbuf), fmt, errval), ap); 258f003fb54Skardel } 259abb0f93cSkardel 260f003fb54Skardel 261f003fb54Skardel int 262f003fb54Skardel mvfprintf( 263f003fb54Skardel FILE * fp, 264f003fb54Skardel const char * fmt, 265f003fb54Skardel va_list ap 266f003fb54Skardel ) 267f003fb54Skardel { 268f003fb54Skardel #ifndef VSNPRINTF_PERCENT_M 26922eebdc3Schristos char fmtbuf[256]; 270f003fb54Skardel #endif 271f003fb54Skardel int errval; 272f003fb54Skardel 273f003fb54Skardel /* 274f003fb54Skardel * Save the error value as soon as possible 275f003fb54Skardel */ 276f003fb54Skardel #ifdef SYS_WINNT 277f003fb54Skardel errval = GetLastError(); 278f003fb54Skardel if (NO_ERROR == errval) 279f003fb54Skardel #endif /* SYS_WINNT */ 280f003fb54Skardel errval = errno; 281f003fb54Skardel 28222eebdc3Schristos #ifdef VSNPRINTF_PERCENT_M 283f003fb54Skardel errno = errval; 284f003fb54Skardel #endif 28522eebdc3Schristos return vfprintf(fp, 28622eebdc3Schristos format_errmsg(fmtbuf, sizeof(fmtbuf), fmt, errval), ap); 287f003fb54Skardel } 288f003fb54Skardel 289f003fb54Skardel 290f003fb54Skardel int 291f003fb54Skardel mfprintf( 292f003fb54Skardel FILE * fp, 293f003fb54Skardel const char * fmt, 294f003fb54Skardel ... 295f003fb54Skardel ) 296f003fb54Skardel { 297f003fb54Skardel va_list ap; 298f003fb54Skardel int rc; 299f003fb54Skardel 300f003fb54Skardel va_start(ap, fmt); 301f003fb54Skardel rc = mvfprintf(fp, fmt, ap); 302abb0f93cSkardel va_end(ap); 303f003fb54Skardel 304f003fb54Skardel return rc; 305f003fb54Skardel } 306f003fb54Skardel 307f003fb54Skardel 308f003fb54Skardel int 309f003fb54Skardel mprintf( 310f003fb54Skardel const char * fmt, 311f003fb54Skardel ... 312f003fb54Skardel ) 313f003fb54Skardel { 314f003fb54Skardel va_list ap; 315f003fb54Skardel int rc; 316f003fb54Skardel 317f003fb54Skardel va_start(ap, fmt); 318f003fb54Skardel rc = mvfprintf(stdout, fmt, ap); 319f003fb54Skardel va_end(ap); 320f003fb54Skardel 321f003fb54Skardel return rc; 322f003fb54Skardel } 323f003fb54Skardel 324f003fb54Skardel 325f003fb54Skardel int 326f003fb54Skardel msnprintf( 327f003fb54Skardel char * buf, 328f003fb54Skardel size_t bufsiz, 329f003fb54Skardel const char * fmt, 330f003fb54Skardel ... 331f003fb54Skardel ) 332f003fb54Skardel { 333f003fb54Skardel va_list ap; 3348b8da087Schristos int rc; 335f003fb54Skardel 336f003fb54Skardel va_start(ap, fmt); 337f003fb54Skardel rc = mvsnprintf(buf, bufsiz, fmt, ap); 338f003fb54Skardel va_end(ap); 339f003fb54Skardel 340f003fb54Skardel return rc; 341f003fb54Skardel } 342f003fb54Skardel 343f003fb54Skardel 344f003fb54Skardel void 345f003fb54Skardel msyslog( 346f003fb54Skardel int level, 347f003fb54Skardel const char * fmt, 348f003fb54Skardel ... 349f003fb54Skardel ) 350f003fb54Skardel { 351f003fb54Skardel va_list ap; 352f003fb54Skardel 353f003fb54Skardel va_start(ap, fmt); 354*eabc0478Schristos mvsyslog(level, fmt, ap); 355f003fb54Skardel va_end(ap); 356abb0f93cSkardel } 3578585484eSchristos 358*eabc0478Schristos 359af12ab5eSchristos void 360af12ab5eSchristos mvsyslog( 361af12ab5eSchristos int level, 362af12ab5eSchristos const char * fmt, 363af12ab5eSchristos va_list ap 364af12ab5eSchristos ) 365af12ab5eSchristos { 366af12ab5eSchristos char buf[1024]; 367*eabc0478Schristos 368af12ab5eSchristos mvsnprintf(buf, sizeof(buf), fmt, ap); 369af12ab5eSchristos addto_syslog(level, buf); 370af12ab5eSchristos } 371af12ab5eSchristos 3728585484eSchristos 3738585484eSchristos /* 3748585484eSchristos * Initialize the logging 3758585484eSchristos * 3768585484eSchristos * Called once per process, including forked children. 3778585484eSchristos */ 3788585484eSchristos void 3798585484eSchristos init_logging( 3808585484eSchristos const char * name, 3818585484eSchristos u_int32 def_syslogmask, 3828585484eSchristos int is_daemon 3838585484eSchristos ) 3848585484eSchristos { 3858585484eSchristos static int was_daemon; 386af12ab5eSchristos char * cp; 3878585484eSchristos const char * pname; 3888585484eSchristos 3898585484eSchristos /* 3908585484eSchristos * ntpd defaults to only logging sync-category events, when 3918585484eSchristos * NLOG() is used to conditionalize. Other libntp clients 3928585484eSchristos * leave it alone so that all NLOG() conditionals will fire. 3938585484eSchristos * This presumes all bits lit in ntp_syslogmask can't be 3948585484eSchristos * configured via logconfig and all lit is thereby a sentinel 3958585484eSchristos * that ntp_syslogmask is still at its default from libntp, 3968585484eSchristos * keeping in mind this function is called in forked children 3978585484eSchristos * where it has already been called in the parent earlier. 3988585484eSchristos * Forked children pass 0 for def_syslogmask. 3998585484eSchristos */ 4008585484eSchristos if (INIT_NTP_SYSLOGMASK == ntp_syslogmask && 4018585484eSchristos 0 != def_syslogmask) 4028585484eSchristos ntp_syslogmask = def_syslogmask; /* set more via logconfig */ 4038585484eSchristos 4048585484eSchristos /* 4058585484eSchristos * Logging. This may actually work on the gizmo board. Find a name 4068585484eSchristos * to log with by using the basename 4078585484eSchristos */ 4088585484eSchristos cp = strrchr(name, DIR_SEP); 4098585484eSchristos if (NULL == cp) 4108585484eSchristos pname = name; 4118585484eSchristos else 4128585484eSchristos pname = 1 + cp; /* skip DIR_SEP */ 4138585484eSchristos progname = estrdup(pname); 4148585484eSchristos #ifdef SYS_WINNT /* strip ".exe" */ 4158585484eSchristos cp = strrchr(progname, '.'); 4168585484eSchristos if (NULL != cp && !strcasecmp(cp, ".exe")) 417af12ab5eSchristos *cp = '\0'; 4188585484eSchristos #endif 4198585484eSchristos 4208585484eSchristos #if !defined(VMS) 4218585484eSchristos 4228585484eSchristos if (is_daemon) 4238585484eSchristos was_daemon = TRUE; 4248585484eSchristos # ifndef LOG_DAEMON 4258585484eSchristos openlog(progname, LOG_PID); 4268585484eSchristos # else /* LOG_DAEMON */ 4278585484eSchristos 4288585484eSchristos # ifndef LOG_NTP 4298585484eSchristos # define LOG_NTP LOG_DAEMON 4308585484eSchristos # endif 4318585484eSchristos openlog(progname, LOG_PID | LOG_NDELAY, (was_daemon) 4328585484eSchristos ? LOG_NTP 4338585484eSchristos : 0); 4348585484eSchristos # ifdef DEBUG 4358585484eSchristos if (debug) 4368585484eSchristos setlogmask(LOG_UPTO(LOG_DEBUG)); 4378585484eSchristos else 4388585484eSchristos # endif /* DEBUG */ 4398585484eSchristos setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */ 4408585484eSchristos # endif /* LOG_DAEMON */ 4418585484eSchristos #endif /* !VMS */ 4428585484eSchristos } 4438585484eSchristos 4448585484eSchristos 4458585484eSchristos /* 4468585484eSchristos * change_logfile() 4478585484eSchristos * 4488585484eSchristos * Used to change from syslog to a logfile, or from one logfile to 4498585484eSchristos * another, and to reopen logfiles after forking. On systems where 4508585484eSchristos * ntpd forks, deals with converting relative logfile paths to 4518585484eSchristos * absolute (root-based) because we reopen logfiles after the current 4528585484eSchristos * directory has changed. 4538585484eSchristos */ 4548585484eSchristos int 4558585484eSchristos change_logfile( 4568585484eSchristos const char * fname, 4578585484eSchristos int leave_crumbs 4588585484eSchristos ) 4598585484eSchristos { 4608585484eSchristos FILE * new_file; 4618585484eSchristos const char * log_fname; 4628585484eSchristos char * abs_fname; 4638585484eSchristos #if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS) 4648585484eSchristos char curdir[512]; 4658585484eSchristos size_t cd_octets; 4668585484eSchristos size_t octets; 4678585484eSchristos #endif /* POSIX */ 4688585484eSchristos 469af12ab5eSchristos REQUIRE(fname != NULL); 4708585484eSchristos log_fname = fname; 4718585484eSchristos 4728585484eSchristos /* 4738585484eSchristos * In a forked child of a parent which is logging to a file 4748585484eSchristos * instead of syslog, syslog_file will be NULL and both 4758585484eSchristos * syslog_fname and syslog_abs_fname will be non-NULL. 4768585484eSchristos * If we are given the same filename previously opened 4778585484eSchristos * and it's still open, there's nothing to do here. 4788585484eSchristos */ 4798585484eSchristos if (syslog_file != NULL && syslog_fname != NULL && 4808585484eSchristos 0 == strcmp(syslog_fname, log_fname)) 4818585484eSchristos return 0; 4828585484eSchristos 4838585484eSchristos if (0 == strcmp(log_fname, "stderr")) { 4848585484eSchristos new_file = stderr; 4858585484eSchristos abs_fname = estrdup(log_fname); 4868585484eSchristos } else if (0 == strcmp(log_fname, "stdout")) { 4878585484eSchristos new_file = stdout; 4888585484eSchristos abs_fname = estrdup(log_fname); 4898585484eSchristos } else { 4908585484eSchristos if (syslog_fname != NULL && 4918585484eSchristos 0 == strcmp(log_fname, syslog_fname)) 4928585484eSchristos log_fname = syslog_abs_fname; 4938585484eSchristos #if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS) 4948585484eSchristos if (log_fname != syslog_abs_fname && 4958585484eSchristos DIR_SEP != log_fname[0] && 4968585484eSchristos 0 != strcmp(log_fname, "stderr") && 4978585484eSchristos 0 != strcmp(log_fname, "stdout") && 4988585484eSchristos NULL != getcwd(curdir, sizeof(curdir))) { 4998585484eSchristos cd_octets = strlen(curdir); 5008585484eSchristos /* trim any trailing '/' */ 5018585484eSchristos if (cd_octets > 1 && 5028585484eSchristos DIR_SEP == curdir[cd_octets - 1]) 5038585484eSchristos cd_octets--; 5048585484eSchristos octets = cd_octets; 5058585484eSchristos octets += 1; /* separator '/' */ 5068585484eSchristos octets += strlen(log_fname); 5078585484eSchristos octets += 1; /* NUL terminator */ 5088585484eSchristos abs_fname = emalloc(octets); 5098585484eSchristos snprintf(abs_fname, octets, "%.*s%c%s", 5108585484eSchristos (int)cd_octets, curdir, DIR_SEP, 5118585484eSchristos log_fname); 5128585484eSchristos } else 5138585484eSchristos #endif 5148585484eSchristos abs_fname = estrdup(log_fname); 5158585484eSchristos TRACE(1, ("attempting to open log %s\n", abs_fname)); 5168585484eSchristos new_file = fopen(abs_fname, "a"); 5178585484eSchristos } 5188585484eSchristos 5198585484eSchristos if (NULL == new_file) { 5208585484eSchristos free(abs_fname); 5218585484eSchristos return -1; 5228585484eSchristos } 5238585484eSchristos 5248585484eSchristos /* leave a pointer in the old log */ 5258585484eSchristos if (leave_crumbs && (syslogit || log_fname != syslog_abs_fname)) 5268585484eSchristos msyslog(LOG_NOTICE, "switching logging to file %s", 5278585484eSchristos abs_fname); 5288585484eSchristos 5298585484eSchristos if (syslog_file != NULL && 5308585484eSchristos syslog_file != stderr && syslog_file != stdout && 5318585484eSchristos fileno(syslog_file) != fileno(new_file)) 5328585484eSchristos fclose(syslog_file); 5338585484eSchristos syslog_file = new_file; 5348585484eSchristos if (log_fname == syslog_abs_fname) { 5358585484eSchristos free(abs_fname); 5368585484eSchristos } else { 5378585484eSchristos if (syslog_abs_fname != NULL && 5388585484eSchristos syslog_abs_fname != syslog_fname) 5398585484eSchristos free(syslog_abs_fname); 5408585484eSchristos if (syslog_fname != NULL) 5418585484eSchristos free(syslog_fname); 5428585484eSchristos syslog_fname = estrdup(log_fname); 5438585484eSchristos syslog_abs_fname = abs_fname; 5448585484eSchristos } 5458585484eSchristos syslogit = FALSE; 5468585484eSchristos 5478585484eSchristos return 0; 5488585484eSchristos } 5498585484eSchristos 5508585484eSchristos 5518585484eSchristos /* 5528585484eSchristos * setup_logfile() 5538585484eSchristos * 5548585484eSchristos * Redirect logging to a file if requested with -l/--logfile or via 5558585484eSchristos * ntp.conf logfile directive. 5568585484eSchristos * 5578585484eSchristos * This routine is invoked three different times in the sequence of a 5588585484eSchristos * typical daemon ntpd with DNS lookups to do. First it is invoked in 5598585484eSchristos * the original ntpd process, then again in the daemon after closing 5608585484eSchristos * all descriptors. In both of those cases, ntp.conf has not been 5618585484eSchristos * processed, so only -l/--logfile will trigger logfile redirection in 5628585484eSchristos * those invocations. Finally, if DNS names are resolved, the worker 5638585484eSchristos * child invokes this routine after its fork and close of all 5648585484eSchristos * descriptors. In this case, ntp.conf has been processed and any 5658585484eSchristos * "logfile" directive needs to be honored in the child as well. 5668585484eSchristos */ 5678585484eSchristos void 5688585484eSchristos setup_logfile( 5698585484eSchristos const char * name 5708585484eSchristos ) 5718585484eSchristos { 5728585484eSchristos if (NULL == syslog_fname && NULL != name) { 5738585484eSchristos if (-1 == change_logfile(name, TRUE)) 5748585484eSchristos msyslog(LOG_ERR, "Cannot open log file %s, %m", 5758585484eSchristos name); 5768585484eSchristos return ; 5778585484eSchristos } 5788585484eSchristos if (NULL == syslog_fname) 5798585484eSchristos return; 5808585484eSchristos 5818585484eSchristos if (-1 == change_logfile(syslog_fname, FALSE)) 5828585484eSchristos msyslog(LOG_ERR, "Cannot reopen log file %s, %m", 5838585484eSchristos syslog_fname); 5848585484eSchristos } 585cdfa2a7eSchristos 586*eabc0478Schristos /* 587*eabc0478Schristos * Helper for unit tests, where stdout + stderr are piped to the same 588*eabc0478Schristos * stream. This works moderately reliably only if both streams are 589cdfa2a7eSchristos * unbuffered or line buffered. Unfortunately stdout can be fully 590cdfa2a7eSchristos * buffered on pipes or files... 591cdfa2a7eSchristos */ 592cdfa2a7eSchristos int 593cdfa2a7eSchristos change_iobufs( 594cdfa2a7eSchristos int how 595cdfa2a7eSchristos ) 596cdfa2a7eSchristos { 597cdfa2a7eSchristos int retv = 0; 598cdfa2a7eSchristos 599cdfa2a7eSchristos # ifdef HAVE_SETVBUF 600cdfa2a7eSchristos 601cdfa2a7eSchristos int mode; 602cdfa2a7eSchristos 603cdfa2a7eSchristos switch (how) { 604cdfa2a7eSchristos case 0 : mode = _IONBF; break; /* no buffering */ 605cdfa2a7eSchristos case 1 : mode = _IOLBF; break; /* line buffering */ 606cdfa2a7eSchristos case 2 : mode = _IOFBF; break; /* full buffering */ 607cdfa2a7eSchristos default: mode = _IOLBF; break; /* line buffering */ 608cdfa2a7eSchristos } 609cdfa2a7eSchristos 610cdfa2a7eSchristos retv = 1; 611cdfa2a7eSchristos if (setvbuf(stdout, NULL, mode, BUFSIZ) != 0) 612cdfa2a7eSchristos retv = -1; 613cdfa2a7eSchristos if (setvbuf(stderr, NULL, mode, BUFSIZ) != 0) 614cdfa2a7eSchristos retv = -1; 615cdfa2a7eSchristos 616cdfa2a7eSchristos # else 617cdfa2a7eSchristos 618cdfa2a7eSchristos UNUSED_ARG(how); 619cdfa2a7eSchristos 620cdfa2a7eSchristos # endif 621cdfa2a7eSchristos 622cdfa2a7eSchristos return retv; 623cdfa2a7eSchristos } 624