]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ntp/ntpd/ntpd.c
This commit was generated by cvs2svn to compensate for changes in r168609,
[FreeBSD/FreeBSD.git] / contrib / ntp / ntpd / ntpd.c
1 /*
2  * ntpd.c - main program for the fixed point NTP daemon
3  */
4
5 #ifdef HAVE_CONFIG_H
6 # include <config.h>
7 #endif
8
9 #include "ntp_machine.h"
10 #include "ntpd.h"
11 #include "ntp_io.h"
12 #include "ntp_stdlib.h"
13
14 #ifdef SIM
15 #include "ntpsim.h"
16 #endif
17
18 #ifdef HAVE_UNISTD_H
19 # include <unistd.h>
20 #endif
21 #ifdef HAVE_SYS_STAT_H
22 # include <sys/stat.h>
23 #endif
24 #include <stdio.h>
25 #ifndef SYS_WINNT
26 # if !defined(VMS)      /*wjm*/
27 #  ifdef HAVE_SYS_PARAM_H
28 #   include <sys/param.h>
29 #  endif
30 # endif /* VMS */
31 # ifdef HAVE_SYS_SIGNAL_H
32 #  include <sys/signal.h>
33 # else
34 #  include <signal.h>
35 # endif
36 # ifdef HAVE_SYS_IOCTL_H
37 #  include <sys/ioctl.h>
38 # endif /* HAVE_SYS_IOCTL_H */
39 # ifdef HAVE_SYS_RESOURCE_H
40 #  include <sys/resource.h>
41 # endif /* HAVE_SYS_RESOURCE_H */
42 #else
43 # include <signal.h>
44 # include <process.h>
45 # include <io.h>
46 # include "../libntp/log.h"
47 # include <clockstuff.h>
48 # include <crtdbg.h>
49 #endif /* SYS_WINNT */
50 #if defined(HAVE_RTPRIO)
51 # ifdef HAVE_SYS_RESOURCE_H
52 #  include <sys/resource.h>
53 # endif
54 # ifdef HAVE_SYS_LOCK_H
55 #  include <sys/lock.h>
56 # endif
57 # include <sys/rtprio.h>
58 #else
59 # ifdef HAVE_PLOCK
60 #  ifdef HAVE_SYS_LOCK_H
61 #       include <sys/lock.h>
62 #  endif
63 # endif
64 #endif
65 #if defined(HAVE_SCHED_SETSCHEDULER)
66 # ifdef HAVE_SCHED_H
67 #  include <sched.h>
68 # else
69 #  ifdef HAVE_SYS_SCHED_H
70 #   include <sys/sched.h>
71 #  endif
72 # endif
73 #endif
74 #if defined(HAVE_SYS_MMAN_H)
75 # include <sys/mman.h>
76 #endif
77
78 #ifdef HAVE_TERMIOS_H
79 # include <termios.h>
80 #endif
81
82 #ifdef SYS_DOMAINOS
83 # include <apollo/base.h>
84 #endif /* SYS_DOMAINOS */
85
86 #include "recvbuff.h"  
87 #include "ntp_cmdargs.h"  
88
89 #if 0                           /* HMS: I don't think we need this. 961223 */
90 #ifdef LOCK_PROCESS
91 # ifdef SYS_SOLARIS
92 #  include <sys/mman.h>
93 # else
94 #  include <sys/lock.h>
95 # endif
96 #endif
97 #endif
98
99 #ifdef _AIX
100 # include <ulimit.h>
101 #endif /* _AIX */
102
103 #ifdef SCO5_CLOCK
104 # include <sys/ci/ciioctl.h>
105 #endif
106
107 #ifdef HAVE_CLOCKCTL
108 # include <ctype.h>
109 # include <grp.h>
110 # include <pwd.h>
111 #endif
112
113 /*
114  * Signals we catch for debugging.      If not debugging we ignore them.
115  */
116 #define MOREDEBUGSIG    SIGUSR1
117 #define LESSDEBUGSIG    SIGUSR2
118
119 /*
120  * Signals which terminate us gracefully.
121  */
122 #ifndef SYS_WINNT
123 # define SIGDIE1        SIGHUP
124 # define SIGDIE3        SIGQUIT
125 # define SIGDIE2        SIGINT
126 # define SIGDIE4        SIGTERM
127 #endif /* SYS_WINNT */
128
129 #if defined SYS_WINNT
130 /* handles for various threads, process, and objects */
131 HANDLE ResolverThreadHandle = NULL;
132 /* variables used to inform the Service Control Manager of our current state */
133 BOOL NoWinService = FALSE;
134 SERVICE_STATUS ssStatus;
135 SERVICE_STATUS_HANDLE   sshStatusHandle;
136 HANDLE WaitHandles[3] = { NULL, NULL, NULL };
137 char szMsgPath[255];
138 static BOOL WINAPI OnConsoleEvent(DWORD dwCtrlType);
139 BOOL init_randfile();
140 #endif /* SYS_WINNT */
141
142 /*
143  * Scheduling priority we run at
144  */
145 #define NTPD_PRIO       (-12)
146
147 int priority_done = 2;          /* 0 - Set priority */
148                                 /* 1 - priority is OK where it is */
149                                 /* 2 - Don't set priority */
150                                 /* 1 and 2 are pretty much the same */
151
152 /*
153  * Debugging flag
154  */
155 volatile int debug;
156
157 /*
158  * Set the processing not to be in the forground
159  */
160 int forground_process = FALSE;
161
162 /*
163  * No-fork flag.  If set, we do not become a background daemon.
164  */
165 int nofork;
166
167 #ifdef HAVE_CLOCKCTL
168 char *user = NULL;              /* User to switch to */
169 char *group = NULL;             /* group to switch to */
170 char *chrootdir = NULL;         /* directory to chroot to */
171 int sw_uid;
172 int sw_gid;
173 char *endp;  
174 struct group *gr;
175 struct passwd *pw; 
176 #endif /* HAVE_CLOCKCTL */
177
178 /*
179  * Initializing flag.  All async routines watch this and only do their
180  * thing when it is clear.
181  */
182 int initializing;
183
184 /*
185  * Version declaration
186  */
187 extern const char *Version;
188
189 int was_alarmed;
190
191 #ifdef DECL_SYSCALL
192 /*
193  * We put this here, since the argument profile is syscall-specific
194  */
195 extern int syscall      P((int, ...));
196 #endif /* DECL_SYSCALL */
197
198
199 #ifdef  SIGDIE2
200 static  RETSIGTYPE      finish          P((int));
201 #endif  /* SIGDIE2 */
202
203 #ifdef  DEBUG
204 #ifndef SYS_WINNT
205 static  RETSIGTYPE      moredebug       P((int));
206 static  RETSIGTYPE      lessdebug       P((int));
207 #endif
208 #else /* not DEBUG */
209 static  RETSIGTYPE      no_debug        P((int));
210 #endif  /* not DEBUG */
211
212 int             ntpdmain                P((int, char **));
213 static void     set_process_priority    P((void));
214
215 #ifdef SIM
216 int
217 main(
218         int argc,
219         char *argv[]
220         )
221 {
222         return ntpsim(argc, argv);
223 }
224 #else /* SIM */
225 #ifdef NO_MAIN_ALLOWED
226 CALL(ntpd,"ntpd",ntpdmain);
227 #else
228 int
229 main(
230         int argc,
231         char *argv[]
232         )
233 {
234         return ntpdmain(argc, argv);
235 }
236 #endif
237 #endif /* SIM */
238
239 #ifdef _AIX
240 /*
241  * OK. AIX is different than solaris in how it implements plock().
242  * If you do NOT adjust the stack limit, you will get the MAXIMUM
243  * stack size allocated and PINNED with you program. To check the 
244  * value, use ulimit -a. 
245  *
246  * To fix this, we create an automatic variable and set our stack limit 
247  * to that PLUS 32KB of extra space (we need some headroom).
248  *
249  * This subroutine gets the stack address.
250  *
251  * Grover Davidson and Matt Ladendorf
252  *
253  */
254 static char *
255 get_aix_stack(void)
256 {
257         char ch;
258         return (&ch);
259 }
260
261 /*
262  * Signal handler for SIGDANGER.
263  */
264 static void
265 catch_danger(int signo)
266 {
267         msyslog(LOG_INFO, "ntpd: setpgid(): %m");
268         /* Make the system believe we'll free something, but don't do it! */
269         return;
270 }
271 #endif /* _AIX */
272
273 /*
274  * Set the process priority
275  */
276 static void
277 set_process_priority(void)
278 {
279
280 #ifdef DEBUG
281         if (debug > 1)
282                 msyslog(LOG_DEBUG, "set_process_priority: %s: priority_done is <%d>",
283                         ((priority_done)
284                          ? "Leave priority alone"
285                          : "Attempt to set priority"
286                                 ),
287                         priority_done);
288 #endif /* DEBUG */
289
290 #ifdef SYS_WINNT
291         priority_done += NT_set_process_priority();
292 #endif
293
294 #if defined(HAVE_SCHED_SETSCHEDULER)
295         if (!priority_done) {
296                 extern int config_priority_override, config_priority;
297                 int pmax, pmin;
298                 struct sched_param sched;
299
300                 pmax = sched_get_priority_max(SCHED_FIFO);
301                 sched.sched_priority = pmax;
302                 if ( config_priority_override ) {
303                         pmin = sched_get_priority_min(SCHED_FIFO);
304                         if ( config_priority > pmax )
305                                 sched.sched_priority = pmax;
306                         else if ( config_priority < pmin )
307                                 sched.sched_priority = pmin;
308                         else
309                                 sched.sched_priority = config_priority;
310                 }
311                 if ( sched_setscheduler(0, SCHED_FIFO, &sched) == -1 )
312                         msyslog(LOG_ERR, "sched_setscheduler(): %m");
313                 else
314                         ++priority_done;
315         }
316 #endif /* HAVE_SCHED_SETSCHEDULER */
317 #if defined(HAVE_RTPRIO)
318 # ifdef RTP_SET
319         if (!priority_done) {
320                 struct rtprio srtp;
321
322                 srtp.type = RTP_PRIO_REALTIME;  /* was: RTP_PRIO_NORMAL */
323                 srtp.prio = 0;          /* 0 (hi) -> RTP_PRIO_MAX (31,lo) */
324
325                 if (rtprio(RTP_SET, getpid(), &srtp) < 0)
326                         msyslog(LOG_ERR, "rtprio() error: %m");
327                 else
328                         ++priority_done;
329         }
330 # else /* not RTP_SET */
331         if (!priority_done) {
332                 if (rtprio(0, 120) < 0)
333                         msyslog(LOG_ERR, "rtprio() error: %m");
334                 else
335                         ++priority_done;
336         }
337 # endif /* not RTP_SET */
338 #endif  /* HAVE_RTPRIO */
339 #if defined(NTPD_PRIO) && NTPD_PRIO != 0
340 # ifdef HAVE_ATT_NICE
341         if (!priority_done) {
342                 errno = 0;
343                 if (-1 == nice (NTPD_PRIO) && errno != 0)
344                         msyslog(LOG_ERR, "nice() error: %m");
345                 else
346                         ++priority_done;
347         }
348 # endif /* HAVE_ATT_NICE */
349 # ifdef HAVE_BSD_NICE
350         if (!priority_done) {
351                 if (-1 == setpriority(PRIO_PROCESS, 0, NTPD_PRIO))
352                         msyslog(LOG_ERR, "setpriority() error: %m");
353                 else
354                         ++priority_done;
355         }
356 # endif /* HAVE_BSD_NICE */
357 #endif /* NTPD_PRIO && NTPD_PRIO != 0 */
358         if (!priority_done)
359                 msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority");
360 }
361
362
363 /*
364  * Main program.  Initialize us, disconnect us from the tty if necessary,
365  * and loop waiting for I/O and/or timer expiries.
366  */
367 int
368 ntpdmain(
369         int argc,
370         char *argv[]
371         )
372 {
373         l_fp now;
374         char *cp;
375         struct recvbuf *rbuflist;
376         struct recvbuf *rbuf;
377 #ifdef _AIX                     /* HMS: ifdef SIGDANGER? */
378         struct sigaction sa;
379 #endif
380
381         initializing = 1;               /* mark that we are initializing */
382         debug = 0;                      /* no debugging by default */
383         nofork = 0;                     /* will fork by default */
384
385 #ifdef HAVE_UMASK
386         {
387                 mode_t uv;
388
389                 uv = umask(0);
390                 if(uv)
391                         (void) umask(uv);
392                 else
393                         (void) umask(022);
394         }
395 #endif
396
397 #if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
398         {
399                 uid_t uid;
400
401                 uid = getuid();
402                 if (uid)
403                 {
404                         msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid);
405                         exit(1);
406                 }
407         }
408 #endif
409
410 #ifdef SYS_WINNT
411         /* Set the Event-ID message-file name. */
412         if (!GetModuleFileName(NULL, szMsgPath, sizeof(szMsgPath))) {
413                 msyslog(LOG_ERR, "GetModuleFileName(PGM_EXE_FILE) failed: %m\n");
414                 exit(1);
415         }
416         addSourceToRegistry("NTP", szMsgPath);
417 #endif
418         getstartup(argc, argv); /* startup configuration, may set debug */
419
420         if (debug)
421             printf("%s\n", Version);
422
423         /*
424          * Initialize random generator and public key pair
425          */
426 #ifdef SYS_WINNT
427         /* Initialize random file before OpenSSL checks */
428         if(!init_randfile())
429                 msyslog(LOG_ERR, "Unable to initialize .rnd file\n");
430 #endif
431         get_systime(&now);
432         SRANDOM((int)(now.l_i * now.l_uf));
433
434 #if !defined(VMS)
435 # ifndef NODETACH
436         /*
437          * Detach us from the terminal.  May need an #ifndef GIZMO.
438          */
439 #  ifdef DEBUG
440         if (!debug && !nofork)
441 #  else /* DEBUG */
442         if (!nofork)
443 #  endif /* DEBUG */
444         {
445 #  ifndef SYS_WINNT
446 #   ifdef HAVE_DAEMON
447                 daemon(0, 0);
448 #   else /* not HAVE_DAEMON */
449                 if (fork())     /* HMS: What about a -1? */
450                         exit(0);
451
452                 {
453 #if !defined(F_CLOSEM)
454                         u_long s;
455                         int max_fd;
456 #endif /* not F_CLOSEM */
457
458 #if defined(F_CLOSEM)
459                         /*
460                          * From 'Writing Reliable AIX Daemons,' SG24-4946-00,
461                          * by Eric Agar (saves us from doing 32767 system
462                          * calls)
463                          */
464                         if (fcntl(0, F_CLOSEM, 0) == -1)
465                             msyslog(LOG_ERR, "ntpd: failed to close open files(): %m");
466 #else  /* not F_CLOSEM */
467
468 # if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
469                         max_fd = sysconf(_SC_OPEN_MAX);
470 # else /* HAVE_SYSCONF && _SC_OPEN_MAX */
471                         max_fd = getdtablesize();
472 # endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
473                         for (s = 0; s < max_fd; s++)
474                                 (void) close((int)s);
475 #endif /* not F_CLOSEM */
476                         (void) open("/", 0);
477                         (void) dup2(0, 1);
478                         (void) dup2(0, 2);
479 #ifdef SYS_DOMAINOS
480                         {
481                                 uid_$t puid;
482                                 status_$t st;
483
484                                 proc2_$who_am_i(&puid);
485                                 proc2_$make_server(&puid, &st);
486                         }
487 #endif /* SYS_DOMAINOS */
488 #if defined(HAVE_SETPGID) || defined(HAVE_SETSID)
489 # ifdef HAVE_SETSID
490                         if (setsid() == (pid_t)-1)
491                                 msyslog(LOG_ERR, "ntpd: setsid(): %m");
492 # else
493                         if (setpgid(0, 0) == -1)
494                                 msyslog(LOG_ERR, "ntpd: setpgid(): %m");
495 # endif
496 #else /* HAVE_SETPGID || HAVE_SETSID */
497                         {
498 # if defined(TIOCNOTTY)
499                                 int fid;
500
501                                 fid = open("/dev/tty", 2);
502                                 if (fid >= 0)
503                                 {
504                                         (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);
505                                         (void) close(fid);
506                                 }
507 # endif /* defined(TIOCNOTTY) */
508 # ifdef HAVE_SETPGRP_0
509                                 (void) setpgrp();
510 # else /* HAVE_SETPGRP_0 */
511                                 (void) setpgrp(0, getpid());
512 # endif /* HAVE_SETPGRP_0 */
513                         }
514 #endif /* HAVE_SETPGID || HAVE_SETSID */
515 #ifdef _AIX
516                         /* Don't get killed by low-on-memory signal. */
517                         sa.sa_handler = catch_danger;
518                         sigemptyset(&sa.sa_mask);
519                         sa.sa_flags = SA_RESTART;
520
521                         (void) sigaction(SIGDANGER, &sa, NULL);
522 #endif /* _AIX */
523                 }
524 #   endif /* not HAVE_DAEMON */
525 #  else /* SYS_WINNT */
526
527                 {
528                         if (NoWinService == FALSE) {
529                                 SERVICE_TABLE_ENTRY dispatchTable[] = {
530                                 { TEXT("NetworkTimeProtocol"), (LPSERVICE_MAIN_FUNCTION)service_main },
531                                 { NULL, NULL }
532                                 };
533
534                                 /* daemonize */
535                                 if (!StartServiceCtrlDispatcher(dispatchTable))
536                                 {
537                                         msyslog(LOG_ERR, "StartServiceCtrlDispatcher: %m");
538                                         ExitProcess(2);
539                                 }
540                         }
541                         else {
542                                 service_main(argc, argv);
543                                 return 0;
544                         }
545                 }
546 #  endif /* SYS_WINNT */
547         }
548 # endif /* NODETACH */
549 # if defined(SYS_WINNT) && !defined(NODETACH)
550         else
551                 service_main(argc, argv);
552         return 0;       /* must return a value */
553 } /* end main */
554
555 /*
556  * If this runs as a service under NT, the main thread will block at
557  * StartServiceCtrlDispatcher() and another thread will be started by the
558  * Service Control Dispatcher which will begin execution at the routine
559  * specified in that call (viz. service_main)
560  */
561 void
562 service_main(
563         DWORD argc,
564         LPTSTR *argv
565         )
566 {
567         char *cp;
568         struct recvbuf *rbuflist;
569         struct recvbuf *rbuf;
570
571         if(!debug && NoWinService == FALSE)
572         {
573                 /* register our service control handler */
574                 sshStatusHandle = RegisterServiceCtrlHandler( TEXT("NetworkTimeProtocol"),
575                                                         (LPHANDLER_FUNCTION)service_ctrl);
576                 if(sshStatusHandle == 0)
577                 {
578                         msyslog(LOG_ERR, "RegisterServiceCtrlHandler failed: %m");
579                         return;
580                 }
581
582                 /* report pending status to Service Control Manager */
583                 ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
584                 ssStatus.dwCurrentState = SERVICE_START_PENDING;
585                 ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
586                 ssStatus.dwWin32ExitCode = NO_ERROR;
587                 ssStatus.dwServiceSpecificExitCode = 0;
588                 ssStatus.dwCheckPoint = 1;
589                 ssStatus.dwWaitHint = 5000;
590                 if (!SetServiceStatus(sshStatusHandle, &ssStatus))
591                 {
592                         msyslog(LOG_ERR, "SetServiceStatus: %m");
593                         ssStatus.dwCurrentState = SERVICE_STOPPED;
594                         SetServiceStatus(sshStatusHandle, &ssStatus);
595                         return;
596                 }
597
598         }  /* debug */
599 # endif /* defined(SYS_WINNT) && !defined(NODETACH) */
600 #endif /* VMS */
601
602         /*
603          * Logging.  This may actually work on the gizmo board.  Find a name
604          * to log with by using the basename of argv[0]
605          */
606         cp = strrchr(argv[0], '/');
607         if (cp == 0)
608                 cp = argv[0];
609         else
610                 cp++;
611
612         debug = 0; /* will be immediately re-initialized 8-( */
613         getstartup(argc, argv); /* startup configuration, catch logfile this time */
614
615 #if !defined(VMS)
616
617 # ifndef LOG_DAEMON
618         openlog(cp, LOG_PID);
619 # else /* LOG_DAEMON */
620
621 #  ifndef LOG_NTP
622 #       define  LOG_NTP LOG_DAEMON
623 #  endif
624         openlog(cp, LOG_PID | LOG_NDELAY, LOG_NTP);
625 #  ifdef DEBUG
626         if (debug)
627                 setlogmask(LOG_UPTO(LOG_DEBUG));
628         else
629 #  endif /* DEBUG */
630                 setlogmask(LOG_UPTO(LOG_DEBUG)); /* @@@ was INFO */
631 # endif /* LOG_DAEMON */
632 #endif  /* !SYS_WINNT && !VMS */
633
634         NLOG(NLOG_SYSINFO) /* conditional if clause for conditional syslog */
635                 msyslog(LOG_NOTICE, "%s", Version);
636
637 #ifdef SYS_WINNT
638         /* GMS 1/18/1997
639          * TODO: lock the process in memory using SetProcessWorkingSetSize() and VirtualLock() functions
640          *
641          process_handle = GetCurrentProcess();
642          if (SetProcessWorkingSetSize(process_handle, 2097152 , 4194304 ) == TRUE) {
643          if (VirtualLock(0 , 4194304) == FALSE)
644          msyslog(LOG_ERR, "VirtualLock() failed: %m");
645          } else {
646          msyslog(LOG_ERR, "SetProcessWorkingSetSize() failed: %m");
647          }
648         */
649 #endif /* SYS_WINNT */
650
651 #ifdef SCO5_CLOCK
652         /*
653          * SCO OpenServer's system clock offers much more precise timekeeping
654          * on the base CPU than the other CPUs (for multiprocessor systems),
655          * so we must lock to the base CPU.
656          */
657         {
658             int fd = open("/dev/at1", O_RDONLY);
659             if (fd >= 0) {
660                 int zero = 0;
661                 if (ioctl(fd, ACPU_LOCK, &zero) < 0)
662                     msyslog(LOG_ERR, "cannot lock to base CPU: %m\n");
663                 close( fd );
664             } /* else ...
665                *   If we can't open the device, this probably just isn't
666                *   a multiprocessor system, so we're A-OK.
667                */
668         }
669 #endif
670
671 #if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE)
672 # ifdef HAVE_SETRLIMIT
673         /*
674          * Set the stack limit to something smaller, so that we don't lock a lot
675          * of unused stack memory.
676          */
677         {
678             struct rlimit rl;
679
680             if (getrlimit(RLIMIT_STACK, &rl) != -1
681                 && (rl.rlim_cur = 20 * 4096) < rl.rlim_max)
682             {
683                     if (setrlimit(RLIMIT_STACK, &rl) == -1)
684                     {
685                             msyslog(LOG_ERR,
686                                 "Cannot adjust stack limit for mlockall: %m");
687                     }
688             }
689         }
690 # endif /* HAVE_SETRLIMIT */
691         /*
692          * lock the process into memory
693          */
694         if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0)
695                 msyslog(LOG_ERR, "mlockall(): %m");
696 #else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
697 # ifdef HAVE_PLOCK
698 #  ifdef PROCLOCK
699 #   ifdef _AIX
700         /* 
701          * set the stack limit for AIX for plock().
702          * see get_aix_stack for more info.
703          */
704         if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0)
705         {
706                 msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m");
707         }
708 #   endif /* _AIX */
709         /*
710          * lock the process into memory
711          */
712         if (plock(PROCLOCK) < 0)
713                 msyslog(LOG_ERR, "plock(PROCLOCK): %m");
714 #  else /* not PROCLOCK */
715 #   ifdef TXTLOCK
716         /*
717          * Lock text into ram
718          */
719         if (plock(TXTLOCK) < 0)
720                 msyslog(LOG_ERR, "plock(TXTLOCK) error: %m");
721 #   else /* not TXTLOCK */
722         msyslog(LOG_ERR, "plock() - don't know what to lock!");
723 #   endif /* not TXTLOCK */
724 #  endif /* not PROCLOCK */
725 # endif /* HAVE_PLOCK */
726 #endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
727
728         /*
729          * Set up signals we pay attention to locally.
730          */
731 #ifdef SIGDIE1
732         (void) signal_no_reset(SIGDIE1, finish);
733 #endif  /* SIGDIE1 */
734 #ifdef SIGDIE2
735         (void) signal_no_reset(SIGDIE2, finish);
736 #endif  /* SIGDIE2 */
737 #ifdef SIGDIE3
738         (void) signal_no_reset(SIGDIE3, finish);
739 #endif  /* SIGDIE3 */
740 #ifdef SIGDIE4
741         (void) signal_no_reset(SIGDIE4, finish);
742 #endif  /* SIGDIE4 */
743
744 #ifdef SIGBUS
745         (void) signal_no_reset(SIGBUS, finish);
746 #endif /* SIGBUS */
747
748 #if !defined(SYS_WINNT) && !defined(VMS)
749 # ifdef DEBUG
750         (void) signal_no_reset(MOREDEBUGSIG, moredebug);
751         (void) signal_no_reset(LESSDEBUGSIG, lessdebug);
752 # else
753         (void) signal_no_reset(MOREDEBUGSIG, no_debug);
754         (void) signal_no_reset(LESSDEBUGSIG, no_debug);
755 # endif /* DEBUG */
756 #endif /* !SYS_WINNT && !VMS */
757
758         /*
759          * Set up signals we should never pay attention to.
760          */
761 #if defined SIGPIPE
762         (void) signal_no_reset(SIGPIPE, SIG_IGN);
763 #endif  /* SIGPIPE */
764
765 #if defined SYS_WINNT
766         if (!SetConsoleCtrlHandler(OnConsoleEvent, TRUE)) {
767                 msyslog(LOG_ERR, "Can't set console control handler: %m");
768         }
769 #endif
770
771         /*
772          * Call the init_ routines to initialize the data structures.
773          */
774 #if defined (HAVE_IO_COMPLETION_PORT)
775         init_io_completion_port();
776         init_winnt_time();
777 #endif
778         init_auth();
779         init_util();
780         init_restrict();
781         init_mon();
782         init_timer();
783         init_lib();
784         init_random();
785         init_request();
786         init_control();
787         init_peer();
788 #ifdef REFCLOCK
789         init_refclock();
790 #endif
791         set_process_priority();
792         init_proto();           /* Call at high priority */
793         init_io();
794         init_loopfilter();
795         mon_start(MON_ON);      /* monitor on by default now      */
796                                 /* turn off in config if unwanted */
797
798         /*
799          * Get configuration.  This (including argument list parsing) is
800          * done in a separate module since this will definitely be different
801          * for the gizmo board. While at it, save the host name for later
802          * along with the length. The crypto needs this.
803          */
804 #ifdef DEBUG
805         debug = 0;
806 #endif
807         getconfig(argc, argv);
808 #ifdef OPENSSL
809         crypto_setup();
810 #endif /* OPENSSL */
811         initializing = 0;
812
813 #if defined(SYS_WINNT) && !defined(NODETACH)
814 # if defined(DEBUG)
815         if(!debug)
816         {
817 # endif
818                 if (NoWinService == FALSE) {
819                 /* report to the service control manager that the service is running */
820                         ssStatus.dwCurrentState = SERVICE_RUNNING;
821                         ssStatus.dwWin32ExitCode = NO_ERROR;
822                         if (!SetServiceStatus(sshStatusHandle, &ssStatus))
823                         {
824                                 msyslog(LOG_ERR, "SetServiceStatus: %m");
825                                 if (ResolverThreadHandle != NULL)
826                                         CloseHandle(ResolverThreadHandle);
827                                 ssStatus.dwCurrentState = SERVICE_STOPPED;
828                                 SetServiceStatus(sshStatusHandle, &ssStatus);
829                                 return;
830                         }
831                 }
832 # if defined(DEBUG)
833         }
834 # endif  
835 #endif
836
837 #ifdef HAVE_CLOCKCTL
838         /* 
839          * Drop super-user privileges and chroot now if the OS supports
840          * non root clock control (only NetBSD for now).
841          */
842         if (user != NULL) {
843                 if (isdigit((unsigned char)*user)) {
844                         sw_uid = (uid_t)strtoul(user, &endp, 0);
845                         if (*endp != '\0') 
846                                 goto getuser;
847                 } else {
848 getuser:        
849                         if ((pw = getpwnam(user)) != NULL) {
850                                 sw_uid = pw->pw_uid;
851                         } else {
852                                 errno = 0;
853                                 msyslog(LOG_ERR, "Cannot find user `%s'", user);
854                                                                         exit (-1);
855                         }
856                 }
857         }
858         if (group != NULL) {
859                 if (isdigit((unsigned char)*group)) {
860                         sw_gid = (gid_t)strtoul(group, &endp, 0);
861                         if (*endp != '\0') 
862                                 goto getgroup;
863                 } else {
864 getgroup:       
865                         if ((gr = getgrnam(group)) != NULL) {
866                                 sw_gid = pw->pw_gid;
867                         } else {
868                                 errno = 0;
869                                 msyslog(LOG_ERR, "Cannot find group `%s'", group);
870                                                                         exit (-1);
871                         }
872                 }
873         }
874         if (chrootdir && chroot(chrootdir)) {
875                 msyslog(LOG_ERR, "Cannot chroot to `%s': %m", chrootdir);
876                 exit (-1);
877         }
878         if (group && setgid(sw_gid)) {
879                 msyslog(LOG_ERR, "Cannot setgid() to group `%s': %m", group);
880                 exit (-1);
881         }
882         if (group && setegid(sw_gid)) {
883                 msyslog(LOG_ERR, "Cannot setegid() to group `%s': %m", group);
884                 exit (-1);
885         }
886         if (user && setuid(sw_uid)) {
887                 msyslog(LOG_ERR, "Cannot setuid() to user `%s': %m", user);
888                 exit (-1);
889         }
890         if (user && seteuid(sw_uid)) {
891                 msyslog(LOG_ERR, "Cannot seteuid() to user `%s': %m", user);
892                 exit (-1);
893         }
894 #endif
895         /*
896          * Report that we're up to any trappers
897          */
898         report_event(EVNT_SYSRESTART, (struct peer *)0);
899
900         /*
901          * Use select() on all on all input fd's for unlimited
902          * time.  select() will terminate on SIGALARM or on the
903          * reception of input.  Using select() means we can't do
904          * robust signal handling and we get a potential race
905          * between checking for alarms and doing the select().
906          * Mostly harmless, I think.
907          */
908         /* On VMS, I suspect that select() can't be interrupted
909          * by a "signal" either, so I take the easy way out and
910          * have select() time out after one second.
911          * System clock updates really aren't time-critical,
912          * and - lacking a hardware reference clock - I have
913          * yet to learn about anything else that is.
914          */
915 #if defined(HAVE_IO_COMPLETION_PORT)
916                 WaitHandles[0] = CreateEvent(NULL, FALSE, FALSE, NULL); /* exit reques */
917                 WaitHandles[1] = get_timer_handle();
918                 WaitHandles[2] = get_io_event();
919
920                 for (;;) {
921                         DWORD Index = WaitForMultipleObjectsEx(sizeof(WaitHandles)/sizeof(WaitHandles[0]), WaitHandles, FALSE, 1000, TRUE);
922                         switch (Index) {
923                                 case WAIT_OBJECT_0 + 0 : /* exit request */
924                                         exit(0);
925                                 break;
926
927                                 case WAIT_OBJECT_0 + 1 : /* timer */
928                                         timer();
929                                 break;
930
931                                 case WAIT_OBJECT_0 + 2 : /* Io event */
932 # ifdef DEBUG
933                                         if ( debug > 3 )
934                                         {
935                                                 printf( "IoEvent occurred\n" );
936                                         }
937 # endif
938                                 break;
939
940                                 case WAIT_IO_COMPLETION : /* loop */
941                                 case WAIT_TIMEOUT :
942                                 break;
943                                 case WAIT_FAILED:
944                                         msyslog(LOG_ERR, "ntpdc: WaitForMultipleObjectsEx Failed: Error: %m");
945                                         break;
946
947                                 /* For now do nothing if not expected */
948                                 default:
949                                         break;          
950                                 
951                         } /* switch */
952                         rbuflist = getrecvbufs();       /* get received buffers */
953
954 #else /* normal I/O */
955
956         was_alarmed = 0;
957         rbuflist = (struct recvbuf *)0;
958         for (;;)
959         {
960 # if !defined(HAVE_SIGNALED_IO) 
961                 extern fd_set activefds;
962                 extern int maxactivefd;
963
964                 fd_set rdfdes;
965                 int nfound;
966 # elif defined(HAVE_SIGNALED_IO)
967                 block_io_and_alarm();
968 # endif
969
970                 rbuflist = getrecvbufs();       /* get received buffers */
971                 if (alarm_flag)         /* alarmed? */
972                 {
973                         was_alarmed = 1;
974                         alarm_flag = 0;
975                 }
976
977                 if (!was_alarmed && rbuflist == (struct recvbuf *)0)
978                 {
979                         /*
980                          * Nothing to do.  Wait for something.
981                          */
982 # ifndef HAVE_SIGNALED_IO
983                         rdfdes = activefds;
984 #  if defined(VMS) || defined(SYS_VXWORKS)
985                         /* make select() wake up after one second */
986                         {
987                                 struct timeval t1;
988
989                                 t1.tv_sec = 1; t1.tv_usec = 0;
990                                 nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
991                                                 (fd_set *)0, &t1);
992                         }
993 #  else
994                         nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
995                                         (fd_set *)0, (struct timeval *)0);
996 #  endif /* VMS */
997                         if (nfound > 0)
998                         {
999                                 l_fp ts;
1000
1001                                 get_systime(&ts);
1002
1003                                 (void)input_handler(&ts);
1004                         }
1005                         else if (nfound == -1 && errno != EINTR)
1006                                 msyslog(LOG_ERR, "select() error: %m");
1007 #  ifdef DEBUG
1008                         else if (debug > 2)
1009                                 msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
1010 #  endif /* DEBUG */
1011 # else /* HAVE_SIGNALED_IO */
1012                         
1013                         wait_for_signal();
1014 # endif /* HAVE_SIGNALED_IO */
1015                         if (alarm_flag)         /* alarmed? */
1016                         {
1017                                 was_alarmed = 1;
1018                                 alarm_flag = 0;
1019                         }
1020                         rbuflist = getrecvbufs();  /* get received buffers */
1021                 }
1022 # ifdef HAVE_SIGNALED_IO
1023                 unblock_io_and_alarm();
1024 # endif /* HAVE_SIGNALED_IO */
1025
1026                 /*
1027                  * Out here, signals are unblocked.  Call timer routine
1028                  * to process expiry.
1029                  */
1030                 if (was_alarmed)
1031                 {
1032                         timer();
1033                         was_alarmed = 0;
1034                 }
1035
1036 #endif /* HAVE_IO_COMPLETION_PORT */
1037                 /*
1038                  * Call the data procedure to handle each received
1039                  * packet.
1040                  */
1041                 while (rbuflist != (struct recvbuf *)0)
1042                 {
1043                         rbuf = rbuflist;
1044                         rbuflist = rbuf->next;
1045                         (rbuf->receiver)(rbuf);
1046                         freerecvbuf(rbuf);
1047                 }
1048 #if defined DEBUG && defined SYS_WINNT
1049                 if (debug > 4)
1050                     printf("getrecvbufs: %ld handler interrupts, %ld frames\n",
1051                            handler_calls, handler_pkts);
1052 #endif
1053
1054                 /*
1055                  * Go around again
1056                  */
1057         }
1058 #ifndef SYS_WINNT
1059         exit(1); /* unreachable */
1060 #endif
1061 #ifndef SYS_WINNT
1062         return 1;               /* DEC OSF cc braindamage */
1063 #endif
1064 }
1065
1066
1067 #ifdef SIGDIE2
1068 /*
1069  * finish - exit gracefully
1070  */
1071 static RETSIGTYPE
1072 finish(
1073         int sig
1074         )
1075 {
1076
1077         msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig);
1078
1079         switch (sig)
1080         {
1081 # ifdef SIGBUS
1082                 case SIGBUS:
1083                 printf("\nfinish(SIGBUS)\n");
1084                 exit(0);
1085 # endif
1086                 case 0:                 /* Should never happen... */
1087                 return;
1088                 default:
1089                 exit(0);
1090         }
1091 }
1092 #endif  /* SIGDIE2 */
1093
1094
1095 #ifdef DEBUG
1096 #ifndef SYS_WINNT
1097 /*
1098  * moredebug - increase debugging verbosity
1099  */
1100 static RETSIGTYPE
1101 moredebug(
1102         int sig
1103         )
1104 {
1105         int saved_errno = errno;
1106
1107         if (debug < 255)
1108         {
1109                 debug++;
1110                 msyslog(LOG_DEBUG, "debug raised to %d", debug);
1111         }
1112         errno = saved_errno;
1113 }
1114
1115 /*
1116  * lessdebug - decrease debugging verbosity
1117  */
1118 static RETSIGTYPE
1119 lessdebug(
1120         int sig
1121         )
1122 {
1123         int saved_errno = errno;
1124
1125         if (debug > 0)
1126         {
1127                 debug--;
1128                 msyslog(LOG_DEBUG, "debug lowered to %d", debug);
1129         }
1130         errno = saved_errno;
1131 }
1132 #endif
1133 #else /* not DEBUG */
1134 #ifndef SYS_WINNT/*
1135  * no_debug - We don't do the debug here.
1136  */
1137 static RETSIGTYPE
1138 no_debug(
1139         int sig
1140         )
1141 {
1142         int saved_errno = errno;
1143
1144         msyslog(LOG_DEBUG, "ntpd not compiled for debugging (signal %d)", sig);
1145         errno = saved_errno;
1146 }
1147 #endif  /* not SYS_WINNT */
1148 #endif  /* not DEBUG */
1149
1150 #ifdef SYS_WINNT
1151 /* service_ctrl - control handler for NTP service
1152  * signals the service_main routine of start/stop requests
1153  * from the control panel or other applications making
1154  * win32API calls
1155  */
1156 void
1157 service_ctrl(
1158         DWORD dwCtrlCode
1159         )
1160 {
1161         DWORD  dwState = SERVICE_RUNNING;
1162
1163         /* Handle the requested control code */
1164         switch(dwCtrlCode)
1165         {
1166                 case SERVICE_CONTROL_PAUSE:
1167                 /* see no reason to support this */
1168                 break;
1169
1170                 case SERVICE_CONTROL_CONTINUE:
1171                 /* see no reason to support this */
1172                 break;
1173
1174                 case SERVICE_CONTROL_STOP:
1175                         dwState = SERVICE_STOP_PENDING;
1176                         /*
1177                          * Report the status, specifying the checkpoint and waithint,
1178                          *      before setting the termination event.
1179                          */
1180                         ssStatus.dwCurrentState = dwState;
1181                         ssStatus.dwWin32ExitCode = NO_ERROR;
1182                         ssStatus.dwWaitHint = 3000;
1183                         if (!SetServiceStatus(sshStatusHandle, &ssStatus))
1184                         {
1185                                 msyslog(LOG_ERR, "SetServiceStatus: %m");
1186                         }
1187                         if (WaitHandles[0] != NULL) {
1188                                 SetEvent(WaitHandles[0]);
1189                         }
1190                 return;
1191
1192                 case SERVICE_CONTROL_INTERROGATE:
1193                 /* Update the service status */
1194                 break;
1195
1196                 default:
1197                 /* invalid control code */
1198                 break;
1199
1200         }
1201
1202         ssStatus.dwCurrentState = dwState;
1203         ssStatus.dwWin32ExitCode = NO_ERROR;
1204         if (!SetServiceStatus(sshStatusHandle, &ssStatus))
1205         {
1206                 msyslog(LOG_ERR, "SetServiceStatus: %m");
1207         }
1208 }
1209
1210 static BOOL WINAPI 
1211 OnConsoleEvent(  
1212         DWORD dwCtrlType
1213         )
1214 {
1215         switch (dwCtrlType) {
1216                 case CTRL_BREAK_EVENT :
1217                         if (debug > 0) {
1218                                 debug <<= 1;
1219                         }
1220                         else {
1221                                 debug = 1;
1222                         }
1223                         if (debug > 8) {
1224                                 debug = 0;
1225                         }
1226                         printf("debug level %d\n", debug);
1227                 break ;
1228
1229                 case CTRL_C_EVENT  :
1230                 case CTRL_CLOSE_EVENT :
1231                 case CTRL_SHUTDOWN_EVENT :
1232                         if (WaitHandles[0] != NULL) {
1233                                 SetEvent(WaitHandles[0]);
1234                         }
1235                 break;
1236
1237                 default :
1238                         return FALSE;
1239
1240
1241         }
1242         return TRUE;;
1243 }
1244
1245
1246 /*
1247  *  NT version of exit() - all calls to exit() should be routed to
1248  *  this function.
1249  */
1250 void
1251 service_exit(
1252         int status
1253         )
1254 {
1255         if (!debug) { /* did not become a service, simply exit */
1256                 /* service mode, need to have the service_main routine
1257                  * register with the service control manager that the 
1258                  * service has stopped running, before exiting
1259                  */
1260                 ssStatus.dwCurrentState = SERVICE_STOPPED;
1261                 SetServiceStatus(sshStatusHandle, &ssStatus);
1262
1263         }
1264         uninit_io_completion_port();
1265         reset_winnt_time();
1266
1267 # if defined _MSC_VER
1268         _CrtDumpMemoryLeaks();
1269 # endif 
1270 #undef exit     
1271         exit(status);
1272 }
1273
1274 #endif /* SYS_WINNT */