ntpd.c revision 272461
1231990Smp/*
259243Sobrien * ntpd.c - main program for the fixed point NTP daemon
359243Sobrien */
459243Sobrien
559243Sobrien#ifdef HAVE_CONFIG_H
659243Sobrien# include <config.h>
759243Sobrien#endif
859243Sobrien
959243Sobrien#include "ntp_machine.h"
1059243Sobrien#include "ntpd.h"
1159243Sobrien#include "ntp_io.h"
1259243Sobrien#include "ntp_stdlib.h"
1359243Sobrien#include <ntp_random.h>
1459243Sobrien
1559243Sobrien#ifdef SIM
1659243Sobrien# include "ntpsim.h"
17100616Smp# include "ntpdsim-opts.h"
1859243Sobrien#else
1959243Sobrien# include "ntpd-opts.h"
2059243Sobrien#endif
2159243Sobrien
2259243Sobrien#ifdef HAVE_UNISTD_H
2359243Sobrien# include <unistd.h>
2459243Sobrien#endif
2559243Sobrien#ifdef HAVE_SYS_STAT_H
2659243Sobrien# include <sys/stat.h>
2759243Sobrien#endif
2859243Sobrien#include <stdio.h>
2959243Sobrien#if !defined(VMS)	/*wjm*/
3059243Sobrien# ifdef HAVE_SYS_PARAM_H
3159243Sobrien#  include <sys/param.h>
3259243Sobrien# endif
3359243Sobrien#endif /* VMS */
3459243Sobrien#ifdef HAVE_SYS_SIGNAL_H
35231990Smp# include <sys/signal.h>
3659243Sobrien#else
37231990Smp# include <signal.h>
3859243Sobrien#endif
3959243Sobrien#ifdef HAVE_SYS_IOCTL_H
40145479Smp# include <sys/ioctl.h>
41167465Smp#endif /* HAVE_SYS_IOCTL_H */
4259243Sobrien#ifdef HAVE_SYS_RESOURCE_H
4359243Sobrien# include <sys/resource.h>
44167465Smp#endif /* HAVE_SYS_RESOURCE_H */
45167465Smp#if defined(HAVE_RTPRIO)
4659243Sobrien# ifdef HAVE_SYS_RESOURCE_H
4759243Sobrien#  include <sys/resource.h>
4859243Sobrien# endif
4959243Sobrien# ifdef HAVE_SYS_LOCK_H
5059243Sobrien#  include <sys/lock.h>
5159243Sobrien# endif
5259243Sobrien# include <sys/rtprio.h>
5359243Sobrien#else
5459243Sobrien# ifdef HAVE_PLOCK
5559243Sobrien#  ifdef HAVE_SYS_LOCK_H
5659243Sobrien#	include <sys/lock.h>
5759243Sobrien#  endif
5859243Sobrien# endif
59231990Smp#endif
60231990Smp#if defined(HAVE_SCHED_SETSCHEDULER)
61231990Smp# ifdef HAVE_SCHED_H
62231990Smp#  include <sched.h>
63231990Smp# else
64231990Smp#  ifdef HAVE_SYS_SCHED_H
65231990Smp#   include <sys/sched.h>
66231990Smp#  endif
67231990Smp# endif
68231990Smp#endif
69231990Smp#if defined(HAVE_SYS_MMAN_H)
70231990Smp# include <sys/mman.h>
71231990Smp#endif
72231990Smp
73231990Smp#ifdef HAVE_TERMIOS_H
74231990Smp# include <termios.h>
75231990Smp#endif
76231990Smp
77231990Smp#ifdef SYS_DOMAINOS
78231990Smp# include <apollo/base.h>
79231990Smp#endif /* SYS_DOMAINOS */
80231990Smp
81231990Smp#include "recvbuff.h"
82231990Smp#include "ntp_cmdargs.h"
83231990Smp
84231990Smp#if 0				/* HMS: I don't think we need this. 961223 */
85231990Smp#ifdef LOCK_PROCESS
86231990Smp# ifdef SYS_SOLARIS
87231990Smp#  include <sys/mman.h>
88231990Smp# else
89231990Smp#  include <sys/lock.h>
90231990Smp# endif
91231990Smp#endif
92231990Smp#endif
93231990Smp
94231990Smp#ifdef _AIX
95231990Smp# include <ulimit.h>
96231990Smp#endif /* _AIX */
97231990Smp
98231990Smp#ifdef SCO5_CLOCK
99231990Smp# include <sys/ci/ciioctl.h>
100231990Smp#endif
101231990Smp
102231990Smp#ifdef HAVE_DROPROOT
103231990Smp# include <ctype.h>
104231990Smp# include <grp.h>
105231990Smp# include <pwd.h>
106231990Smp#ifdef HAVE_LINUX_CAPABILITIES
107231990Smp# include <sys/capability.h>
108231990Smp# include <sys/prctl.h>
109231990Smp#endif
110231990Smp#endif
111231990Smp
112231990Smp/*
113231990Smp * Signals we catch for debugging.	If not debugging we ignore them.
114231990Smp */
115231990Smp#define MOREDEBUGSIG	SIGUSR1
116231990Smp#define LESSDEBUGSIG	SIGUSR2
117231990Smp
118231990Smp/*
119231990Smp * Signals which terminate us gracefully.
120231990Smp */
121231990Smp#ifndef SYS_WINNT
122231990Smp# define SIGDIE1 	SIGHUP
123231990Smp# define SIGDIE3 	SIGQUIT
124231990Smp# define SIGDIE2 	SIGINT
125231990Smp# define SIGDIE4 	SIGTERM
126231990Smp#endif /* SYS_WINNT */
127231990Smp
128231990Smp#ifdef HAVE_DNSREGISTRATION
129231990Smp#include <dns_sd.h>
130231990SmpDNSServiceRef mdns;
131231990Smp#endif
132231990Smp
133231990Smp/*
134231990Smp * Scheduling priority we run at
135231990Smp */
136231990Smp#define NTPD_PRIO	(-12)
137231990Smp
138231990Smpint priority_done = 2;		/* 0 - Set priority */
139231990Smp				/* 1 - priority is OK where it is */
140231990Smp				/* 2 - Don't set priority */
141231990Smp				/* 1 and 2 are pretty much the same */
142231990Smp
14359243Sobrien#ifdef DEBUG
144231990Smp/*
145231990Smp * Debugging flag
146231990Smp */
14759243Sobrienvolatile int debug = 0;		/* No debugging by default */
148145479Smp#endif
14959243Sobrien
15059243Sobrienint	listen_to_virtual_ips = 1;
15159243Sobrienconst char *specific_interface = NULL;        /* interface name or IP address to bind to */
15259243Sobrien
15359243Sobrien/*
15459243Sobrien * No-fork flag.  If set, we do not become a background daemon.
155167465Smp */
156167465Smpint nofork = 0;			/* Fork by default */
157167465Smp
158167465Smp#ifdef HAVE_DROPROOT
15959243Sobrienint droproot = 0;
160167465Smpchar *user = NULL;		/* User to switch to */
16159243Sobrienchar *group = NULL;		/* group to switch to */
16259243Sobrienchar *chrootdir = NULL;		/* directory to chroot to */
163231990Smpint sw_uid;
164231990Smpint sw_gid;
16559243Sobrienchar *endp;
16659243Sobrienstruct group *gr;
167231990Smpstruct passwd *pw;
168231990Smp#endif /* HAVE_DROPROOT */
169231990Smp
170231990Smp/*
171231990Smp * Initializing flag.  All async routines watch this and only do their
172231990Smp * thing when it is clear.
173231990Smp */
174231990Smpint initializing;
175231990Smp
176231990Smp/*
177231990Smp * Version declaration
178231990Smp */
179231990Smpextern const char *Version;
180231990Smp
181231990Smpchar const *progname;
182231990Smp
183231990Smpint was_alarmed;
184231990Smp
185231990Smp#ifdef DECL_SYSCALL
186231990Smp/*
187231990Smp * We put this here, since the argument profile is syscall-specific
188231990Smp */
189231990Smpextern int syscall	P((int, ...));
190231990Smp#endif /* DECL_SYSCALL */
191231990Smp
192231990Smp
193231990Smp#ifdef	SIGDIE2
194231990Smpstatic	RETSIGTYPE	finish		P((int));
195231990Smp#endif	/* SIGDIE2 */
196231990Smp
197231990Smp#ifdef	DEBUG
198231990Smp#ifndef SYS_WINNT
199231990Smpstatic	RETSIGTYPE	moredebug	P((int));
200231990Smpstatic	RETSIGTYPE	lessdebug	P((int));
201231990Smp#endif
202231990Smp#else /* not DEBUG */
203231990Smpstatic	RETSIGTYPE	no_debug	P((int));
204231990Smp#endif	/* not DEBUG */
205231990Smp
206231990Smpint 		ntpdmain		P((int, char **));
207231990Smpstatic void	set_process_priority	P((void));
208231990Smpstatic void	init_logging		P((char const *));
209231990Smpstatic void	setup_logfile		P((void));
210231990Smp
211231990Smp/*
212231990Smp * Initialize the logging
213231990Smp */
214231990Smpvoid
215231990Smpinit_logging(char const *name)
216231990Smp{
217231990Smp	const char *cp;
218231990Smp
219231990Smp	/*
220231990Smp	 * Logging.  This may actually work on the gizmo board.  Find a name
221231990Smp	 * to log with by using the basename
222231990Smp	 */
223231990Smp	cp = strrchr(name, '/');
224231990Smp	if (cp == 0)
225231990Smp		cp = name;
226231990Smp	else
227231990Smp		cp++;
228231990Smp
229231990Smp#if !defined(VMS)
230231990Smp
231231990Smp# ifndef LOG_DAEMON
232231990Smp	openlog(cp, LOG_PID);
233231990Smp# else /* LOG_DAEMON */
234231990Smp
235231990Smp#  ifndef LOG_NTP
236231990Smp#	define	LOG_NTP LOG_DAEMON
237231990Smp#  endif
238231990Smp	openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP);
239231990Smp#  ifdef DEBUG
240231990Smp	if (debug)
241231990Smp		setlogmask(LOG_UPTO(LOG_DEBUG));
242231990Smp	else
243231990Smp#  endif /* DEBUG */
244231990Smp		setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
245231990Smp# endif /* LOG_DAEMON */
246231990Smp#endif	/* !SYS_WINNT && !VMS */
247231990Smp
248231990Smp	NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
249231990Smp		msyslog(LOG_NOTICE, "%s", Version);
250231990Smp}
251231990Smp
252231990Smp
253231990Smp/*
254231990Smp * See if we should redirect the logfile
255231990Smp */
256231990Smp
257231990Smpvoid
258231990Smpsetup_logfile(
259231990Smp	void
260231990Smp	)
261231990Smp{
262231990Smp	if (HAVE_OPT( LOGFILE )) {
263231990Smp		const char *my_optarg = OPT_ARG( LOGFILE );
264231990Smp		FILE *new_file;
265231990Smp
266231990Smp		if(strcmp(my_optarg, "stderr") == 0)
267231990Smp			new_file = stderr;
268231990Smp		else if(strcmp(my_optarg, "stdout") == 0)
269231990Smp			new_file = stdout;
270231990Smp		else
271231990Smp			new_file = fopen(my_optarg, "a");
272231990Smp		if (new_file != NULL) {
273231990Smp			NLOG(NLOG_SYSINFO)
274231990Smp				msyslog(LOG_NOTICE, "logging to file %s", my_optarg);
275231990Smp			if (syslog_file != NULL &&
276231990Smp				fileno(syslog_file) != fileno(new_file))
277231990Smp				(void)fclose(syslog_file);
278231990Smp
279231990Smp			syslog_file = new_file;
280231990Smp			syslogit = 0;
281231990Smp		}
282231990Smp		else
283231990Smp			msyslog(LOG_ERR,
284231990Smp				"Cannot open log file %s",
285231990Smp				my_optarg);
286231990Smp	}
287231990Smp}
288231990Smp
289231990Smp#ifdef SIM
290231990Smpint
291231990Smpmain(
292231990Smp	int argc,
293231990Smp	char *argv[]
294231990Smp	)
295231990Smp{
296231990Smp	return ntpsim(argc, argv);
297231990Smp}
298231990Smp#else /* SIM */
299231990Smp#ifdef NO_MAIN_ALLOWED
300231990SmpCALL(ntpd,"ntpd",ntpdmain);
301231990Smp#else
302231990Smp#ifndef SYS_WINNT
303231990Smpint
304231990Smpmain(
305231990Smp	int argc,
306231990Smp	char *argv[]
307231990Smp	)
308231990Smp{
309231990Smp	return ntpdmain(argc, argv);
310231990Smp}
311231990Smp#endif /* SYS_WINNT */
312231990Smp#endif /* NO_MAIN_ALLOWED */
313231990Smp#endif /* SIM */
314231990Smp
315231990Smp#ifdef _AIX
316231990Smp/*
317231990Smp * OK. AIX is different than solaris in how it implements plock().
318231990Smp * If you do NOT adjust the stack limit, you will get the MAXIMUM
319231990Smp * stack size allocated and PINNED with you program. To check the
320231990Smp * value, use ulimit -a.
321231990Smp *
322231990Smp * To fix this, we create an automatic variable and set our stack limit
323231990Smp * to that PLUS 32KB of extra space (we need some headroom).
324231990Smp *
325231990Smp * This subroutine gets the stack address.
326231990Smp *
327231990Smp * Grover Davidson and Matt Ladendorf
328231990Smp *
329231990Smp */
330231990Smpstatic char *
331231990Smpget_aix_stack(void)
332231990Smp{
333231990Smp	char ch;
334231990Smp	return (&ch);
335231990Smp}
336231990Smp
337231990Smp/*
338231990Smp * Signal handler for SIGDANGER.
339231990Smp */
340231990Smpstatic void
341231990Smpcatch_danger(int signo)
342231990Smp{
343231990Smp	msyslog(LOG_INFO, "ntpd: setpgid(): %m");
344231990Smp	/* Make the system believe we'll free something, but don't do it! */
345231990Smp	return;
346231990Smp}
347231990Smp#endif /* _AIX */
348231990Smp
349231990Smp/*
350231990Smp * Set the process priority
351231990Smp */
352231990Smpstatic void
353231990Smpset_process_priority(void)
354231990Smp{
355231990Smp
356231990Smp#ifdef DEBUG
357231990Smp	if (debug > 1)
358231990Smp		msyslog(LOG_DEBUG, "set_process_priority: %s: priority_done is <%d>",
359231990Smp			((priority_done)
360231990Smp			 ? "Leave priority alone"
361231990Smp			 : "Attempt to set priority"
362231990Smp				),
363231990Smp			priority_done);
364231990Smp#endif /* DEBUG */
365231990Smp
366231990Smp#ifdef SYS_WINNT
367231990Smp	priority_done += NT_set_process_priority();
368231990Smp#endif
369231990Smp
370231990Smp#if defined(HAVE_SCHED_SETSCHEDULER)
371231990Smp	if (!priority_done) {
372231990Smp		extern int config_priority_override, config_priority;
373231990Smp		int pmax, pmin;
374231990Smp		struct sched_param sched;
375231990Smp
376231990Smp		pmax = sched_get_priority_max(SCHED_FIFO);
377231990Smp		sched.sched_priority = pmax;
378231990Smp		if ( config_priority_override ) {
379231990Smp			pmin = sched_get_priority_min(SCHED_FIFO);
380231990Smp			if ( config_priority > pmax )
381231990Smp				sched.sched_priority = pmax;
382231990Smp			else if ( config_priority < pmin )
383231990Smp				sched.sched_priority = pmin;
384231990Smp			else
385231990Smp				sched.sched_priority = config_priority;
386231990Smp		}
387231990Smp		if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 )
388231990Smp			msyslog(LOG_ERR, "sched_setscheduler(): %m");
389231990Smp		else
390231990Smp			++priority_done;
391231990Smp	}
392231990Smp#endif /* HAVE_SCHED_SETSCHEDULER */
393231990Smp#if defined(HAVE_RTPRIO)
394231990Smp# ifdef RTP_SET
395231990Smp	if (!priority_done) {
396231990Smp		struct rtprio srtp;
397231990Smp
398231990Smp		srtp.type = RTP_PRIO_REALTIME;	/* was: RTP_PRIO_NORMAL */
399231990Smp		srtp.prio = 0;		/* 0 (hi) -> RTP_PRIO_MAX (31,lo) */
400231990Smp
401231990Smp		if (rtprio(RTP_SET, getpid(), &srtp) < 0)
402231990Smp			msyslog(LOG_ERR, "rtprio() error: %m");
403231990Smp		else
404231990Smp			++priority_done;
405231990Smp	}
406231990Smp# else /* not RTP_SET */
407231990Smp	if (!priority_done) {
408231990Smp		if (rtprio(0, 120) < 0)
409231990Smp			msyslog(LOG_ERR, "rtprio() error: %m");
410231990Smp		else
411231990Smp			++priority_done;
412231990Smp	}
413231990Smp# endif /* not RTP_SET */
414231990Smp#endif  /* HAVE_RTPRIO */
415231990Smp#if defined(NTPD_PRIO) && NTPD_PRIO != 0
416231990Smp# ifdef HAVE_ATT_NICE
417231990Smp	if (!priority_done) {
418231990Smp		errno = 0;
419231990Smp		if (-1 == nice (NTPD_PRIO) && errno != 0)
420231990Smp			msyslog(LOG_ERR, "nice() error: %m");
421231990Smp		else
422231990Smp			++priority_done;
423231990Smp	}
424231990Smp# endif /* HAVE_ATT_NICE */
425231990Smp# ifdef HAVE_BSD_NICE
426231990Smp	if (!priority_done) {
427231990Smp		if (-1 == setpriority(PRIO_PROCESS, 0, NTPD_PRIO))
428231990Smp			msyslog(LOG_ERR, "setpriority() error: %m");
429231990Smp		else
430231990Smp			++priority_done;
431231990Smp	}
432231990Smp# endif /* HAVE_BSD_NICE */
433231990Smp#endif /* NTPD_PRIO && NTPD_PRIO != 0 */
434231990Smp	if (!priority_done)
435231990Smp		msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority");
436231990Smp}
437231990Smp
438231990Smp
439231990Smp/*
440231990Smp * Main program.  Initialize us, disconnect us from the tty if necessary,
441231990Smp * and loop waiting for I/O and/or timer expiries.
442231990Smp */
443231990Smpint
444231990Smpntpdmain(
445231990Smp	int argc,
446231990Smp	char *argv[]
447231990Smp	)
448231990Smp{
449231990Smp	l_fp now;
450231990Smp	struct recvbuf *rbuf;
451231990Smp#ifdef _AIX			/* HMS: ifdef SIGDANGER? */
452231990Smp	struct sigaction sa;
453231990Smp#endif
454231990Smp
455231990Smp	progname = argv[0];
456231990Smp
457231990Smp	initializing = 1;		/* mark that we are initializing */
458231990Smp
459231990Smp	{
460231990Smp		int optct = optionProcess(
461231990Smp#ifdef SIM
462231990Smp					  &ntpdsimOptions
463231990Smp#else
464231990Smp					  &ntpdOptions
465231990Smp#endif
466231990Smp					  , argc, argv);
467231990Smp		argc -= optct;
468231990Smp		argv += optct;
469231990Smp	}
470231990Smp
471231990Smp	/* HMS: is this lame? Should we process -l first? */
472231990Smp
473231990Smp	init_logging(progname);		/* Open the log file */
474231990Smp
475231990Smp#ifdef HAVE_UMASK
476231990Smp	{
477231990Smp		mode_t uv;
478231990Smp
479231990Smp		uv = umask(0);
480231990Smp		if(uv)
481231990Smp			(void) umask(uv);
482231990Smp		else
483231990Smp			(void) umask(022);
484231990Smp	}
485231990Smp#endif
486231990Smp
487231990Smp#if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
488231990Smp	{
489231990Smp		uid_t uid;
490231990Smp
491231990Smp		uid = getuid();
492231990Smp		if (uid)
493231990Smp		{
494231990Smp			msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid);
495231990Smp			printf("must be run as root, not uid %ld", (long)uid);
496231990Smp			exit(1);
497231990Smp		}
498231990Smp	}
499231990Smp#endif
500231990Smp
501231990Smp#ifdef OPENSSL
502231990Smp	if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) {
503231990Smp		msyslog(LOG_ERR,
504231990Smp		    "ntpd: OpenSSL version mismatch. Built against %lx, you have %lx\n",
505231990Smp		    OPENSSL_VERSION_NUMBER, SSLeay());
506231990Smp		exit(1);
507231990Smp	}
508231990Smp#endif
509231990Smp
510231990Smp	/* getstartup(argc, argv); / * startup configuration, may set debug */
511231990Smp
512231990Smp#ifdef DEBUG
513231990Smp	debug = DESC(DEBUG_LEVEL).optOccCt;
514231990Smp	if (debug)
515231990Smp	    printf("%s\n", Version);
516231990Smp#endif
517231990Smp
518231990Smp/*
519231990Smp * Enable the Multi-Media Timer for Windows?
520231990Smp */
521231990Smp#ifdef SYS_WINNT
522231990Smp	if (HAVE_OPT( MODIFYMMTIMER ))
523231990Smp		set_mm_timer(MM_TIMER_HIRES);
524231990Smp#endif
525231990Smp
526231990Smp	if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT ))
527231990Smp		nofork = 1;
528231990Smp
529231990Smp	if (HAVE_OPT( NOVIRTUALIPS ))
530231990Smp		listen_to_virtual_ips = 0;
531231990Smp
532231990Smp	if (HAVE_OPT( INTERFACE )) {
533231990Smp#if 0
534231990Smp		int	ifacect = STACKCT_OPT( INTERFACE );
535231990Smp		char**	ifaces  = STACKLST_OPT( INTERFACE );
536231990Smp
537231990Smp		/* malloc space for the array of names */
538231990Smp		while (ifacect-- > 0) {
539231990Smp			next_iface = *ifaces++;
540231990Smp		}
541231990Smp#else
542231990Smp		specific_interface = OPT_ARG( INTERFACE );
543231990Smp#endif
544231990Smp	}
545231990Smp
546231990Smp	if (HAVE_OPT( NICE ))
547231990Smp		priority_done = 0;
548231990Smp
549231990Smp#if defined(HAVE_SCHED_SETSCHEDULER)
550231990Smp	if (HAVE_OPT( PRIORITY )) {
551231990Smp		config_priority = OPT_VALUE_PRIORITY;
552231990Smp		config_priority_override = 1;
553231990Smp		priority_done = 0;
554231990Smp	}
555231990Smp#endif
556231990Smp
557231990Smp#ifdef SYS_WINNT
558231990Smp	/*
559231990Smp	 * Initialize the time structures and variables
560231990Smp	 */
561231990Smp	init_winnt_time();
562231990Smp#endif
563231990Smp
564231990Smp	setup_logfile();
565231990Smp
566231990Smp	/*
567231990Smp	 * Initialize random generator and public key pair
568231990Smp	 */
569231990Smp	get_systime(&now);
570231990Smp
571231990Smp	ntp_srandom((int)(now.l_i * now.l_uf));
572231990Smp
573231990Smp#ifdef HAVE_DNSREGISTRATION
574231990Smp	/* HMS: does this have to happen this early? */
575231990Smp	msyslog(LOG_INFO, "Attemping to register mDNS");
576231990Smp	if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) {
577231990Smp		msyslog(LOG_ERR, "Unable to register mDNS");
578231990Smp	}
579231990Smp#endif
580231990Smp
581231990Smp#if !defined(VMS)
582231990Smp# ifndef NODETACH
583231990Smp	/*
584231990Smp	 * Detach us from the terminal.  May need an #ifndef GIZMO.
585231990Smp	 */
586231990Smp	if (
587231990Smp#  ifdef DEBUG
588231990Smp	    !debug &&
589231990Smp#  endif /* DEBUG */
590231990Smp	    !nofork)
591231990Smp	{
592231990Smp#  ifndef SYS_WINNT
593231990Smp#   ifdef HAVE_DAEMON
594231990Smp		daemon(0, 0);
595231990Smp#   else /* not HAVE_DAEMON */
596231990Smp		if (fork())	/* HMS: What about a -1? */
597231990Smp			exit(0);
598231990Smp
599231990Smp		{
600231990Smp#if !defined(F_CLOSEM)
601231990Smp			u_long s;
602145479Smp			int max_fd;
603167465Smp#endif /* not F_CLOSEM */
60459243Sobrien
605167465Smp#if defined(F_CLOSEM)
60659243Sobrien			/*
60759243Sobrien			 * From 'Writing Reliable AIX Daemons,' SG24-4946-00,
60859243Sobrien			 * by Eric Agar (saves us from doing 32767 system
60959243Sobrien			 * calls)
61059243Sobrien			 */
61159243Sobrien			if (fcntl(0, F_CLOSEM, 0) == -1)
61259243Sobrien			    msyslog(LOG_ERR, "ntpd: failed to close open files(): %m");
61359243Sobrien#else  /* not F_CLOSEM */
61459243Sobrien
61559243Sobrien# if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
616231990Smp			max_fd = sysconf(_SC_OPEN_MAX);
61759243Sobrien# else /* HAVE_SYSCONF && _SC_OPEN_MAX */
61859243Sobrien			max_fd = getdtablesize();
619231990Smp# endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
620231990Smp			for (s = 0; s < max_fd; s++)
621231990Smp				(void) close((int)s);
622231990Smp#endif /* not F_CLOSEM */
623231990Smp			(void) open("/", 0);
624231990Smp			(void) dup2(0, 1);
625231990Smp			(void) dup2(0, 2);
626231990Smp#ifdef SYS_DOMAINOS
62759243Sobrien			{
628231990Smp				uid_$t puid;
629231990Smp				status_$t st;
630231990Smp
631231990Smp				proc2_$who_am_i(&puid);
632231990Smp				proc2_$make_server(&puid, &st);
633231990Smp			}
634231990Smp#endif /* SYS_DOMAINOS */
635231990Smp#if defined(HAVE_SETPGID) || defined(HAVE_SETSID)
636231990Smp# ifdef HAVE_SETSID
637231990Smp			if (setsid() == (pid_t)-1)
638231990Smp				msyslog(LOG_ERR, "ntpd: setsid(): %m");
639231990Smp# else
640231990Smp			if (setpgid(0, 0) == -1)
641231990Smp				msyslog(LOG_ERR, "ntpd: setpgid(): %m");
642231990Smp# endif
643231990Smp#else /* HAVE_SETPGID || HAVE_SETSID */
644231990Smp			{
645231990Smp# if defined(TIOCNOTTY)
646231990Smp				int fid;
647231990Smp
648231990Smp				fid = open("/dev/tty", 2);
649231990Smp				if (fid >= 0)
650231990Smp				{
651231990Smp					(void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);
652231990Smp					(void) close(fid);
653231990Smp				}
654231990Smp# endif /* defined(TIOCNOTTY) */
655231990Smp# ifdef HAVE_SETPGRP_0
656231990Smp				(void) setpgrp();
657231990Smp# else /* HAVE_SETPGRP_0 */
658231990Smp				(void) setpgrp(0, getpid());
659231990Smp# endif /* HAVE_SETPGRP_0 */
660231990Smp			}
661231990Smp#endif /* HAVE_SETPGID || HAVE_SETSID */
662231990Smp#ifdef _AIX
663231990Smp			/* Don't get killed by low-on-memory signal. */
664231990Smp			sa.sa_handler = catch_danger;
665231990Smp			sigemptyset(&sa.sa_mask);
666231990Smp			sa.sa_flags = SA_RESTART;
667231990Smp
668231990Smp			(void) sigaction(SIGDANGER, &sa, NULL);
669231990Smp#endif /* _AIX */
670231990Smp		}
671231990Smp#   endif /* not HAVE_DAEMON */
672231990Smp#  endif /* SYS_WINNT */
673231990Smp	}
674231990Smp# endif /* NODETACH */
675231990Smp#endif /* VMS */
676231990Smp
677231990Smp	setup_logfile();	/* We lost any redirect when we daemonized */
678231990Smp
679231990Smp#ifdef SCO5_CLOCK
680231990Smp	/*
681231990Smp	 * SCO OpenServer's system clock offers much more precise timekeeping
682231990Smp	 * on the base CPU than the other CPUs (for multiprocessor systems),
683231990Smp	 * so we must lock to the base CPU.
684231990Smp	 */
685231990Smp	{
686231990Smp	    int fd = open("/dev/at1", O_RDONLY);
687231990Smp	    if (fd >= 0) {
688231990Smp		int zero = 0;
689231990Smp		if (ioctl(fd, ACPU_LOCK, &zero) < 0)
690231990Smp		    msyslog(LOG_ERR, "cannot lock to base CPU: %m");
691231990Smp		close( fd );
692231990Smp	    } /* else ...
693231990Smp	       *   If we can't open the device, this probably just isn't
694231990Smp	       *   a multiprocessor system, so we're A-OK.
695231990Smp	       */
696231990Smp	}
697231990Smp#endif
698231990Smp
699231990Smp#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE)
700231990Smp# ifdef HAVE_SETRLIMIT
701231990Smp	/*
702231990Smp	 * Set the stack limit to something smaller, so that we don't lock a lot
703231990Smp	 * of unused stack memory.
704231990Smp	 */
705231990Smp	{
706231990Smp	    struct rlimit rl;
707231990Smp
708231990Smp	    /* HMS: must make the rlim_cur amount configurable */
709231990Smp	    if (getrlimit(RLIMIT_STACK, &rl) != -1
710231990Smp		&& (rl.rlim_cur = 50 * 4096) < rl.rlim_max)
711231990Smp	    {
712231990Smp		    if (setrlimit(RLIMIT_STACK, &rl) == -1)
713231990Smp		    {
714231990Smp			    msyslog(LOG_ERR,
715231990Smp				"Cannot adjust stack limit for mlockall: %m");
716231990Smp		    }
717231990Smp	    }
718231990Smp#  ifdef RLIMIT_MEMLOCK
719231990Smp	    /*
720231990Smp	     * The default RLIMIT_MEMLOCK is very low on Linux systems.
721231990Smp	     * Unless we increase this limit malloc calls are likely to
722231990Smp	     * fail if we drop root privlege.  To be useful the value
723231990Smp	     * has to be larger than the largest ntpd resident set size.
724231990Smp	     */
725231990Smp	    rl.rlim_cur = rl.rlim_max = 32*1024*1024;
726231990Smp	    if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) {
727231990Smp	    	msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
728231990Smp	    }
729231990Smp#  endif /* RLIMIT_MEMLOCK */
730231990Smp	}
731231990Smp# endif /* HAVE_SETRLIMIT */
732231990Smp	/*
733231990Smp	 * lock the process into memory
734231990Smp	 */
735231990Smp	if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0)
736231990Smp		msyslog(LOG_ERR, "mlockall(): %m");
737231990Smp#else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
738231990Smp# ifdef HAVE_PLOCK
739231990Smp#  ifdef PROCLOCK
740231990Smp#   ifdef _AIX
741231990Smp	/*
742231990Smp	 * set the stack limit for AIX for plock().
743231990Smp	 * see get_aix_stack() for more info.
744231990Smp	 */
745231990Smp	if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0)
746231990Smp	{
747231990Smp		msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m");
748231990Smp	}
749231990Smp#   endif /* _AIX */
750231990Smp	/*
751231990Smp	 * lock the process into memory
752231990Smp	 */
753231990Smp	if (plock(PROCLOCK) < 0)
754231990Smp		msyslog(LOG_ERR, "plock(PROCLOCK): %m");
755231990Smp#  else /* not PROCLOCK */
756231990Smp#   ifdef TXTLOCK
757231990Smp	/*
758231990Smp	 * Lock text into ram
759231990Smp	 */
760231990Smp	if (plock(TXTLOCK) < 0)
761231990Smp		msyslog(LOG_ERR, "plock(TXTLOCK) error: %m");
762231990Smp#   else /* not TXTLOCK */
763231990Smp	msyslog(LOG_ERR, "plock() - don't know what to lock!");
764231990Smp#   endif /* not TXTLOCK */
765231990Smp#  endif /* not PROCLOCK */
766231990Smp# endif /* HAVE_PLOCK */
767231990Smp#endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
768231990Smp
769231990Smp	/*
770231990Smp	 * Set up signals we pay attention to locally.
771231990Smp	 */
772231990Smp#ifdef SIGDIE1
773231990Smp	(void) signal_no_reset(SIGDIE1, finish);
774231990Smp#endif	/* SIGDIE1 */
775231990Smp#ifdef SIGDIE2
776231990Smp	(void) signal_no_reset(SIGDIE2, finish);
777231990Smp#endif	/* SIGDIE2 */
778231990Smp#ifdef SIGDIE3
779231990Smp	(void) signal_no_reset(SIGDIE3, finish);
780231990Smp#endif	/* SIGDIE3 */
781231990Smp#ifdef SIGDIE4
782231990Smp	(void) signal_no_reset(SIGDIE4, finish);
783231990Smp#endif	/* SIGDIE4 */
784231990Smp
785231990Smp#ifdef SIGBUS
786231990Smp	(void) signal_no_reset(SIGBUS, finish);
787231990Smp#endif /* SIGBUS */
788231990Smp
789231990Smp#if !defined(SYS_WINNT) && !defined(VMS)
790231990Smp# ifdef DEBUG
791231990Smp	(void) signal_no_reset(MOREDEBUGSIG, moredebug);
792231990Smp	(void) signal_no_reset(LESSDEBUGSIG, lessdebug);
793231990Smp# else
794231990Smp	(void) signal_no_reset(MOREDEBUGSIG, no_debug);
795231990Smp	(void) signal_no_reset(LESSDEBUGSIG, no_debug);
796231990Smp# endif /* DEBUG */
797231990Smp#endif /* !SYS_WINNT && !VMS */
798231990Smp
799231990Smp	/*
800231990Smp	 * Set up signals we should never pay attention to.
801231990Smp	 */
802231990Smp#if defined SIGPIPE
803231990Smp	(void) signal_no_reset(SIGPIPE, SIG_IGN);
804231990Smp#endif	/* SIGPIPE */
805231990Smp
806231990Smp	/*
807231990Smp	 * Call the init_ routines to initialize the data structures.
808231990Smp	 *
809231990Smp	 * Exactly what command-line options are we expecting here?
810231990Smp	 */
811231990Smp	init_auth();
812231990Smp	init_util();
813231990Smp	init_restrict();
814231990Smp	init_mon();
815231990Smp	init_timer();
816231990Smp	init_lib();
817231990Smp	init_request();
818231990Smp	init_control();
819231990Smp	init_peer();
820231990Smp#ifdef REFCLOCK
821231990Smp	init_refclock();
822231990Smp#endif
823231990Smp	set_process_priority();
824231990Smp	init_proto();		/* Call at high priority */
825231990Smp	init_io();
826231990Smp	init_loopfilter();
827231990Smp	mon_start(MON_ON);	/* monitor on by default now	  */
828231990Smp				/* turn off in config if unwanted */
829231990Smp
830231990Smp	/*
831231990Smp	 * Get the configuration.  This is done in a separate module
832231990Smp	 * since this will definitely be different for the gizmo board.
833231990Smp	 */
834231990Smp
835231990Smp	getconfig(argc, argv);
836231990Smp
837231990Smp	loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
838231990Smp#ifdef OPENSSL
839231990Smp	crypto_setup();
840231990Smp#endif /* OPENSSL */
841231990Smp	initializing = 0;
842231990Smp
843231990Smp#ifdef HAVE_DROPROOT
844231990Smp	if( droproot ) {
845231990Smp		/* Drop super-user privileges and chroot now if the OS supports this */
846231990Smp
847231990Smp#ifdef HAVE_LINUX_CAPABILITIES
848231990Smp		/* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */
849231990Smp		if( prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1 ) {
850231990Smp			msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" );
851231990Smp			exit(-1);
852231990Smp		}
853231990Smp#else
854231990Smp		/* we need a user to switch to */
855231990Smp		if( user == NULL ) {
856231990Smp			msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" );
857231990Smp			exit(-1);
858231990Smp		}
859231990Smp#endif /* HAVE_LINUX_CAPABILITIES */
860231990Smp
861231990Smp		if (user != NULL) {
862231990Smp			if (isdigit((unsigned char)*user)) {
863231990Smp				sw_uid = (uid_t)strtoul(user, &endp, 0);
864231990Smp				if (*endp != '\0')
865231990Smp					goto getuser;
866231990Smp			} else {
867231990Smpgetuser:
868231990Smp				if ((pw = getpwnam(user)) != NULL) {
869231990Smp					sw_uid = pw->pw_uid;
870231990Smp				} else {
871231990Smp					errno = 0;
872231990Smp					msyslog(LOG_ERR, "Cannot find user `%s'", user);
873231990Smp					exit (-1);
874231990Smp				}
875231990Smp			}
876231990Smp		}
877231990Smp		if (group != NULL) {
878231990Smp			if (isdigit((unsigned char)*group)) {
879231990Smp				sw_gid = (gid_t)strtoul(group, &endp, 0);
880231990Smp				if (*endp != '\0')
881231990Smp					goto getgroup;
882231990Smp			} else {
883231990Smpgetgroup:
884231990Smp				if ((gr = getgrnam(group)) != NULL) {
885231990Smp					sw_gid = gr->gr_gid;
886231990Smp				} else {
887231990Smp					errno = 0;
888231990Smp					msyslog(LOG_ERR, "Cannot find group `%s'", group);
889231990Smp					exit (-1);
890231990Smp				}
891231990Smp			}
892231990Smp		}
893231990Smp
894231990Smp		if( chrootdir ) {
895231990Smp			/* make sure cwd is inside the jail: */
896231990Smp			if( chdir(chrootdir) ) {
897231990Smp				msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir);
898231990Smp				exit (-1);
899231990Smp			}
900231990Smp			if( chroot(chrootdir) ) {
901231990Smp				msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir);
902231990Smp				exit (-1);
903231990Smp			}
904231990Smp		}
905231990Smp		if (group && setgid(sw_gid)) {
906231990Smp			msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
907231990Smp			exit (-1);
908231990Smp		}
909231990Smp		if (group && setegid(sw_gid)) {
910231990Smp			msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
911231990Smp			exit (-1);
912231990Smp		}
913231990Smp		if (user && setuid(sw_uid)) {
914231990Smp			msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
915231990Smp			exit (-1);
916231990Smp		}
917231990Smp		if (user && seteuid(sw_uid)) {
918231990Smp			msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
919231990Smp			exit (-1);
920231990Smp		}
921231990Smp
922231990Smp#ifndef HAVE_LINUX_CAPABILITIES
923231990Smp		/*
924231990Smp		 * for now assume that the privilege to bind to privileged ports
925231990Smp		 * is associated with running with uid 0 - should be refined on
926231990Smp		 * ports that allow binding to NTP_PORT with uid != 0
927231990Smp		 */
928231990Smp		disable_dynamic_updates |= (sw_uid != 0);  /* also notifies routing message listener */
929231990Smp#endif
930231990Smp
93159243Sobrien		if (disable_dynamic_updates && interface_interval) {
932231990Smp			interface_interval = 0;
933231990Smp			msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking");
934231990Smp		}
935231990Smp
936231990Smp#ifdef HAVE_LINUX_CAPABILITIES
937231990Smp		do {
93859243Sobrien			/*
939231990Smp			 *  We may be running under non-root uid now, but we still hold full root privileges!
940145479Smp			 *  We drop all of them, except for the crucial one or two: cap_sys_time and
941167465Smp			 *  cap_net_bind_service if doing dynamic interface tracking.
942231990Smp			 */
943231990Smp			cap_t caps;
94459243Sobrien			char *captext = interface_interval ?
94559243Sobrien			       	"cap_sys_time,cap_net_bind_service=ipe" :
94659243Sobrien			       	"cap_sys_time=ipe";
947231990Smp			if( ! ( caps = cap_from_text( captext ) ) ) {
948231990Smp				msyslog( LOG_ERR, "cap_from_text() failed: %m" );
949231990Smp				exit(-1);
950231990Smp			}
951231990Smp			if( cap_set_proc( caps ) == -1 ) {
952231990Smp				msyslog( LOG_ERR, "cap_set_proc() failed to drop root privileges: %m" );
953231990Smp				exit(-1);
954231990Smp			}
955231990Smp			cap_free( caps );
956231990Smp		} while(0);
957231990Smp#endif /* HAVE_LINUX_CAPABILITIES */
958231990Smp
959231990Smp	}    /* if( droproot ) */
960231990Smp#endif /* HAVE_DROPROOT */
961231990Smp
962231990Smp	/*
963231990Smp	 * Report that we're up to any trappers
96459243Sobrien	 */
96559243Sobrien	report_event(EVNT_SYSRESTART, (struct peer *)0);
966231990Smp
967231990Smp	/*
968231990Smp	 * Use select() on all on all input fd's for unlimited
969231990Smp	 * time.  select() will terminate on SIGALARM or on the
970231990Smp	 * reception of input.	Using select() means we can't do
971231990Smp	 * robust signal handling and we get a potential race
97259243Sobrien	 * between checking for alarms and doing the select().
97359243Sobrien	 * Mostly harmless, I think.
97459243Sobrien	 */
97559243Sobrien	/* On VMS, I suspect that select() can't be interrupted
97659243Sobrien	 * by a "signal" either, so I take the easy way out and
97759243Sobrien	 * have select() time out after one second.
97859243Sobrien	 * System clock updates really aren't time-critical,
97959243Sobrien	 * and - lacking a hardware reference clock - I have
98059243Sobrien	 * yet to learn about anything else that is.
981167465Smp	 */
98259243Sobrien#if defined(HAVE_IO_COMPLETION_PORT)
98359243Sobrien
984167465Smp	for (;;) {
98559243Sobrien		GetReceivedBuffers();
98659243Sobrien#else /* normal I/O */
98759243Sobrien
98859243Sobrien	BLOCK_IO_AND_ALARM();
989231990Smp	was_alarmed = 0;
99059243Sobrien	for (;;)
99159243Sobrien	{
992231990Smp# if !defined(HAVE_SIGNALED_IO)
99359243Sobrien		extern fd_set activefds;
994231990Smp		extern int maxactivefd;
99559243Sobrien
99659243Sobrien		fd_set rdfdes;
997231990Smp		int nfound;
99859243Sobrien# endif
999167465Smp
100059243Sobrien		if (alarm_flag) 	/* alarmed? */
100159243Sobrien		{
100259243Sobrien			was_alarmed = 1;
100359243Sobrien			alarm_flag = 0;
100459243Sobrien		}
100559243Sobrien
100659243Sobrien		if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE)
1007231990Smp		{
1008231990Smp			/*
100959243Sobrien			 * Nothing to do.  Wait for something.
1010231990Smp			 */
1011231990Smp# ifndef HAVE_SIGNALED_IO
1012231990Smp			rdfdes = activefds;
1013231990Smp#  if defined(VMS) || defined(SYS_VXWORKS)
1014231990Smp			/* make select() wake up after one second */
1015231990Smp			{
1016231990Smp				struct timeval t1;
1017231990Smp
1018231990Smp				t1.tv_sec = 1; t1.tv_usec = 0;
1019231990Smp				nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
1020231990Smp						(fd_set *)0, &t1);
1021231990Smp			}
1022231990Smp#  else
1023231990Smp			nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
1024231990Smp					(fd_set *)0, (struct timeval *)0);
1025231990Smp#  endif /* VMS */
1026231990Smp			if (nfound > 0)
1027231990Smp			{
1028231990Smp				l_fp ts;
1029231990Smp
1030231990Smp				get_systime(&ts);
1031231990Smp
1032231990Smp				(void)input_handler(&ts);
1033231990Smp			}
1034231990Smp			else if (nfound == -1 && errno != EINTR)
1035231990Smp				netsyslog(LOG_ERR, "select() error: %m");
1036231990Smp#  ifdef DEBUG
1037231990Smp			else if (debug > 5)
103859243Sobrien				netsyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
103959243Sobrien#  endif /* DEBUG */
104059243Sobrien# else /* HAVE_SIGNALED_IO */
104159243Sobrien
1042167465Smp			wait_for_signal();
104359243Sobrien# endif /* HAVE_SIGNALED_IO */
1044231990Smp			if (alarm_flag) 	/* alarmed? */
1045231990Smp			{
1046231990Smp				was_alarmed = 1;
104759243Sobrien				alarm_flag = 0;
104859243Sobrien			}
1049231990Smp		}
1050167465Smp
105159243Sobrien		if (was_alarmed)
105259243Sobrien		{
1053231990Smp			UNBLOCK_IO_AND_ALARM();
1054231990Smp			/*
1055231990Smp			 * Out here, signals are unblocked.  Call timer routine
1056231990Smp			 * to process expiry.
1057231990Smp			 */
105859243Sobrien			timer();
1059231990Smp			was_alarmed = 0;
1060231990Smp                        BLOCK_IO_AND_ALARM();
1061231990Smp		}
1062231990Smp
1063231990Smp#endif /* HAVE_IO_COMPLETION_PORT */
1064231990Smp
1065231990Smp#ifdef DEBUG_TIMING
1066231990Smp		{
1067231990Smp			l_fp pts;
1068231990Smp			l_fp tsa, tsb;
1069231990Smp			int bufcount = 0;
1070231990Smp
1071231990Smp			get_systime(&pts);
1072231990Smp			tsa = pts;
1073231990Smp#endif
1074231990Smp			rbuf = get_full_recv_buffer();
1075231990Smp			while (rbuf != NULL)
1076231990Smp			{
1077231990Smp				if (alarm_flag)
1078231990Smp				{
1079231990Smp					was_alarmed = 1;
1080231990Smp					alarm_flag = 0;
1081231990Smp				}
1082231990Smp				UNBLOCK_IO_AND_ALARM();
1083231990Smp
1084231990Smp				if (was_alarmed)
1085231990Smp				{	/* avoid timer starvation during lengthy I/O handling */
1086231990Smp					timer();
1087231990Smp					was_alarmed = 0;
1088231990Smp				}
1089231990Smp
1090231990Smp				/*
1091231990Smp				 * Call the data procedure to handle each received
1092231990Smp				 * packet.
1093231990Smp				 */
1094231990Smp				if (rbuf->receiver != NULL)	/* This should always be true */
1095231990Smp				{
1096231990Smp#ifdef DEBUG_TIMING
1097231990Smp					l_fp dts = pts;
1098231990Smp
1099231990Smp					L_SUB(&dts, &rbuf->recv_time);
1100231990Smp					DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9)));
1101231990Smp					collect_timing(rbuf, "buffer processing delay", 1, &dts);
1102231990Smp					bufcount++;
1103231990Smp#endif
1104231990Smp					(rbuf->receiver)(rbuf);
1105231990Smp				} else {
1106231990Smp					msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING");
1107231990Smp					abort();
1108231990Smp				}
1109231990Smp
1110231990Smp				BLOCK_IO_AND_ALARM();
1111231990Smp				freerecvbuf(rbuf);
1112231990Smp				rbuf = get_full_recv_buffer();
1113231990Smp			}
1114231990Smp#ifdef DEBUG_TIMING
1115231990Smp			get_systime(&tsb);
1116231990Smp			L_SUB(&tsb, &tsa);
1117231990Smp			if (bufcount) {
1118231990Smp				collect_timing(NULL, "processing", bufcount, &tsb);
1119231990Smp				DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9)));
1120231990Smp			}
1121231990Smp		}
1122231990Smp#endif
1123231990Smp
1124231990Smp		/*
1125231990Smp		 * Go around again
1126231990Smp		 */
1127231990Smp	}
1128231990Smp	UNBLOCK_IO_AND_ALARM();
112959243Sobrien	return 1;
113059243Sobrien}
1131167465Smp
113259243Sobrien
113359243Sobrien#ifdef SIGDIE2
113459243Sobrien/*
113559243Sobrien * finish - exit gracefully
113659243Sobrien */
113759243Sobrienstatic RETSIGTYPE
113859243Sobrienfinish(
113959243Sobrien	int sig
114059243Sobrien	)
114159243Sobrien{
114259243Sobrien
114359243Sobrien	msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig);
114459243Sobrien	write_stats();
114559243Sobrien#ifdef HAVE_DNSREGISTRATION
114659243Sobrien	if (mdns != NULL)
114759243Sobrien	DNSServiceRefDeallocate(mdns);
114859243Sobrien#endif
114959243Sobrien
115059243Sobrien	switch (sig)
115159243Sobrien	{
115259243Sobrien# ifdef SIGBUS
115359243Sobrien		case SIGBUS:
115459243Sobrien		printf("\nfinish(SIGBUS)\n");
115559243Sobrien		exit(0);
115659243Sobrien# endif
115759243Sobrien		case 0: 		/* Should never happen... */
115859243Sobrien		return;
115959243Sobrien		default:
116059243Sobrien		exit(0);
116159243Sobrien	}
116259243Sobrien}
116359243Sobrien#endif	/* SIGDIE2 */
116459243Sobrien
116559243Sobrien
116659243Sobrien#ifdef DEBUG
116759243Sobrien#ifndef SYS_WINNT
116859243Sobrien/*
116959243Sobrien * moredebug - increase debugging verbosity
1170231990Smp */
1171231990Smpstatic RETSIGTYPE
1172231990Smpmoredebug(
117359243Sobrien	int sig
117459243Sobrien	)
1175167465Smp{
117659243Sobrien	int saved_errno = errno;
1177167465Smp
117859243Sobrien	if (debug < 255)
117959243Sobrien	{
1180167465Smp		debug++;
1181167465Smp		msyslog(LOG_DEBUG, "debug raised to %d", debug);
1182167465Smp	}
1183167465Smp	errno = saved_errno;
1184167465Smp}
1185231990Smp
118659243Sobrien/*
118759243Sobrien * lessdebug - decrease debugging verbosity
118859243Sobrien */
118959243Sobrienstatic RETSIGTYPE
1190167465Smplessdebug(
1191167465Smp	int sig
1192167465Smp	)
1193167465Smp{
119459243Sobrien	int saved_errno = errno;
1195167465Smp
119659243Sobrien	if (debug > 0)
119759243Sobrien	{
1198167465Smp		debug--;
119959243Sobrien		msyslog(LOG_DEBUG, "debug lowered to %d", debug);
120059243Sobrien	}
1201167465Smp	errno = saved_errno;
120259243Sobrien}
1203167465Smp#endif
120459243Sobrien#else /* not DEBUG */
1205145479Smp#ifndef SYS_WINNT
1206167465Smp/*
1207167465Smp * no_debug - We don't do the debug here.
1208167465Smp */
1209167465Smpstatic RETSIGTYPE
1210167465Smpno_debug(
1211167465Smp	int sig
1212167465Smp	)
1213167465Smp{
1214167465Smp	int saved_errno = errno;
121559243Sobrien
121659243Sobrien	msyslog(LOG_DEBUG, "ntpd not compiled for debugging (signal %d)", sig);
1217167465Smp	errno = saved_errno;
121859243Sobrien}
1219167465Smp#endif  /* not SYS_WINNT */
122059243Sobrien#endif	/* not DEBUG */
122159243Sobrien