154359Sroberto/*
254359Sroberto * msyslog - either send a message to the terminal or print it on
354359Sroberto *	     the standard output.
454359Sroberto *
554359Sroberto * Converted to use varargs, much better ... jks
654359Sroberto */
754359Sroberto
854359Sroberto#ifdef HAVE_CONFIG_H
954359Sroberto# include <config.h>
1054359Sroberto#endif
1154359Sroberto
12285612Sdelphij#include <sys/types.h>
1354359Sroberto#ifdef HAVE_UNISTD_H
1454359Sroberto# include <unistd.h>
1554359Sroberto#endif
1654359Sroberto#include <stdio.h>
1754359Sroberto
1854359Sroberto#include "ntp_string.h"
19285612Sdelphij#include "ntp.h"
20285612Sdelphij#include "ntp_debug.h"
2182498Sroberto#include "ntp_syslog.h"
2254359Sroberto
2354359Sroberto#ifdef SYS_WINNT
24132451Sroberto# include <stdarg.h>
2554359Sroberto# include "..\ports\winnt\libntp\messages.h"
2654359Sroberto#endif
2754359Sroberto
2854359Sroberto
29285612Sdelphijint	syslogit = TRUE;
30285612Sdelphijint	msyslog_term = FALSE;	/* duplicate to stdout/err */
31285612Sdelphijint	msyslog_term_pid = TRUE;
32285612Sdelphijint	msyslog_include_timestamp = TRUE;
33285612SdelphijFILE *	syslog_file;
34285612Sdelphijchar *	syslog_fname;
35285612Sdelphijchar *	syslog_abs_fname;
3654359Sroberto
37285612Sdelphij/* libntp default ntp_syslogmask is all bits lit */
38285612Sdelphij#define INIT_NTP_SYSLOGMASK	~(u_int32)0
39285612Sdelphiju_int32 ntp_syslogmask = INIT_NTP_SYSLOGMASK;
4054359Sroberto
41289999Sglebiusextern char const * progname;
4254359Sroberto
43132451Sroberto/* Declare the local functions */
44285612Sdelphijvoid	addto_syslog	(int, const char *);
45285612Sdelphij#ifndef VSNPRINTF_PERCENT_M
46285612Sdelphijvoid	format_errmsg	(char *, size_t, const char *, int);
47132451Sroberto
48285612Sdelphij/* format_errmsg() is under #ifndef VSNPRINTF_PERCENT_M above */
49132451Srobertovoid
50285612Sdelphijformat_errmsg(
51285612Sdelphij	char *		nfmt,
52285612Sdelphij	size_t		lennfmt,
53285612Sdelphij	const char *	fmt,
54285612Sdelphij	int		errval
55285612Sdelphij	)
5654359Sroberto{
57285612Sdelphij	char errmsg[256];
58285612Sdelphij	char c;
59285612Sdelphij	char *n;
60285612Sdelphij	const char *f;
61285612Sdelphij	size_t len;
62132451Sroberto
6354359Sroberto	n = nfmt;
6454359Sroberto	f = fmt;
65285612Sdelphij	while ((c = *f++) != '\0' && n < (nfmt + lennfmt - 1)) {
6654359Sroberto		if (c != '%') {
6754359Sroberto			*n++ = c;
6854359Sroberto			continue;
6954359Sroberto		}
7054359Sroberto		if ((c = *f++) != 'm') {
7154359Sroberto			*n++ = '%';
72285612Sdelphij			if ('\0' == c)
73285612Sdelphij				break;
7454359Sroberto			*n++ = c;
7554359Sroberto			continue;
7654359Sroberto		}
77285612Sdelphij		errno_to_str(errval, errmsg, sizeof(errmsg));
78285612Sdelphij		len = strlen(errmsg);
79285612Sdelphij
80132451Sroberto		/* Make sure we have enough space for the error message */
81285612Sdelphij		if ((n + len) < (nfmt + lennfmt - 1)) {
82285612Sdelphij			memcpy(n, errmsg, len);
83285612Sdelphij			n += len;
8454359Sroberto		}
8554359Sroberto	}
8654359Sroberto	*n = '\0';
87132451Sroberto}
88285612Sdelphij#endif	/* VSNPRINTF_PERCENT_M */
8954359Sroberto
90285612Sdelphij
91132451Sroberto/*
92285612Sdelphij * errno_to_str() - a thread-safe strerror() replacement.
93285612Sdelphij *		    Hides the varied signatures of strerror_r().
94285612Sdelphij *		    For Windows, we have:
95285612Sdelphij *			#define errno_to_str isc_strerror
96132451Sroberto */
97285612Sdelphij#ifndef errno_to_str
98285612Sdelphijvoid
99285612Sdelphijerrno_to_str(
100285612Sdelphij	int	err,
101285612Sdelphij	char *	buf,
102285612Sdelphij	size_t	bufsiz
103285612Sdelphij	)
104285612Sdelphij{
105285612Sdelphij# if defined(STRERROR_R_CHAR_P) || !HAVE_DECL_STRERROR_R
106285612Sdelphij	char *	pstatic;
107132451Sroberto
108285612Sdelphij	buf[0] = '\0';
109285612Sdelphij#  ifdef STRERROR_R_CHAR_P
110285612Sdelphij	pstatic = strerror_r(err, buf, bufsiz);
111285612Sdelphij#  else
112285612Sdelphij	pstatic = strerror(err);
113285612Sdelphij#  endif
114285612Sdelphij	if (NULL == pstatic && '\0' == buf[0])
115285612Sdelphij		snprintf(buf, bufsiz, "%s(%d): errno %d",
116285612Sdelphij#  ifdef STRERROR_R_CHAR_P
117285612Sdelphij			 "strerror_r",
118285612Sdelphij#  else
119285612Sdelphij			 "strerror",
120285612Sdelphij#  endif
121285612Sdelphij			 err, errno);
122285612Sdelphij	/* protect against believing an int return is a pointer */
123285612Sdelphij	else if (pstatic != buf && pstatic > (char *)bufsiz)
124285612Sdelphij		strlcpy(buf, pstatic, bufsiz);
125285612Sdelphij# else
126285612Sdelphij	int	rc;
127285612Sdelphij
128285612Sdelphij	rc = strerror_r(err, buf, bufsiz);
129285612Sdelphij	if (rc < 0)
130285612Sdelphij		snprintf(buf, bufsiz, "strerror_r(%d): errno %d",
131285612Sdelphij			 err, errno);
132285612Sdelphij# endif
133285612Sdelphij}
134285612Sdelphij#endif	/* errno_to_str */
135285612Sdelphij
136285612Sdelphij
137285612Sdelphij/*
138285612Sdelphij * addto_syslog()
139285612Sdelphij * This routine adds the contents of a buffer to the syslog or an
140285612Sdelphij * application-specific logfile.
141285612Sdelphij */
142285612Sdelphijvoid
143285612Sdelphijaddto_syslog(
144285612Sdelphij	int		level,
145285612Sdelphij	const char *	msg
146285612Sdelphij	)
147132451Sroberto{
148289999Sglebius	static char const *	prevcall_progname;
149289999Sglebius	static char const *	prog;
150285612Sdelphij	const char	nl[] = "\n";
151285612Sdelphij	const char	empty[] = "";
152285612Sdelphij	FILE *		term_file;
153285612Sdelphij	int		log_to_term;
154285612Sdelphij	int		log_to_file;
155285612Sdelphij	int		pid;
156285612Sdelphij	const char *	nl_or_empty;
157285612Sdelphij	const char *	human_time;
158285612Sdelphij
159285612Sdelphij	/* setup program basename static var prog if needed */
160285612Sdelphij	if (progname != prevcall_progname) {
161285612Sdelphij		prevcall_progname = progname;
162285612Sdelphij		prog = strrchr(progname, DIR_SEP);
163285612Sdelphij		if (prog != NULL)
164285612Sdelphij			prog++;
165285612Sdelphij		else
166285612Sdelphij			prog = progname;
167285612Sdelphij	}
168285612Sdelphij
169285612Sdelphij	log_to_term = msyslog_term;
170285612Sdelphij	log_to_file = FALSE;
171285612Sdelphij#if !defined(VMS) && !defined(SYS_VXWORKS)
172285612Sdelphij	if (syslogit)
173285612Sdelphij		syslog(level, "%s", msg);
174285612Sdelphij	else
175285612Sdelphij#endif
176285612Sdelphij		if (syslog_file != NULL)
177285612Sdelphij			log_to_file = TRUE;
178285612Sdelphij		else
179285612Sdelphij			log_to_term = TRUE;
180285612Sdelphij#if DEBUG
181285612Sdelphij	if (debug > 0)
182285612Sdelphij		log_to_term = TRUE;
183285612Sdelphij#endif
184285612Sdelphij	if (!(log_to_file || log_to_term))
185285612Sdelphij		return;
186285612Sdelphij
187285612Sdelphij	/* syslog() adds the timestamp, name, and pid */
188285612Sdelphij	if (msyslog_include_timestamp)
189285612Sdelphij		human_time = humanlogtime();
190285612Sdelphij	else	/* suppress gcc pot. uninit. warning */
191285612Sdelphij		human_time = NULL;
192285612Sdelphij	if (msyslog_term_pid || log_to_file)
193285612Sdelphij		pid = getpid();
194285612Sdelphij	else	/* suppress gcc pot. uninit. warning */
195285612Sdelphij		pid = -1;
196285612Sdelphij
197285612Sdelphij	/* syslog() adds trailing \n if not present */
198285612Sdelphij	if ('\n' != msg[strlen(msg) - 1])
199285612Sdelphij		nl_or_empty = nl;
200285612Sdelphij	else
201285612Sdelphij		nl_or_empty = empty;
202285612Sdelphij
203285612Sdelphij	if (log_to_term) {
204285612Sdelphij		term_file = (level <= LOG_ERR)
205285612Sdelphij				? stderr
206285612Sdelphij				: stdout;
207285612Sdelphij		if (msyslog_include_timestamp)
208285612Sdelphij			fprintf(term_file, "%s ", human_time);
209285612Sdelphij		if (msyslog_term_pid)
210285612Sdelphij			fprintf(term_file, "%s[%d]: ", prog, pid);
211285612Sdelphij		fprintf(term_file, "%s%s", msg, nl_or_empty);
212285612Sdelphij		fflush(term_file);
213285612Sdelphij	}
214285612Sdelphij
215285612Sdelphij	if (log_to_file) {
216285612Sdelphij		if (msyslog_include_timestamp)
217285612Sdelphij			fprintf(syslog_file, "%s ", human_time);
218285612Sdelphij		fprintf(syslog_file, "%s[%d]: %s%s", prog, pid, msg,
219285612Sdelphij			nl_or_empty);
220285612Sdelphij		fflush(syslog_file);
221285612Sdelphij	}
222285612Sdelphij}
223285612Sdelphij
224285612Sdelphij
225285612Sdelphijint
226285612Sdelphijmvsnprintf(
227285612Sdelphij	char *		buf,
228285612Sdelphij	size_t		bufsiz,
229285612Sdelphij	const char *	fmt,
230285612Sdelphij	va_list		ap
231285612Sdelphij	)
232285612Sdelphij{
233285612Sdelphij#ifndef VSNPRINTF_PERCENT_M
234285612Sdelphij	char		nfmt[256];
235132451Sroberto#else
236285612Sdelphij	const char *	nfmt = fmt;
237132451Sroberto#endif
238285612Sdelphij	int		errval;
239132451Sroberto
240132451Sroberto	/*
241132451Sroberto	 * Save the error value as soon as possible
242132451Sroberto	 */
243132451Sroberto#ifdef SYS_WINNT
244285612Sdelphij	errval = GetLastError();
245285612Sdelphij	if (NO_ERROR == errval)
246285612Sdelphij#endif /* SYS_WINNT */
247285612Sdelphij		errval = errno;
248285612Sdelphij
249285612Sdelphij#ifndef VSNPRINTF_PERCENT_M
250285612Sdelphij	format_errmsg(nfmt, sizeof(nfmt), fmt, errval);
251132451Sroberto#else
252285612Sdelphij	errno = errval;
253132451Sroberto#endif
254285612Sdelphij	return vsnprintf(buf, bufsiz, nfmt, ap);
255285612Sdelphij}
256132451Sroberto
257132451Sroberto
258285612Sdelphijint
259285612Sdelphijmvfprintf(
260285612Sdelphij	FILE *		fp,
261285612Sdelphij	const char *	fmt,
262285612Sdelphij	va_list		ap
263285612Sdelphij	)
264132451Sroberto{
265285612Sdelphij#ifndef VSNPRINTF_PERCENT_M
266285612Sdelphij	char		nfmt[256];
26754359Sroberto#else
268285612Sdelphij	const char *	nfmt = fmt;
269132451Sroberto#endif
270285612Sdelphij	int		errval;
27154359Sroberto
272132451Sroberto	/*
273132451Sroberto	 * Save the error value as soon as possible
274132451Sroberto	 */
275132451Sroberto#ifdef SYS_WINNT
276285612Sdelphij	errval = GetLastError();
277285612Sdelphij	if (NO_ERROR == errval)
278285612Sdelphij#endif /* SYS_WINNT */
279285612Sdelphij		errval = errno;
280285612Sdelphij
281285612Sdelphij#ifndef VSNPRINTF_PERCENT_M
282285612Sdelphij	format_errmsg(nfmt, sizeof(nfmt), fmt, errval);
283132451Sroberto#else
284285612Sdelphij	errno = errval;
285132451Sroberto#endif
286285612Sdelphij	return vfprintf(fp, nfmt, ap);
287285612Sdelphij}
288132451Sroberto
289285612Sdelphij
290285612Sdelphijint
291285612Sdelphijmfprintf(
292285612Sdelphij	FILE *		fp,
293285612Sdelphij	const char *	fmt,
294285612Sdelphij	...
295285612Sdelphij	)
296285612Sdelphij{
297285612Sdelphij	va_list		ap;
298285612Sdelphij	int		rc;
299285612Sdelphij
300132451Sroberto	va_start(ap, fmt);
301285612Sdelphij	rc = mvfprintf(fp, fmt, ap);
302285612Sdelphij	va_end(ap);
303132451Sroberto
304285612Sdelphij	return rc;
305285612Sdelphij}
306132451Sroberto
307285612Sdelphij
308285612Sdelphijint
309285612Sdelphijmprintf(
310285612Sdelphij	const char *	fmt,
311285612Sdelphij	...
312285612Sdelphij	)
313285612Sdelphij{
314285612Sdelphij	va_list		ap;
315285612Sdelphij	int		rc;
316285612Sdelphij
317285612Sdelphij	va_start(ap, fmt);
318285612Sdelphij	rc = mvfprintf(stdout, fmt, ap);
31954359Sroberto	va_end(ap);
320285612Sdelphij
321285612Sdelphij	return rc;
32254359Sroberto}
323285612Sdelphij
324285612Sdelphij
325285612Sdelphijint
326285612Sdelphijmsnprintf(
327285612Sdelphij	char *		buf,
328285612Sdelphij	size_t		bufsiz,
329285612Sdelphij	const char *	fmt,
330285612Sdelphij	...
331285612Sdelphij	)
332285612Sdelphij{
333285612Sdelphij	va_list	ap;
334293893Sglebius	int	rc;
335285612Sdelphij
336285612Sdelphij	va_start(ap, fmt);
337285612Sdelphij	rc = mvsnprintf(buf, bufsiz, fmt, ap);
338285612Sdelphij	va_end(ap);
339285612Sdelphij
340285612Sdelphij	return rc;
341285612Sdelphij}
342285612Sdelphij
343285612Sdelphij
344285612Sdelphijvoid
345285612Sdelphijmsyslog(
346285612Sdelphij	int		level,
347285612Sdelphij	const char *	fmt,
348285612Sdelphij	...
349285612Sdelphij	)
350285612Sdelphij{
351285612Sdelphij	char	buf[1024];
352285612Sdelphij	va_list	ap;
353285612Sdelphij
354285612Sdelphij	va_start(ap, fmt);
355285612Sdelphij	mvsnprintf(buf, sizeof(buf), fmt, ap);
356285612Sdelphij	va_end(ap);
357285612Sdelphij	addto_syslog(level, buf);
358285612Sdelphij}
359285612Sdelphij
360289999Sglebiusvoid
361289999Sglebiusmvsyslog(
362289999Sglebius	int		level,
363289999Sglebius	const char *	fmt,
364289999Sglebius	va_list		ap
365289999Sglebius	)
366289999Sglebius{
367289999Sglebius	char	buf[1024];
368289999Sglebius	mvsnprintf(buf, sizeof(buf), fmt, ap);
369289999Sglebius	addto_syslog(level, buf);
370289999Sglebius}
371285612Sdelphij
372289999Sglebius
373285612Sdelphij/*
374285612Sdelphij * Initialize the logging
375285612Sdelphij *
376285612Sdelphij * Called once per process, including forked children.
377285612Sdelphij */
378285612Sdelphijvoid
379285612Sdelphijinit_logging(
380285612Sdelphij	const char *	name,
381285612Sdelphij	u_int32		def_syslogmask,
382285612Sdelphij	int		is_daemon
383285612Sdelphij	)
384285612Sdelphij{
385285612Sdelphij	static int	was_daemon;
386289999Sglebius	char *		cp;
387285612Sdelphij	const char *	pname;
388285612Sdelphij
389285612Sdelphij	/*
390285612Sdelphij	 * ntpd defaults to only logging sync-category events, when
391285612Sdelphij	 * NLOG() is used to conditionalize.  Other libntp clients
392285612Sdelphij	 * leave it alone so that all NLOG() conditionals will fire.
393285612Sdelphij	 * This presumes all bits lit in ntp_syslogmask can't be
394285612Sdelphij	 * configured via logconfig and all lit is thereby a sentinel
395285612Sdelphij	 * that ntp_syslogmask is still at its default from libntp,
396285612Sdelphij	 * keeping in mind this function is called in forked children
397285612Sdelphij	 * where it has already been called in the parent earlier.
398285612Sdelphij	 * Forked children pass 0 for def_syslogmask.
399285612Sdelphij	 */
400285612Sdelphij	if (INIT_NTP_SYSLOGMASK == ntp_syslogmask &&
401285612Sdelphij	    0 != def_syslogmask)
402285612Sdelphij		ntp_syslogmask = def_syslogmask; /* set more via logconfig */
403285612Sdelphij
404285612Sdelphij	/*
405285612Sdelphij	 * Logging.  This may actually work on the gizmo board.  Find a name
406285612Sdelphij	 * to log with by using the basename
407285612Sdelphij	 */
408285612Sdelphij	cp = strrchr(name, DIR_SEP);
409285612Sdelphij	if (NULL == cp)
410285612Sdelphij		pname = name;
411285612Sdelphij	else
412285612Sdelphij		pname = 1 + cp;	/* skip DIR_SEP */
413285612Sdelphij	progname = estrdup(pname);
414285612Sdelphij#ifdef SYS_WINNT			/* strip ".exe" */
415285612Sdelphij	cp = strrchr(progname, '.');
416285612Sdelphij	if (NULL != cp && !strcasecmp(cp, ".exe"))
417289999Sglebius		*cp = '\0';
418285612Sdelphij#endif
419285612Sdelphij
420285612Sdelphij#if !defined(VMS)
421285612Sdelphij
422285612Sdelphij	if (is_daemon)
423285612Sdelphij		was_daemon = TRUE;
424285612Sdelphij# ifndef LOG_DAEMON
425285612Sdelphij	openlog(progname, LOG_PID);
426285612Sdelphij# else /* LOG_DAEMON */
427285612Sdelphij
428285612Sdelphij#  ifndef LOG_NTP
429285612Sdelphij#	define	LOG_NTP LOG_DAEMON
430285612Sdelphij#  endif
431285612Sdelphij	openlog(progname, LOG_PID | LOG_NDELAY, (was_daemon)
432285612Sdelphij						    ? LOG_NTP
433285612Sdelphij						    : 0);
434285612Sdelphij#  ifdef DEBUG
435285612Sdelphij	if (debug)
436285612Sdelphij		setlogmask(LOG_UPTO(LOG_DEBUG));
437285612Sdelphij	else
438285612Sdelphij#  endif /* DEBUG */
439285612Sdelphij		setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
440285612Sdelphij# endif /* LOG_DAEMON */
441285612Sdelphij#endif	/* !VMS */
442285612Sdelphij}
443285612Sdelphij
444285612Sdelphij
445285612Sdelphij/*
446285612Sdelphij * change_logfile()
447285612Sdelphij *
448285612Sdelphij * Used to change from syslog to a logfile, or from one logfile to
449285612Sdelphij * another, and to reopen logfiles after forking.  On systems where
450285612Sdelphij * ntpd forks, deals with converting relative logfile paths to
451285612Sdelphij * absolute (root-based) because we reopen logfiles after the current
452285612Sdelphij * directory has changed.
453285612Sdelphij */
454285612Sdelphijint
455285612Sdelphijchange_logfile(
456285612Sdelphij	const char *	fname,
457285612Sdelphij	int		leave_crumbs
458285612Sdelphij	)
459285612Sdelphij{
460285612Sdelphij	FILE *		new_file;
461285612Sdelphij	const char *	log_fname;
462285612Sdelphij	char *		abs_fname;
463285612Sdelphij#if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS)
464285612Sdelphij	char		curdir[512];
465285612Sdelphij	size_t		cd_octets;
466285612Sdelphij	size_t		octets;
467285612Sdelphij#endif	/* POSIX */
468285612Sdelphij
469289999Sglebius	REQUIRE(fname != NULL);
470285612Sdelphij	log_fname = fname;
471285612Sdelphij
472285612Sdelphij	/*
473285612Sdelphij	 * In a forked child of a parent which is logging to a file
474285612Sdelphij	 * instead of syslog, syslog_file will be NULL and both
475285612Sdelphij	 * syslog_fname and syslog_abs_fname will be non-NULL.
476285612Sdelphij	 * If we are given the same filename previously opened
477285612Sdelphij	 * and it's still open, there's nothing to do here.
478285612Sdelphij	 */
479285612Sdelphij	if (syslog_file != NULL && syslog_fname != NULL &&
480285612Sdelphij	    0 == strcmp(syslog_fname, log_fname))
481285612Sdelphij		return 0;
482285612Sdelphij
483285612Sdelphij	if (0 == strcmp(log_fname, "stderr")) {
484285612Sdelphij		new_file = stderr;
485285612Sdelphij		abs_fname = estrdup(log_fname);
486285612Sdelphij	} else if (0 == strcmp(log_fname, "stdout")) {
487285612Sdelphij		new_file = stdout;
488285612Sdelphij		abs_fname = estrdup(log_fname);
489285612Sdelphij	} else {
490285612Sdelphij		if (syslog_fname != NULL &&
491285612Sdelphij		    0 == strcmp(log_fname, syslog_fname))
492285612Sdelphij			log_fname = syslog_abs_fname;
493285612Sdelphij#if !defined(SYS_WINNT) && !defined(SYS_VXWORKS) && !defined(VMS)
494285612Sdelphij		if (log_fname != syslog_abs_fname &&
495285612Sdelphij		    DIR_SEP != log_fname[0] &&
496285612Sdelphij		    0 != strcmp(log_fname, "stderr") &&
497285612Sdelphij		    0 != strcmp(log_fname, "stdout") &&
498285612Sdelphij		    NULL != getcwd(curdir, sizeof(curdir))) {
499285612Sdelphij			cd_octets = strlen(curdir);
500285612Sdelphij			/* trim any trailing '/' */
501285612Sdelphij			if (cd_octets > 1 &&
502285612Sdelphij			    DIR_SEP == curdir[cd_octets - 1])
503285612Sdelphij				cd_octets--;
504285612Sdelphij			octets = cd_octets;
505285612Sdelphij			octets += 1;	/* separator '/' */
506285612Sdelphij			octets += strlen(log_fname);
507285612Sdelphij			octets += 1;	/* NUL terminator */
508285612Sdelphij			abs_fname = emalloc(octets);
509285612Sdelphij			snprintf(abs_fname, octets, "%.*s%c%s",
510285612Sdelphij				 (int)cd_octets, curdir, DIR_SEP,
511285612Sdelphij				 log_fname);
512285612Sdelphij		} else
513285612Sdelphij#endif
514285612Sdelphij			abs_fname = estrdup(log_fname);
515285612Sdelphij		TRACE(1, ("attempting to open log %s\n", abs_fname));
516285612Sdelphij		new_file = fopen(abs_fname, "a");
517285612Sdelphij	}
518285612Sdelphij
519285612Sdelphij	if (NULL == new_file) {
520285612Sdelphij		free(abs_fname);
521285612Sdelphij		return -1;
522285612Sdelphij	}
523285612Sdelphij
524285612Sdelphij	/* leave a pointer in the old log */
525285612Sdelphij	if (leave_crumbs && (syslogit || log_fname != syslog_abs_fname))
526285612Sdelphij		msyslog(LOG_NOTICE, "switching logging to file %s",
527285612Sdelphij			abs_fname);
528285612Sdelphij
529285612Sdelphij	if (syslog_file != NULL &&
530285612Sdelphij	    syslog_file != stderr && syslog_file != stdout &&
531285612Sdelphij	    fileno(syslog_file) != fileno(new_file))
532285612Sdelphij		fclose(syslog_file);
533285612Sdelphij	syslog_file = new_file;
534285612Sdelphij	if (log_fname == syslog_abs_fname) {
535285612Sdelphij		free(abs_fname);
536285612Sdelphij	} else {
537285612Sdelphij		if (syslog_abs_fname != NULL &&
538285612Sdelphij		    syslog_abs_fname != syslog_fname)
539285612Sdelphij			free(syslog_abs_fname);
540285612Sdelphij		if (syslog_fname != NULL)
541285612Sdelphij			free(syslog_fname);
542285612Sdelphij		syslog_fname = estrdup(log_fname);
543285612Sdelphij		syslog_abs_fname = abs_fname;
544285612Sdelphij	}
545285612Sdelphij	syslogit = FALSE;
546285612Sdelphij
547285612Sdelphij	return 0;
548285612Sdelphij}
549285612Sdelphij
550285612Sdelphij
551285612Sdelphij/*
552285612Sdelphij * setup_logfile()
553285612Sdelphij *
554285612Sdelphij * Redirect logging to a file if requested with -l/--logfile or via
555285612Sdelphij * ntp.conf logfile directive.
556285612Sdelphij *
557285612Sdelphij * This routine is invoked three different times in the sequence of a
558285612Sdelphij * typical daemon ntpd with DNS lookups to do.  First it is invoked in
559285612Sdelphij * the original ntpd process, then again in the daemon after closing
560285612Sdelphij * all descriptors.  In both of those cases, ntp.conf has not been
561285612Sdelphij * processed, so only -l/--logfile will trigger logfile redirection in
562285612Sdelphij * those invocations.  Finally, if DNS names are resolved, the worker
563285612Sdelphij * child invokes this routine after its fork and close of all
564285612Sdelphij * descriptors.  In this case, ntp.conf has been processed and any
565285612Sdelphij * "logfile" directive needs to be honored in the child as well.
566285612Sdelphij */
567285612Sdelphijvoid
568285612Sdelphijsetup_logfile(
569285612Sdelphij	const char *	name
570285612Sdelphij	)
571285612Sdelphij{
572285612Sdelphij	if (NULL == syslog_fname && NULL != name) {
573285612Sdelphij		if (-1 == change_logfile(name, TRUE))
574285612Sdelphij			msyslog(LOG_ERR, "Cannot open log file %s, %m",
575285612Sdelphij				name);
576285612Sdelphij		return ;
577285612Sdelphij	}
578285612Sdelphij	if (NULL == syslog_fname)
579285612Sdelphij		return;
580285612Sdelphij
581285612Sdelphij	if (-1 == change_logfile(syslog_fname, FALSE))
582285612Sdelphij		msyslog(LOG_ERR, "Cannot reopen log file %s, %m",
583285612Sdelphij			syslog_fname);
584285612Sdelphij}
585