154359Sroberto/*
254359Sroberto * ntpd.c - main program for the fixed point NTP daemon
354359Sroberto */
482498Sroberto
554359Sroberto#ifdef HAVE_CONFIG_H
654359Sroberto# include <config.h>
754359Sroberto#endif
854359Sroberto
9106163Sroberto#include "ntp_machine.h"
1082498Sroberto#include "ntpd.h"
1182498Sroberto#include "ntp_io.h"
1282498Sroberto#include "ntp_stdlib.h"
13182007Sroberto#include <ntp_random.h>
1482498Sroberto
15132451Sroberto#ifdef SIM
16182007Sroberto# include "ntpsim.h"
17182007Sroberto# include "ntpdsim-opts.h"
18182007Sroberto#else
19182007Sroberto# include "ntpd-opts.h"
20132451Sroberto#endif
21132451Sroberto
2254359Sroberto#ifdef HAVE_UNISTD_H
2354359Sroberto# include <unistd.h>
2454359Sroberto#endif
2554359Sroberto#ifdef HAVE_SYS_STAT_H
2654359Sroberto# include <sys/stat.h>
2754359Sroberto#endif
2854359Sroberto#include <stdio.h>
29200576Sroberto#if !defined(VMS)	/*wjm*/
30200576Sroberto# ifdef HAVE_SYS_PARAM_H
31200576Sroberto#  include <sys/param.h>
32106163Sroberto# endif
33200576Sroberto#endif /* VMS */
34200576Sroberto#ifdef HAVE_SYS_SIGNAL_H
35200576Sroberto# include <sys/signal.h>
3654359Sroberto#else
3754359Sroberto# include <signal.h>
38200576Sroberto#endif
39200576Sroberto#ifdef HAVE_SYS_IOCTL_H
40200576Sroberto# include <sys/ioctl.h>
41200576Sroberto#endif /* HAVE_SYS_IOCTL_H */
42200576Sroberto#ifdef HAVE_SYS_RESOURCE_H
43200576Sroberto# include <sys/resource.h>
44200576Sroberto#endif /* HAVE_SYS_RESOURCE_H */
4554359Sroberto#if defined(HAVE_RTPRIO)
4654359Sroberto# ifdef HAVE_SYS_RESOURCE_H
4754359Sroberto#  include <sys/resource.h>
4854359Sroberto# endif
4954359Sroberto# ifdef HAVE_SYS_LOCK_H
5054359Sroberto#  include <sys/lock.h>
5154359Sroberto# endif
5254359Sroberto# include <sys/rtprio.h>
5354359Sroberto#else
5454359Sroberto# ifdef HAVE_PLOCK
5554359Sroberto#  ifdef HAVE_SYS_LOCK_H
5654359Sroberto#	include <sys/lock.h>
5754359Sroberto#  endif
5854359Sroberto# endif
5954359Sroberto#endif
6054359Sroberto#if defined(HAVE_SCHED_SETSCHEDULER)
6154359Sroberto# ifdef HAVE_SCHED_H
6254359Sroberto#  include <sched.h>
6354359Sroberto# else
6454359Sroberto#  ifdef HAVE_SYS_SCHED_H
6554359Sroberto#   include <sys/sched.h>
6654359Sroberto#  endif
6754359Sroberto# endif
6854359Sroberto#endif
6954359Sroberto#if defined(HAVE_SYS_MMAN_H)
7054359Sroberto# include <sys/mman.h>
7154359Sroberto#endif
7254359Sroberto
7354359Sroberto#ifdef HAVE_TERMIOS_H
7454359Sroberto# include <termios.h>
7554359Sroberto#endif
7654359Sroberto
7754359Sroberto#ifdef SYS_DOMAINOS
7854359Sroberto# include <apollo/base.h>
7954359Sroberto#endif /* SYS_DOMAINOS */
8054359Sroberto
8154359Sroberto#include "recvbuff.h"
8282498Sroberto#include "ntp_cmdargs.h"
8354359Sroberto
8454359Sroberto#if 0				/* HMS: I don't think we need this. 961223 */
8554359Sroberto#ifdef LOCK_PROCESS
8654359Sroberto# ifdef SYS_SOLARIS
8754359Sroberto#  include <sys/mman.h>
8854359Sroberto# else
8954359Sroberto#  include <sys/lock.h>
9054359Sroberto# endif
9154359Sroberto#endif
9254359Sroberto#endif
9354359Sroberto
9454359Sroberto#ifdef _AIX
9582498Sroberto# include <ulimit.h>
9654359Sroberto#endif /* _AIX */
9754359Sroberto
9854359Sroberto#ifdef SCO5_CLOCK
9982498Sroberto# include <sys/ci/ciioctl.h>
10054359Sroberto#endif
10154359Sroberto
102182007Sroberto#ifdef HAVE_DROPROOT
103132451Sroberto# include <ctype.h>
104132451Sroberto# include <grp.h>
105132451Sroberto# include <pwd.h>
106182007Sroberto#ifdef HAVE_LINUX_CAPABILITIES
107182007Sroberto# include <sys/capability.h>
108182007Sroberto# include <sys/prctl.h>
109132451Sroberto#endif
110182007Sroberto#endif
11182498Sroberto
11254359Sroberto/*
11354359Sroberto * Signals we catch for debugging.	If not debugging we ignore them.
11454359Sroberto */
11554359Sroberto#define MOREDEBUGSIG	SIGUSR1
11654359Sroberto#define LESSDEBUGSIG	SIGUSR2
11754359Sroberto
11854359Sroberto/*
11954359Sroberto * Signals which terminate us gracefully.
12054359Sroberto */
12154359Sroberto#ifndef SYS_WINNT
12282498Sroberto# define SIGDIE1 	SIGHUP
12382498Sroberto# define SIGDIE3 	SIGQUIT
12482498Sroberto# define SIGDIE2 	SIGINT
12582498Sroberto# define SIGDIE4 	SIGTERM
12654359Sroberto#endif /* SYS_WINNT */
12754359Sroberto
128182007Sroberto#ifdef HAVE_DNSREGISTRATION
129182007Sroberto#include <dns_sd.h>
130182007SrobertoDNSServiceRef mdns;
131182007Sroberto#endif
13254359Sroberto
13354359Sroberto/*
13454359Sroberto * Scheduling priority we run at
13554359Sroberto */
13682498Sroberto#define NTPD_PRIO	(-12)
13754359Sroberto
13882498Srobertoint priority_done = 2;		/* 0 - Set priority */
13982498Sroberto				/* 1 - priority is OK where it is */
14082498Sroberto				/* 2 - Don't set priority */
14182498Sroberto				/* 1 and 2 are pretty much the same */
14282498Sroberto
143182007Sroberto#ifdef DEBUG
14454359Sroberto/*
14554359Sroberto * Debugging flag
14654359Sroberto */
147182007Srobertovolatile int debug = 0;		/* No debugging by default */
148182007Sroberto#endif
14954359Sroberto
150182007Srobertoint	listen_to_virtual_ips = 1;
151182007Srobertoconst char *specific_interface = NULL;        /* interface name or IP address to bind to */
152132451Sroberto
153132451Sroberto/*
15454359Sroberto * No-fork flag.  If set, we do not become a background daemon.
15554359Sroberto */
156182007Srobertoint nofork = 0;			/* Fork by default */
15754359Sroberto
158182007Sroberto#ifdef HAVE_DROPROOT
159182007Srobertoint droproot = 0;
160132451Srobertochar *user = NULL;		/* User to switch to */
161132451Srobertochar *group = NULL;		/* group to switch to */
162132451Srobertochar *chrootdir = NULL;		/* directory to chroot to */
163132451Srobertoint sw_uid;
164132451Srobertoint sw_gid;
165132451Srobertochar *endp;
166132451Srobertostruct group *gr;
167132451Srobertostruct passwd *pw;
168182007Sroberto#endif /* HAVE_DROPROOT */
169132451Sroberto
17054359Sroberto/*
17154359Sroberto * Initializing flag.  All async routines watch this and only do their
17254359Sroberto * thing when it is clear.
17354359Sroberto */
17454359Srobertoint initializing;
17554359Sroberto
17654359Sroberto/*
17754359Sroberto * Version declaration
17854359Sroberto */
17954359Srobertoextern const char *Version;
18054359Sroberto
181182007Srobertochar const *progname;
182182007Sroberto
18354359Srobertoint was_alarmed;
18454359Sroberto
18554359Sroberto#ifdef DECL_SYSCALL
18654359Sroberto/*
18754359Sroberto * We put this here, since the argument profile is syscall-specific
18854359Sroberto */
18954359Srobertoextern int syscall	P((int, ...));
19054359Sroberto#endif /* DECL_SYSCALL */
19154359Sroberto
19254359Sroberto
19354359Sroberto#ifdef	SIGDIE2
19454359Srobertostatic	RETSIGTYPE	finish		P((int));
19554359Sroberto#endif	/* SIGDIE2 */
19654359Sroberto
19754359Sroberto#ifdef	DEBUG
198132451Sroberto#ifndef SYS_WINNT
19954359Srobertostatic	RETSIGTYPE	moredebug	P((int));
20054359Srobertostatic	RETSIGTYPE	lessdebug	P((int));
201132451Sroberto#endif
20254359Sroberto#else /* not DEBUG */
20354359Srobertostatic	RETSIGTYPE	no_debug	P((int));
20454359Sroberto#endif	/* not DEBUG */
20554359Sroberto
20654359Srobertoint 		ntpdmain		P((int, char **));
20754359Srobertostatic void	set_process_priority	P((void));
208182007Srobertostatic void	init_logging		P((char const *));
209182007Srobertostatic void	setup_logfile		P((void));
21054359Sroberto
211182007Sroberto/*
212182007Sroberto * Initialize the logging
213182007Sroberto */
214182007Srobertovoid
215182007Srobertoinit_logging(char const *name)
216182007Sroberto{
217182007Sroberto	const char *cp;
218182007Sroberto
219182007Sroberto	/*
220182007Sroberto	 * Logging.  This may actually work on the gizmo board.  Find a name
221182007Sroberto	 * to log with by using the basename
222182007Sroberto	 */
223182007Sroberto	cp = strrchr(name, '/');
224182007Sroberto	if (cp == 0)
225182007Sroberto		cp = name;
226182007Sroberto	else
227182007Sroberto		cp++;
228182007Sroberto
229182007Sroberto#if !defined(VMS)
230182007Sroberto
231182007Sroberto# ifndef LOG_DAEMON
232182007Sroberto	openlog(cp, LOG_PID);
233182007Sroberto# else /* LOG_DAEMON */
234182007Sroberto
235182007Sroberto#  ifndef LOG_NTP
236182007Sroberto#	define	LOG_NTP LOG_DAEMON
237182007Sroberto#  endif
238182007Sroberto	openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP);
239182007Sroberto#  ifdef DEBUG
240182007Sroberto	if (debug)
241182007Sroberto		setlogmask(LOG_UPTO(LOG_DEBUG));
242182007Sroberto	else
243182007Sroberto#  endif /* DEBUG */
244182007Sroberto		setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
245182007Sroberto# endif /* LOG_DAEMON */
246182007Sroberto#endif	/* !SYS_WINNT && !VMS */
247182007Sroberto
248182007Sroberto	NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
249182007Sroberto		msyslog(LOG_NOTICE, "%s", Version);
250182007Sroberto}
251182007Sroberto
252182007Sroberto
253182007Sroberto/*
254182007Sroberto * See if we should redirect the logfile
255182007Sroberto */
256182007Sroberto
257182007Srobertovoid
258182007Srobertosetup_logfile(
259182007Sroberto	void
260182007Sroberto	)
261182007Sroberto{
262182007Sroberto	if (HAVE_OPT( LOGFILE )) {
263182007Sroberto		const char *my_optarg = OPT_ARG( LOGFILE );
264182007Sroberto		FILE *new_file;
265182007Sroberto
266182007Sroberto		if(strcmp(my_optarg, "stderr") == 0)
267182007Sroberto			new_file = stderr;
268182007Sroberto		else if(strcmp(my_optarg, "stdout") == 0)
269182007Sroberto			new_file = stdout;
270182007Sroberto		else
271182007Sroberto			new_file = fopen(my_optarg, "a");
272182007Sroberto		if (new_file != NULL) {
273182007Sroberto			NLOG(NLOG_SYSINFO)
274182007Sroberto				msyslog(LOG_NOTICE, "logging to file %s", my_optarg);
275182007Sroberto			if (syslog_file != NULL &&
276182007Sroberto				fileno(syslog_file) != fileno(new_file))
277182007Sroberto				(void)fclose(syslog_file);
278182007Sroberto
279182007Sroberto			syslog_file = new_file;
280182007Sroberto			syslogit = 0;
281182007Sroberto		}
282182007Sroberto		else
283182007Sroberto			msyslog(LOG_ERR,
284182007Sroberto				"Cannot open log file %s",
285182007Sroberto				my_optarg);
286182007Sroberto	}
287182007Sroberto}
288182007Sroberto
289132451Sroberto#ifdef SIM
290132451Srobertoint
291132451Srobertomain(
292132451Sroberto	int argc,
293132451Sroberto	char *argv[]
294132451Sroberto	)
295132451Sroberto{
296132451Sroberto	return ntpsim(argc, argv);
297132451Sroberto}
298132451Sroberto#else /* SIM */
29954359Sroberto#ifdef NO_MAIN_ALLOWED
30054359SrobertoCALL(ntpd,"ntpd",ntpdmain);
30154359Sroberto#else
302182007Sroberto#ifndef SYS_WINNT
30354359Srobertoint
30454359Srobertomain(
30554359Sroberto	int argc,
30654359Sroberto	char *argv[]
30754359Sroberto	)
30854359Sroberto{
30954359Sroberto	return ntpdmain(argc, argv);
31054359Sroberto}
311182007Sroberto#endif /* SYS_WINNT */
312182007Sroberto#endif /* NO_MAIN_ALLOWED */
313132451Sroberto#endif /* SIM */
31454359Sroberto
31554359Sroberto#ifdef _AIX
31654359Sroberto/*
31754359Sroberto * OK. AIX is different than solaris in how it implements plock().
31854359Sroberto * If you do NOT adjust the stack limit, you will get the MAXIMUM
31954359Sroberto * stack size allocated and PINNED with you program. To check the
32054359Sroberto * value, use ulimit -a.
32154359Sroberto *
32254359Sroberto * To fix this, we create an automatic variable and set our stack limit
32354359Sroberto * to that PLUS 32KB of extra space (we need some headroom).
32454359Sroberto *
32554359Sroberto * This subroutine gets the stack address.
32654359Sroberto *
32754359Sroberto * Grover Davidson and Matt Ladendorf
32854359Sroberto *
32954359Sroberto */
33054359Srobertostatic char *
33154359Srobertoget_aix_stack(void)
33254359Sroberto{
33354359Sroberto	char ch;
33454359Sroberto	return (&ch);
33554359Sroberto}
33654359Sroberto
33754359Sroberto/*
33854359Sroberto * Signal handler for SIGDANGER.
33954359Sroberto */
34054359Srobertostatic void
34154359Srobertocatch_danger(int signo)
34254359Sroberto{
34354359Sroberto	msyslog(LOG_INFO, "ntpd: setpgid(): %m");
34454359Sroberto	/* Make the system believe we'll free something, but don't do it! */
34554359Sroberto	return;
34654359Sroberto}
34754359Sroberto#endif /* _AIX */
34854359Sroberto
34954359Sroberto/*
35054359Sroberto * Set the process priority
35154359Sroberto */
35254359Srobertostatic void
35354359Srobertoset_process_priority(void)
35454359Sroberto{
35554359Sroberto
35682498Sroberto#ifdef DEBUG
35782498Sroberto	if (debug > 1)
35882498Sroberto		msyslog(LOG_DEBUG, "set_process_priority: %s: priority_done is <%d>",
35982498Sroberto			((priority_done)
36082498Sroberto			 ? "Leave priority alone"
36182498Sroberto			 : "Attempt to set priority"
36282498Sroberto				),
36382498Sroberto			priority_done);
36482498Sroberto#endif /* DEBUG */
36582498Sroberto
36654359Sroberto#ifdef SYS_WINNT
36782498Sroberto	priority_done += NT_set_process_priority();
36856746Sroberto#endif
36956746Sroberto
37082498Sroberto#if defined(HAVE_SCHED_SETSCHEDULER)
37182498Sroberto	if (!priority_done) {
37254359Sroberto		extern int config_priority_override, config_priority;
37354359Sroberto		int pmax, pmin;
37454359Sroberto		struct sched_param sched;
37554359Sroberto
37654359Sroberto		pmax = sched_get_priority_max(SCHED_FIFO);
37754359Sroberto		sched.sched_priority = pmax;
37854359Sroberto		if ( config_priority_override ) {
37954359Sroberto			pmin = sched_get_priority_min(SCHED_FIFO);
38054359Sroberto			if ( config_priority > pmax )
38154359Sroberto				sched.sched_priority = pmax;
38254359Sroberto			else if ( config_priority < pmin )
38354359Sroberto				sched.sched_priority = pmin;
38454359Sroberto			else
38554359Sroberto				sched.sched_priority = config_priority;
38654359Sroberto		}
38754359Sroberto		if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 )
38854359Sroberto			msyslog(LOG_ERR, "sched_setscheduler(): %m");
38954359Sroberto		else
39082498Sroberto			++priority_done;
39154359Sroberto	}
39282498Sroberto#endif /* HAVE_SCHED_SETSCHEDULER */
39382498Sroberto#if defined(HAVE_RTPRIO)
39482498Sroberto# ifdef RTP_SET
39582498Sroberto	if (!priority_done) {
39654359Sroberto		struct rtprio srtp;
39754359Sroberto
39854359Sroberto		srtp.type = RTP_PRIO_REALTIME;	/* was: RTP_PRIO_NORMAL */
39954359Sroberto		srtp.prio = 0;		/* 0 (hi) -> RTP_PRIO_MAX (31,lo) */
40054359Sroberto
40154359Sroberto		if (rtprio(RTP_SET, getpid(), &srtp) < 0)
40254359Sroberto			msyslog(LOG_ERR, "rtprio() error: %m");
40354359Sroberto		else
40482498Sroberto			++priority_done;
40554359Sroberto	}
40682498Sroberto# else /* not RTP_SET */
40782498Sroberto	if (!priority_done) {
40854359Sroberto		if (rtprio(0, 120) < 0)
40954359Sroberto			msyslog(LOG_ERR, "rtprio() error: %m");
41054359Sroberto		else
41182498Sroberto			++priority_done;
41254359Sroberto	}
41382498Sroberto# endif /* not RTP_SET */
41482498Sroberto#endif  /* HAVE_RTPRIO */
41582498Sroberto#if defined(NTPD_PRIO) && NTPD_PRIO != 0
41682498Sroberto# ifdef HAVE_ATT_NICE
41782498Sroberto	if (!priority_done) {
41854359Sroberto		errno = 0;
41954359Sroberto		if (-1 == nice (NTPD_PRIO) && errno != 0)
42054359Sroberto			msyslog(LOG_ERR, "nice() error: %m");
42154359Sroberto		else
42282498Sroberto			++priority_done;
42354359Sroberto	}
42482498Sroberto# endif /* HAVE_ATT_NICE */
42582498Sroberto# ifdef HAVE_BSD_NICE
42682498Sroberto	if (!priority_done) {
42754359Sroberto		if (-1 == setpriority(PRIO_PROCESS, 0, NTPD_PRIO))
42854359Sroberto			msyslog(LOG_ERR, "setpriority() error: %m");
42954359Sroberto		else
43082498Sroberto			++priority_done;
43154359Sroberto	}
43282498Sroberto# endif /* HAVE_BSD_NICE */
43382498Sroberto#endif /* NTPD_PRIO && NTPD_PRIO != 0 */
43482498Sroberto	if (!priority_done)
43554359Sroberto		msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority");
43654359Sroberto}
43754359Sroberto
43856746Sroberto
43954359Sroberto/*
44054359Sroberto * Main program.  Initialize us, disconnect us from the tty if necessary,
44154359Sroberto * and loop waiting for I/O and/or timer expiries.
44254359Sroberto */
44354359Srobertoint
44454359Srobertontpdmain(
44554359Sroberto	int argc,
44654359Sroberto	char *argv[]
44754359Sroberto	)
44854359Sroberto{
44954359Sroberto	l_fp now;
45054359Sroberto	struct recvbuf *rbuf;
45154359Sroberto#ifdef _AIX			/* HMS: ifdef SIGDANGER? */
45254359Sroberto	struct sigaction sa;
45354359Sroberto#endif
45454359Sroberto
455182007Sroberto	progname = argv[0];
456182007Sroberto
45754359Sroberto	initializing = 1;		/* mark that we are initializing */
45854359Sroberto
459182007Sroberto	{
460182007Sroberto		int optct = optionProcess(
461182007Sroberto#ifdef SIM
462182007Sroberto					  &ntpdsimOptions
463182007Sroberto#else
464182007Sroberto					  &ntpdOptions
465182007Sroberto#endif
466182007Sroberto					  , argc, argv);
467182007Sroberto		argc -= optct;
468182007Sroberto		argv += optct;
469182007Sroberto	}
470182007Sroberto
471182007Sroberto	/* HMS: is this lame? Should we process -l first? */
472182007Sroberto
473182007Sroberto	init_logging(progname);		/* Open the log file */
474182007Sroberto
47554359Sroberto#ifdef HAVE_UMASK
47654359Sroberto	{
47782498Sroberto		mode_t uv;
47854359Sroberto
47954359Sroberto		uv = umask(0);
48054359Sroberto		if(uv)
48154359Sroberto			(void) umask(uv);
48254359Sroberto		else
48354359Sroberto			(void) umask(022);
48454359Sroberto	}
48554359Sroberto#endif
48654359Sroberto
487106163Sroberto#if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
48854359Sroberto	{
48954359Sroberto		uid_t uid;
49054359Sroberto
49154359Sroberto		uid = getuid();
49254359Sroberto		if (uid)
49354359Sroberto		{
49454359Sroberto			msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid);
495182007Sroberto			printf("must be run as root, not uid %ld", (long)uid);
49654359Sroberto			exit(1);
49754359Sroberto		}
49854359Sroberto	}
49954359Sroberto#endif
50054359Sroberto
501182007Sroberto#ifdef OPENSSL
502182007Sroberto	if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & ~0xff0L) {
503182007Sroberto		msyslog(LOG_ERR,
504182007Sroberto		    "ntpd: OpenSSL version mismatch. Built against %lx, you have %lx\n",
505182007Sroberto		    OPENSSL_VERSION_NUMBER, SSLeay());
50654359Sroberto		exit(1);
50754359Sroberto	}
50854359Sroberto#endif
50954359Sroberto
510182007Sroberto	/* getstartup(argc, argv); / * startup configuration, may set debug */
511182007Sroberto
512182007Sroberto#ifdef DEBUG
513182007Sroberto	debug = DESC(DEBUG_LEVEL).optOccCt;
514132451Sroberto	if (debug)
515132451Sroberto	    printf("%s\n", Version);
516182007Sroberto#endif
517132451Sroberto
518182007Sroberto/*
519182007Sroberto * Enable the Multi-Media Timer for Windows?
520182007Sroberto */
521182007Sroberto#ifdef SYS_WINNT
522182007Sroberto	if (HAVE_OPT( MODIFYMMTIMER ))
523182007Sroberto		set_mm_timer(MM_TIMER_HIRES);
524182007Sroberto#endif
525182007Sroberto
526182007Sroberto	if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT ))
527182007Sroberto		nofork = 1;
528182007Sroberto
529182007Sroberto	if (HAVE_OPT( NOVIRTUALIPS ))
530182007Sroberto		listen_to_virtual_ips = 0;
531182007Sroberto
532182007Sroberto	if (HAVE_OPT( INTERFACE )) {
533182007Sroberto#if 0
534182007Sroberto		int	ifacect = STACKCT_OPT( INTERFACE );
535182007Sroberto		char**	ifaces  = STACKLST_OPT( INTERFACE );
536182007Sroberto
537182007Sroberto		/* malloc space for the array of names */
538182007Sroberto		while (ifacect-- > 0) {
539182007Sroberto			next_iface = *ifaces++;
540182007Sroberto		}
541182007Sroberto#else
542182007Sroberto		specific_interface = OPT_ARG( INTERFACE );
543182007Sroberto#endif
544182007Sroberto	}
545182007Sroberto
546182007Sroberto	if (HAVE_OPT( NICE ))
547182007Sroberto		priority_done = 0;
548182007Sroberto
549182007Sroberto#if defined(HAVE_SCHED_SETSCHEDULER)
550182007Sroberto	if (HAVE_OPT( PRIORITY )) {
551182007Sroberto		config_priority = OPT_VALUE_PRIORITY;
552182007Sroberto		config_priority_override = 1;
553182007Sroberto		priority_done = 0;
554182007Sroberto	}
555182007Sroberto#endif
556182007Sroberto
557182007Sroberto#ifdef SYS_WINNT
55882498Sroberto	/*
559182007Sroberto	 * Initialize the time structures and variables
560182007Sroberto	 */
561182007Sroberto	init_winnt_time();
562182007Sroberto#endif
563182007Sroberto
564182007Sroberto	setup_logfile();
565182007Sroberto
566182007Sroberto	/*
56782498Sroberto	 * Initialize random generator and public key pair
56882498Sroberto	 */
56954359Sroberto	get_systime(&now);
57054359Sroberto
571182007Sroberto	ntp_srandom((int)(now.l_i * now.l_uf));
572182007Sroberto
573182007Sroberto#ifdef HAVE_DNSREGISTRATION
574182007Sroberto	/* HMS: does this have to happen this early? */
575182007Sroberto	msyslog(LOG_INFO, "Attemping to register mDNS");
576182007Sroberto	if ( DNSServiceRegister (&mdns, 0, 0, NULL, "_ntp._udp", NULL, NULL, htons(NTP_PORT), 0, NULL, NULL, NULL) != kDNSServiceErr_NoError ) {
577182007Sroberto		msyslog(LOG_ERR, "Unable to register mDNS");
578182007Sroberto	}
579182007Sroberto#endif
580182007Sroberto
58154359Sroberto#if !defined(VMS)
58254359Sroberto# ifndef NODETACH
58354359Sroberto	/*
58454359Sroberto	 * Detach us from the terminal.  May need an #ifndef GIZMO.
58554359Sroberto	 */
586182007Sroberto	if (
58754359Sroberto#  ifdef DEBUG
588182007Sroberto	    !debug &&
58954359Sroberto#  endif /* DEBUG */
590182007Sroberto	    !nofork)
59154359Sroberto	{
59254359Sroberto#  ifndef SYS_WINNT
59382498Sroberto#   ifdef HAVE_DAEMON
59454359Sroberto		daemon(0, 0);
59582498Sroberto#   else /* not HAVE_DAEMON */
59654359Sroberto		if (fork())	/* HMS: What about a -1? */
59754359Sroberto			exit(0);
59854359Sroberto
59954359Sroberto		{
60054359Sroberto#if !defined(F_CLOSEM)
60154359Sroberto			u_long s;
60254359Sroberto			int max_fd;
60354359Sroberto#endif /* not F_CLOSEM */
60454359Sroberto
605132451Sroberto#if defined(F_CLOSEM)
60654359Sroberto			/*
60754359Sroberto			 * From 'Writing Reliable AIX Daemons,' SG24-4946-00,
60854359Sroberto			 * by Eric Agar (saves us from doing 32767 system
60954359Sroberto			 * calls)
61054359Sroberto			 */
61154359Sroberto			if (fcntl(0, F_CLOSEM, 0) == -1)
61254359Sroberto			    msyslog(LOG_ERR, "ntpd: failed to close open files(): %m");
61354359Sroberto#else  /* not F_CLOSEM */
61454359Sroberto
61582498Sroberto# if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
61654359Sroberto			max_fd = sysconf(_SC_OPEN_MAX);
61782498Sroberto# else /* HAVE_SYSCONF && _SC_OPEN_MAX */
61854359Sroberto			max_fd = getdtablesize();
61982498Sroberto# endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
62054359Sroberto			for (s = 0; s < max_fd; s++)
62154359Sroberto				(void) close((int)s);
62254359Sroberto#endif /* not F_CLOSEM */
62354359Sroberto			(void) open("/", 0);
62454359Sroberto			(void) dup2(0, 1);
62554359Sroberto			(void) dup2(0, 2);
62654359Sroberto#ifdef SYS_DOMAINOS
62754359Sroberto			{
62854359Sroberto				uid_$t puid;
62954359Sroberto				status_$t st;
63054359Sroberto
63154359Sroberto				proc2_$who_am_i(&puid);
63254359Sroberto				proc2_$make_server(&puid, &st);
63354359Sroberto			}
63454359Sroberto#endif /* SYS_DOMAINOS */
63554359Sroberto#if defined(HAVE_SETPGID) || defined(HAVE_SETSID)
63654359Sroberto# ifdef HAVE_SETSID
63754359Sroberto			if (setsid() == (pid_t)-1)
63854359Sroberto				msyslog(LOG_ERR, "ntpd: setsid(): %m");
63954359Sroberto# else
64054359Sroberto			if (setpgid(0, 0) == -1)
64154359Sroberto				msyslog(LOG_ERR, "ntpd: setpgid(): %m");
64254359Sroberto# endif
64354359Sroberto#else /* HAVE_SETPGID || HAVE_SETSID */
64454359Sroberto			{
64554359Sroberto# if defined(TIOCNOTTY)
64654359Sroberto				int fid;
64754359Sroberto
64854359Sroberto				fid = open("/dev/tty", 2);
64954359Sroberto				if (fid >= 0)
65054359Sroberto				{
65154359Sroberto					(void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);
65254359Sroberto					(void) close(fid);
65354359Sroberto				}
65454359Sroberto# endif /* defined(TIOCNOTTY) */
65554359Sroberto# ifdef HAVE_SETPGRP_0
65654359Sroberto				(void) setpgrp();
65754359Sroberto# else /* HAVE_SETPGRP_0 */
65854359Sroberto				(void) setpgrp(0, getpid());
65954359Sroberto# endif /* HAVE_SETPGRP_0 */
66054359Sroberto			}
66154359Sroberto#endif /* HAVE_SETPGID || HAVE_SETSID */
66254359Sroberto#ifdef _AIX
66354359Sroberto			/* Don't get killed by low-on-memory signal. */
66454359Sroberto			sa.sa_handler = catch_danger;
66554359Sroberto			sigemptyset(&sa.sa_mask);
66654359Sroberto			sa.sa_flags = SA_RESTART;
66754359Sroberto
66854359Sroberto			(void) sigaction(SIGDANGER, &sa, NULL);
66954359Sroberto#endif /* _AIX */
67054359Sroberto		}
67182498Sroberto#   endif /* not HAVE_DAEMON */
67282498Sroberto#  endif /* SYS_WINNT */
67354359Sroberto	}
67482498Sroberto# endif /* NODETACH */
67554359Sroberto#endif /* VMS */
67654359Sroberto
677182007Sroberto	setup_logfile();	/* We lost any redirect when we daemonized */
67854359Sroberto
67954359Sroberto#ifdef SCO5_CLOCK
68054359Sroberto	/*
68154359Sroberto	 * SCO OpenServer's system clock offers much more precise timekeeping
68254359Sroberto	 * on the base CPU than the other CPUs (for multiprocessor systems),
68354359Sroberto	 * so we must lock to the base CPU.
68454359Sroberto	 */
68554359Sroberto	{
68654359Sroberto	    int fd = open("/dev/at1", O_RDONLY);
68754359Sroberto	    if (fd >= 0) {
68854359Sroberto		int zero = 0;
68954359Sroberto		if (ioctl(fd, ACPU_LOCK, &zero) < 0)
690182007Sroberto		    msyslog(LOG_ERR, "cannot lock to base CPU: %m");
69154359Sroberto		close( fd );
69254359Sroberto	    } /* else ...
69354359Sroberto	       *   If we can't open the device, this probably just isn't
69454359Sroberto	       *   a multiprocessor system, so we're A-OK.
69554359Sroberto	       */
69654359Sroberto	}
69754359Sroberto#endif
69854359Sroberto
69954359Sroberto#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE)
700132451Sroberto# ifdef HAVE_SETRLIMIT
70154359Sroberto	/*
702132451Sroberto	 * Set the stack limit to something smaller, so that we don't lock a lot
703132451Sroberto	 * of unused stack memory.
704132451Sroberto	 */
705132451Sroberto	{
706132451Sroberto	    struct rlimit rl;
707132451Sroberto
708182007Sroberto	    /* HMS: must make the rlim_cur amount configurable */
709132451Sroberto	    if (getrlimit(RLIMIT_STACK, &rl) != -1
710182007Sroberto		&& (rl.rlim_cur = 50 * 4096) < rl.rlim_max)
711132451Sroberto	    {
712132451Sroberto		    if (setrlimit(RLIMIT_STACK, &rl) == -1)
713132451Sroberto		    {
714132451Sroberto			    msyslog(LOG_ERR,
715132451Sroberto				"Cannot adjust stack limit for mlockall: %m");
716132451Sroberto		    }
717132451Sroberto	    }
718182007Sroberto#  ifdef RLIMIT_MEMLOCK
719182007Sroberto	    /*
720182007Sroberto	     * The default RLIMIT_MEMLOCK is very low on Linux systems.
721182007Sroberto	     * Unless we increase this limit malloc calls are likely to
722182007Sroberto	     * fail if we drop root privlege.  To be useful the value
723182007Sroberto	     * has to be larger than the largest ntpd resident set size.
724182007Sroberto	     */
725182007Sroberto	    rl.rlim_cur = rl.rlim_max = 32*1024*1024;
726182007Sroberto	    if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) {
727182007Sroberto	    	msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
728182007Sroberto	    }
729182007Sroberto#  endif /* RLIMIT_MEMLOCK */
730132451Sroberto	}
731132451Sroberto# endif /* HAVE_SETRLIMIT */
732132451Sroberto	/*
73354359Sroberto	 * lock the process into memory
73454359Sroberto	 */
73554359Sroberto	if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0)
73654359Sroberto		msyslog(LOG_ERR, "mlockall(): %m");
73754359Sroberto#else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
73854359Sroberto# ifdef HAVE_PLOCK
73954359Sroberto#  ifdef PROCLOCK
74054359Sroberto#   ifdef _AIX
74154359Sroberto	/*
74254359Sroberto	 * set the stack limit for AIX for plock().
743182007Sroberto	 * see get_aix_stack() for more info.
74454359Sroberto	 */
74554359Sroberto	if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0)
74654359Sroberto	{
74754359Sroberto		msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m");
74854359Sroberto	}
74954359Sroberto#   endif /* _AIX */
75054359Sroberto	/*
75154359Sroberto	 * lock the process into memory
75254359Sroberto	 */
75354359Sroberto	if (plock(PROCLOCK) < 0)
75454359Sroberto		msyslog(LOG_ERR, "plock(PROCLOCK): %m");
75554359Sroberto#  else /* not PROCLOCK */
75682498Sroberto#   ifdef TXTLOCK
75754359Sroberto	/*
75854359Sroberto	 * Lock text into ram
75954359Sroberto	 */
76054359Sroberto	if (plock(TXTLOCK) < 0)
76154359Sroberto		msyslog(LOG_ERR, "plock(TXTLOCK) error: %m");
76282498Sroberto#   else /* not TXTLOCK */
76354359Sroberto	msyslog(LOG_ERR, "plock() - don't know what to lock!");
76482498Sroberto#   endif /* not TXTLOCK */
76554359Sroberto#  endif /* not PROCLOCK */
76654359Sroberto# endif /* HAVE_PLOCK */
76754359Sroberto#endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
76854359Sroberto
76954359Sroberto	/*
77054359Sroberto	 * Set up signals we pay attention to locally.
77154359Sroberto	 */
77254359Sroberto#ifdef SIGDIE1
77354359Sroberto	(void) signal_no_reset(SIGDIE1, finish);
77454359Sroberto#endif	/* SIGDIE1 */
77554359Sroberto#ifdef SIGDIE2
77654359Sroberto	(void) signal_no_reset(SIGDIE2, finish);
77754359Sroberto#endif	/* SIGDIE2 */
77854359Sroberto#ifdef SIGDIE3
77954359Sroberto	(void) signal_no_reset(SIGDIE3, finish);
78054359Sroberto#endif	/* SIGDIE3 */
78154359Sroberto#ifdef SIGDIE4
78254359Sroberto	(void) signal_no_reset(SIGDIE4, finish);
78354359Sroberto#endif	/* SIGDIE4 */
78454359Sroberto
78554359Sroberto#ifdef SIGBUS
78654359Sroberto	(void) signal_no_reset(SIGBUS, finish);
78754359Sroberto#endif /* SIGBUS */
78854359Sroberto
78954359Sroberto#if !defined(SYS_WINNT) && !defined(VMS)
79054359Sroberto# ifdef DEBUG
79154359Sroberto	(void) signal_no_reset(MOREDEBUGSIG, moredebug);
79254359Sroberto	(void) signal_no_reset(LESSDEBUGSIG, lessdebug);
79354359Sroberto# else
79454359Sroberto	(void) signal_no_reset(MOREDEBUGSIG, no_debug);
79554359Sroberto	(void) signal_no_reset(LESSDEBUGSIG, no_debug);
79654359Sroberto# endif /* DEBUG */
79754359Sroberto#endif /* !SYS_WINNT && !VMS */
79854359Sroberto
79954359Sroberto	/*
80054359Sroberto	 * Set up signals we should never pay attention to.
80154359Sroberto	 */
80256746Sroberto#if defined SIGPIPE
80354359Sroberto	(void) signal_no_reset(SIGPIPE, SIG_IGN);
80454359Sroberto#endif	/* SIGPIPE */
80554359Sroberto
80654359Sroberto	/*
80754359Sroberto	 * Call the init_ routines to initialize the data structures.
808182007Sroberto	 *
809182007Sroberto	 * Exactly what command-line options are we expecting here?
81054359Sroberto	 */
81154359Sroberto	init_auth();
81254359Sroberto	init_util();
81354359Sroberto	init_restrict();
81454359Sroberto	init_mon();
81554359Sroberto	init_timer();
81654359Sroberto	init_lib();
81754359Sroberto	init_request();
81854359Sroberto	init_control();
81954359Sroberto	init_peer();
82054359Sroberto#ifdef REFCLOCK
82154359Sroberto	init_refclock();
82254359Sroberto#endif
82354359Sroberto	set_process_priority();
82482498Sroberto	init_proto();		/* Call at high priority */
82554359Sroberto	init_io();
82654359Sroberto	init_loopfilter();
82782498Sroberto	mon_start(MON_ON);	/* monitor on by default now	  */
82854359Sroberto				/* turn off in config if unwanted */
82954359Sroberto
83054359Sroberto	/*
831182007Sroberto	 * Get the configuration.  This is done in a separate module
832182007Sroberto	 * since this will definitely be different for the gizmo board.
83354359Sroberto	 */
834182007Sroberto
83554359Sroberto	getconfig(argc, argv);
836182007Sroberto
837182007Sroberto	loop_config(LOOP_DRIFTCOMP, old_drift / 1e6);
838132451Sroberto#ifdef OPENSSL
83982498Sroberto	crypto_setup();
840132451Sroberto#endif /* OPENSSL */
84154359Sroberto	initializing = 0;
84254359Sroberto
843182007Sroberto#ifdef HAVE_DROPROOT
844182007Sroberto	if( droproot ) {
845182007Sroberto		/* Drop super-user privileges and chroot now if the OS supports this */
846182007Sroberto
847182007Sroberto#ifdef HAVE_LINUX_CAPABILITIES
848182007Sroberto		/* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */
849182007Sroberto		if( prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1 ) {
850182007Sroberto			msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" );
851182007Sroberto			exit(-1);
852182007Sroberto		}
853182007Sroberto#else
854182007Sroberto		/* we need a user to switch to */
855182007Sroberto		if( user == NULL ) {
856182007Sroberto			msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" );
857182007Sroberto			exit(-1);
858182007Sroberto		}
859182007Sroberto#endif /* HAVE_LINUX_CAPABILITIES */
860182007Sroberto
861182007Sroberto		if (user != NULL) {
862182007Sroberto			if (isdigit((unsigned char)*user)) {
863182007Sroberto				sw_uid = (uid_t)strtoul(user, &endp, 0);
864182007Sroberto				if (*endp != '\0')
865182007Sroberto					goto getuser;
866182007Sroberto			} else {
867182007Srobertogetuser:
868182007Sroberto				if ((pw = getpwnam(user)) != NULL) {
869182007Sroberto					sw_uid = pw->pw_uid;
870182007Sroberto				} else {
871182007Sroberto					errno = 0;
872182007Sroberto					msyslog(LOG_ERR, "Cannot find user `%s'", user);
873182007Sroberto					exit (-1);
874182007Sroberto				}
875132451Sroberto			}
87654359Sroberto		}
877182007Sroberto		if (group != NULL) {
878182007Sroberto			if (isdigit((unsigned char)*group)) {
879182007Sroberto				sw_gid = (gid_t)strtoul(group, &endp, 0);
880182007Sroberto				if (*endp != '\0')
881182007Sroberto					goto getgroup;
882182007Sroberto			} else {
883182007Srobertogetgroup:
884182007Sroberto				if ((gr = getgrnam(group)) != NULL) {
885182007Sroberto					sw_gid = gr->gr_gid;
886182007Sroberto				} else {
887182007Sroberto					errno = 0;
888182007Sroberto					msyslog(LOG_ERR, "Cannot find group `%s'", group);
889182007Sroberto					exit (-1);
890182007Sroberto				}
891182007Sroberto			}
892182007Sroberto		}
893182007Sroberto
894182007Sroberto		if( chrootdir ) {
895182007Sroberto			/* make sure cwd is inside the jail: */
896182007Sroberto			if( chdir(chrootdir) ) {
897182007Sroberto				msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir);
898182007Sroberto				exit (-1);
899182007Sroberto			}
900182007Sroberto			if( chroot(chrootdir) ) {
901182007Sroberto				msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir);
902182007Sroberto				exit (-1);
903182007Sroberto			}
904182007Sroberto		}
905182007Sroberto		if (group && setgid(sw_gid)) {
906182007Sroberto			msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
907182007Sroberto			exit (-1);
908182007Sroberto		}
909182007Sroberto		if (group && setegid(sw_gid)) {
910182007Sroberto			msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
911182007Sroberto			exit (-1);
912182007Sroberto		}
913182007Sroberto		if (user && setuid(sw_uid)) {
914182007Sroberto			msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
915182007Sroberto			exit (-1);
916182007Sroberto		}
917182007Sroberto		if (user && seteuid(sw_uid)) {
918182007Sroberto			msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
919182007Sroberto			exit (-1);
920182007Sroberto		}
921182007Sroberto
922182007Sroberto#ifndef HAVE_LINUX_CAPABILITIES
923182007Sroberto		/*
924182007Sroberto		 * for now assume that the privilege to bind to privileged ports
925182007Sroberto		 * is associated with running with uid 0 - should be refined on
926182007Sroberto		 * ports that allow binding to NTP_PORT with uid != 0
927182007Sroberto		 */
928182007Sroberto		disable_dynamic_updates |= (sw_uid != 0);  /* also notifies routing message listener */
92954359Sroberto#endif
93054359Sroberto
931182007Sroberto		if (disable_dynamic_updates && interface_interval) {
932182007Sroberto			interface_interval = 0;
933182007Sroberto			msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking");
934182007Sroberto		}
935182007Sroberto
936182007Sroberto#ifdef HAVE_LINUX_CAPABILITIES
937182007Sroberto		do {
938182007Sroberto			/*
939182007Sroberto			 *  We may be running under non-root uid now, but we still hold full root privileges!
940182007Sroberto			 *  We drop all of them, except for the crucial one or two: cap_sys_time and
941182007Sroberto			 *  cap_net_bind_service if doing dynamic interface tracking.
942182007Sroberto			 */
943182007Sroberto			cap_t caps;
944182007Sroberto			char *captext = interface_interval ?
945182007Sroberto			       	"cap_sys_time,cap_net_bind_service=ipe" :
946182007Sroberto			       	"cap_sys_time=ipe";
947182007Sroberto			if( ! ( caps = cap_from_text( captext ) ) ) {
948182007Sroberto				msyslog( LOG_ERR, "cap_from_text() failed: %m" );
949182007Sroberto				exit(-1);
950182007Sroberto			}
951182007Sroberto			if( cap_set_proc( caps ) == -1 ) {
952182007Sroberto				msyslog( LOG_ERR, "cap_set_proc() failed to drop root privileges: %m" );
953182007Sroberto				exit(-1);
954182007Sroberto			}
955182007Sroberto			cap_free( caps );
956182007Sroberto		} while(0);
957182007Sroberto#endif /* HAVE_LINUX_CAPABILITIES */
958182007Sroberto
959182007Sroberto	}    /* if( droproot ) */
960182007Sroberto#endif /* HAVE_DROPROOT */
961182007Sroberto
96254359Sroberto	/*
96354359Sroberto	 * Report that we're up to any trappers
96454359Sroberto	 */
96554359Sroberto	report_event(EVNT_SYSRESTART, (struct peer *)0);
96654359Sroberto
96754359Sroberto	/*
96854359Sroberto	 * Use select() on all on all input fd's for unlimited
96954359Sroberto	 * time.  select() will terminate on SIGALARM or on the
97054359Sroberto	 * reception of input.	Using select() means we can't do
97154359Sroberto	 * robust signal handling and we get a potential race
97254359Sroberto	 * between checking for alarms and doing the select().
97354359Sroberto	 * Mostly harmless, I think.
97454359Sroberto	 */
97554359Sroberto	/* On VMS, I suspect that select() can't be interrupted
97654359Sroberto	 * by a "signal" either, so I take the easy way out and
97754359Sroberto	 * have select() time out after one second.
97854359Sroberto	 * System clock updates really aren't time-critical,
97954359Sroberto	 * and - lacking a hardware reference clock - I have
98054359Sroberto	 * yet to learn about anything else that is.
98154359Sroberto	 */
98282498Sroberto#if defined(HAVE_IO_COMPLETION_PORT)
98354359Sroberto
984182007Sroberto	for (;;) {
985200576Sroberto		GetReceivedBuffers();
98682498Sroberto#else /* normal I/O */
98754359Sroberto
988182007Sroberto	BLOCK_IO_AND_ALARM();
98954359Sroberto	was_alarmed = 0;
99054359Sroberto	for (;;)
99154359Sroberto	{
99282498Sroberto# if !defined(HAVE_SIGNALED_IO)
99354359Sroberto		extern fd_set activefds;
99454359Sroberto		extern int maxactivefd;
99554359Sroberto
99654359Sroberto		fd_set rdfdes;
99754359Sroberto		int nfound;
99882498Sroberto# endif
99954359Sroberto
100054359Sroberto		if (alarm_flag) 	/* alarmed? */
100154359Sroberto		{
100254359Sroberto			was_alarmed = 1;
100354359Sroberto			alarm_flag = 0;
100454359Sroberto		}
100554359Sroberto
1006182007Sroberto		if (!was_alarmed && has_full_recv_buffer() == ISC_FALSE)
100754359Sroberto		{
100854359Sroberto			/*
100954359Sroberto			 * Nothing to do.  Wait for something.
101054359Sroberto			 */
101182498Sroberto# ifndef HAVE_SIGNALED_IO
101254359Sroberto			rdfdes = activefds;
101382498Sroberto#  if defined(VMS) || defined(SYS_VXWORKS)
101454359Sroberto			/* make select() wake up after one second */
101554359Sroberto			{
101654359Sroberto				struct timeval t1;
101754359Sroberto
101854359Sroberto				t1.tv_sec = 1; t1.tv_usec = 0;
101954359Sroberto				nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
102054359Sroberto						(fd_set *)0, &t1);
102154359Sroberto			}
102282498Sroberto#  else
102354359Sroberto			nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
102454359Sroberto					(fd_set *)0, (struct timeval *)0);
102582498Sroberto#  endif /* VMS */
102654359Sroberto			if (nfound > 0)
102754359Sroberto			{
102854359Sroberto				l_fp ts;
102954359Sroberto
103054359Sroberto				get_systime(&ts);
103154359Sroberto
103254359Sroberto				(void)input_handler(&ts);
103354359Sroberto			}
103454359Sroberto			else if (nfound == -1 && errno != EINTR)
1035182007Sroberto				netsyslog(LOG_ERR, "select() error: %m");
1036132451Sroberto#  ifdef DEBUG
1037182007Sroberto			else if (debug > 5)
1038182007Sroberto				netsyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
1039132451Sroberto#  endif /* DEBUG */
104082498Sroberto# else /* HAVE_SIGNALED_IO */
104154359Sroberto
104254359Sroberto			wait_for_signal();
104382498Sroberto# endif /* HAVE_SIGNALED_IO */
104454359Sroberto			if (alarm_flag) 	/* alarmed? */
104554359Sroberto			{
104654359Sroberto				was_alarmed = 1;
104754359Sroberto				alarm_flag = 0;
104854359Sroberto			}
104954359Sroberto		}
105054359Sroberto
105154359Sroberto		if (was_alarmed)
105254359Sroberto		{
1053182007Sroberto			UNBLOCK_IO_AND_ALARM();
1054182007Sroberto			/*
1055182007Sroberto			 * Out here, signals are unblocked.  Call timer routine
1056182007Sroberto			 * to process expiry.
1057182007Sroberto			 */
105854359Sroberto			timer();
105954359Sroberto			was_alarmed = 0;
1060182007Sroberto                        BLOCK_IO_AND_ALARM();
106154359Sroberto		}
106254359Sroberto
106382498Sroberto#endif /* HAVE_IO_COMPLETION_PORT */
1064182007Sroberto
1065182007Sroberto#ifdef DEBUG_TIMING
106654359Sroberto		{
1067182007Sroberto			l_fp pts;
1068182007Sroberto			l_fp tsa, tsb;
1069182007Sroberto			int bufcount = 0;
1070182007Sroberto
1071182007Sroberto			get_systime(&pts);
1072182007Sroberto			tsa = pts;
1073182007Sroberto#endif
1074182007Sroberto			rbuf = get_full_recv_buffer();
1075182007Sroberto			while (rbuf != NULL)
1076182007Sroberto			{
1077182007Sroberto				if (alarm_flag)
1078182007Sroberto				{
1079182007Sroberto					was_alarmed = 1;
1080182007Sroberto					alarm_flag = 0;
1081182007Sroberto				}
1082182007Sroberto				UNBLOCK_IO_AND_ALARM();
1083182007Sroberto
1084182007Sroberto				if (was_alarmed)
1085182007Sroberto				{	/* avoid timer starvation during lengthy I/O handling */
1086182007Sroberto					timer();
1087182007Sroberto					was_alarmed = 0;
1088182007Sroberto				}
1089182007Sroberto
1090182007Sroberto				/*
1091182007Sroberto				 * Call the data procedure to handle each received
1092182007Sroberto				 * packet.
1093182007Sroberto				 */
1094182007Sroberto				if (rbuf->receiver != NULL)	/* This should always be true */
1095182007Sroberto				{
1096182007Sroberto#ifdef DEBUG_TIMING
1097182007Sroberto					l_fp dts = pts;
1098182007Sroberto
1099182007Sroberto					L_SUB(&dts, &rbuf->recv_time);
1100182007Sroberto					DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9)));
1101182007Sroberto					collect_timing(rbuf, "buffer processing delay", 1, &dts);
1102182007Sroberto					bufcount++;
1103182007Sroberto#endif
1104182007Sroberto					(rbuf->receiver)(rbuf);
1105182007Sroberto				} else {
1106182007Sroberto					msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING");
1107182007Sroberto					abort();
1108182007Sroberto				}
1109182007Sroberto
1110182007Sroberto				BLOCK_IO_AND_ALARM();
1111182007Sroberto				freerecvbuf(rbuf);
1112182007Sroberto				rbuf = get_full_recv_buffer();
1113182007Sroberto			}
1114182007Sroberto#ifdef DEBUG_TIMING
1115182007Sroberto			get_systime(&tsb);
1116182007Sroberto			L_SUB(&tsb, &tsa);
1117182007Sroberto			if (bufcount) {
1118182007Sroberto				collect_timing(NULL, "processing", bufcount, &tsb);
1119182007Sroberto				DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9)));
1120182007Sroberto			}
112154359Sroberto		}
112282498Sroberto#endif
112354359Sroberto
112454359Sroberto		/*
112554359Sroberto		 * Go around again
112654359Sroberto		 */
112754359Sroberto	}
1128182007Sroberto	UNBLOCK_IO_AND_ALARM();
1129182007Sroberto	return 1;
113054359Sroberto}
113154359Sroberto
113254359Sroberto
113354359Sroberto#ifdef SIGDIE2
113454359Sroberto/*
113554359Sroberto * finish - exit gracefully
113654359Sroberto */
113754359Srobertostatic RETSIGTYPE
113854359Srobertofinish(
113954359Sroberto	int sig
114054359Sroberto	)
114154359Sroberto{
114254359Sroberto
114354359Sroberto	msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig);
1144182007Sroberto	write_stats();
1145182007Sroberto#ifdef HAVE_DNSREGISTRATION
1146182007Sroberto	if (mdns != NULL)
1147182007Sroberto	DNSServiceRefDeallocate(mdns);
1148182007Sroberto#endif
114954359Sroberto
115054359Sroberto	switch (sig)
115154359Sroberto	{
115282498Sroberto# ifdef SIGBUS
115354359Sroberto		case SIGBUS:
115454359Sroberto		printf("\nfinish(SIGBUS)\n");
115554359Sroberto		exit(0);
115682498Sroberto# endif
115754359Sroberto		case 0: 		/* Should never happen... */
115854359Sroberto		return;
115954359Sroberto		default:
116054359Sroberto		exit(0);
116154359Sroberto	}
116254359Sroberto}
116354359Sroberto#endif	/* SIGDIE2 */
116454359Sroberto
116554359Sroberto
116654359Sroberto#ifdef DEBUG
1167132451Sroberto#ifndef SYS_WINNT
116854359Sroberto/*
116954359Sroberto * moredebug - increase debugging verbosity
117054359Sroberto */
117154359Srobertostatic RETSIGTYPE
117254359Srobertomoredebug(
117354359Sroberto	int sig
117454359Sroberto	)
117554359Sroberto{
117654359Sroberto	int saved_errno = errno;
117754359Sroberto
117854359Sroberto	if (debug < 255)
117954359Sroberto	{
118054359Sroberto		debug++;
118154359Sroberto		msyslog(LOG_DEBUG, "debug raised to %d", debug);
118254359Sroberto	}
118354359Sroberto	errno = saved_errno;
118454359Sroberto}
118554359Sroberto
118654359Sroberto/*
118754359Sroberto * lessdebug - decrease debugging verbosity
118854359Sroberto */
118954359Srobertostatic RETSIGTYPE
119054359Srobertolessdebug(
119154359Sroberto	int sig
119254359Sroberto	)
119354359Sroberto{
119454359Sroberto	int saved_errno = errno;
119554359Sroberto
119654359Sroberto	if (debug > 0)
119754359Sroberto	{
119854359Sroberto		debug--;
119954359Sroberto		msyslog(LOG_DEBUG, "debug lowered to %d", debug);
120054359Sroberto	}
120154359Sroberto	errno = saved_errno;
120254359Sroberto}
1203132451Sroberto#endif
120454359Sroberto#else /* not DEBUG */
1205182007Sroberto#ifndef SYS_WINNT
1206182007Sroberto/*
120754359Sroberto * no_debug - We don't do the debug here.
120854359Sroberto */
120954359Srobertostatic RETSIGTYPE
121054359Srobertono_debug(
121154359Sroberto	int sig
121254359Sroberto	)
121354359Sroberto{
121454359Sroberto	int saved_errno = errno;
121554359Sroberto
121654359Sroberto	msyslog(LOG_DEBUG, "ntpd not compiled for debugging (signal %d)", sig);
121754359Sroberto	errno = saved_errno;
121854359Sroberto}
1219132451Sroberto#endif  /* not SYS_WINNT */
122054359Sroberto#endif	/* not DEBUG */
1221