]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
[Bug 1395] ease ntpdate elimination with ntpd -w/--wait-sync
authorDave Hart <hart@ntp.org>
Sat, 19 Dec 2009 03:29:38 +0000 (03:29 +0000)
committerDave Hart <hart@ntp.org>
Sat, 19 Dec 2009 03:29:38 +0000 (03:29 +0000)
[Bug 1396] allow servers on ntpd command line like ntpdate

bk: 4b2c48a2vyaDih9UpW3W_Q4k3yB-fQ

19 files changed:
ChangeLog
include/ntp_config.h
include/ntp_machine.h
include/ntp_proto.h
include/ntpd.h
include/ntpsim.h
ntpd/Makefile.am
ntpd/cmd_args.c
ntpd/ntp_config.c
ntpd/ntp_loopfilter.c
ntpd/ntp_proto.c
ntpd/ntpd-opts.c
ntpd/ntpd-opts.def
ntpd/ntpd-opts.h
ntpd/ntpd-opts.texi
ntpd/ntpd.1
ntpd/ntpd.c
ntpd/ntpdbase-opts.def
ntpsnmpd/netsnmp_daemonize.c

index 2e96bac71e8c4966cca5c1a39635a47e91301aa1..23d567a89e246eafd8bedbcd1413449401c2c0b3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+* [Bug 1395] ease ntpdate elimination with ntpd -w/--wait-sync
+* [Bug 1396] allow servers on ntpd command line like ntpdate
 * [Bug 1387] Storage leak in ntp_intres (minor).
 * [Bug 1389] buffer overflow in refclock_oncore.c
 * [Bug 1391] .texi usage text from installed, not built binaries.
index 4a9be31a45e3bb4fa4f9c8f58713d33b8488fcab..4cd99e787377468bc8d0ff3103a724bda67c99ca 100644 (file)
@@ -59,7 +59,7 @@
  * to using numeric IP addresses.
  */
 #if defined(VMS) || defined (SYS_VXWORKS) || \
-    (!defined(HAVE_FORK) && !defined(SYS_WINNT))
+    (!defined(HAVE_WORKING_FORK) && !defined(SYS_WINNT))
 #define NO_INTRES
 #endif
 
 #define CONF_SOURCE_FILE               0
 #define CONF_SOURCE_NTPQ               1
 
+/* list of servers from command line for config_peers() */
+extern int     cmdline_server_count;
+extern char ** cmdline_servers;
+
 
 /* Structure for storing an attribute-value pair  */
 struct attr_val {
index 73fd172a2ef628d8b4fd0b93d8e298fe77e37a61..4852d92134c81d00e4f65c7146237122108fcff1 100644 (file)
@@ -261,8 +261,6 @@ int ntp_set_tod (struct timeval *tvp, void *tzp);
 #define HAVE_RANDOM            1       /* configure does not set this ...  */
 #define HAVE_SRANDOM           1       /* configure does not set this ... */
 
-#define NODETACH               1
-
 /* vxWorks specific additions to take care of its
  * unix (non)complicance
  */
index e6e78553305be423aa711ceec0f30a1fe5fd9971..1a5b03efb963b66b3fcc1ea61f9ad8537ad3b1e7 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ntp_proto_h
-#define __ntp_proto_h
+#ifndef NTP_PROTO_H
+#define NTP_PROTO_H
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -7,4 +7,4 @@
 
 #define NTP_MAXFREQ    500e-6
  
-#endif /* __ntp_proto_h */
+#endif /* NTP_PROTO_H */
index 14cf0add2c9ae433ab4ac3ebe969de610aff9679..c6044d841b565a184d6441e455743dae2be67628 100644 (file)
@@ -11,8 +11,8 @@
 #include "ntp_refclock.h"
 #include "recvbuff.h"
 
-/* ntp_config.c */
 
+/* ntp_config.c */
 #define        TAI_1972        10      /* initial TAI offset (s) */
 extern char    *keysdir;       /* crypto keys and leaptable directory */
 extern char *  saveconfigdir;  /* ntpq saveconfig output directory */
@@ -484,6 +484,10 @@ extern char *user;                 /* user to switch to */
 extern char *group;                    /* group to switch to */
 extern const char *chrootdir;          /* directory to chroot to */
 #endif
+#ifdef HAVE_WORKING_FORK
+extern int     waitsync_fd_to_close;   /* -w/--wait-sync */
+#endif
+
 
 /* refclock_conf.c */
 #ifdef REFCLOCK
index dbbfea0576d96e5a20d0abf5b95c686192254ca1..971c7f16340c542a3a3360589019fb459aa441af 100644 (file)
@@ -39,7 +39,6 @@
 #define NET_DLY .001            /* network delay */
 #define PROC_DLY .001          /* processing delay */
 #define BEEP_DLY 3600           /* beep interval (s) */
-#define        SLEW    500e-6          /* correction rate (PPM) */
 
 
 /* Discrete Event Queue
index 972c3006d8c6a3b58605664f45b9ce05ab95e3b2..033d19e0fd81c6a740ba82e3fc6bfb56d9b82d2b 100644 (file)
@@ -114,7 +114,6 @@ check-local: @MAKE_CHECK_Y2K@ $(CHECK_SAVECONFIG)
        test -z "@MAKE_CHECK_Y2K@" || ./@MAKE_CHECK_Y2K@
 
 ntpd_SOURCES =                 \
-       cmd_args.c              \
        ntp_config.c            \
        ntp_data_structures.c   \
        ntp_io.c                \
@@ -134,6 +133,7 @@ ntpdsim_SOURCES =           \
 # libntpd_a_SOURCES do not use #ifdef SIM
 
 libntpd_a_SOURCES =            \
+       cmd_args.c              \
        jupiter.h               \
        ntp_control.c           \
        ntp_crypto.c            \
index 1047b8b7f19ad46c47dc720a824f911625de1fc4..6c6885ece028c1954d4cc6d7a539cc27e8ce83ac 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "ntpd.h"
 #include "ntp_stdlib.h"
+#include "ntp_config.h"
 #include "ntp_cmdargs.h"
 
 #include "ntpd-opts.h"
@@ -34,7 +35,6 @@ getCmdOpts(
 {
        extern const char *config_file;
        int errflg;
-       tOptions *myOptions = &ntpdOptions;
 
        /*
         * Initialize, initialize
@@ -130,14 +130,16 @@ getCmdOpts(
 #endif
 
        if (HAVE_OPT( VAR )) {
-               int             ct = STACKCT_OPT(  VAR );
-               const char**    pp = STACKLST_OPT( VAR );
+               int             ct;
+               const char **   pp;
+               const char *    v_assign;
 
-               do  {
-                       const char* my_ntp_optarg = *pp++;
+               ct = STACKCT_OPT(  VAR );
+               pp = STACKLST_OPT( VAR );
 
-                       set_sys_var(my_ntp_optarg, strlen(my_ntp_optarg)+1,
-                           (u_short) (RW));
+               do  {
+                       v_assign = *pp++;
+                       set_sys_var(v_assign, strlen(v_assign) + 1, RW);
                } while (--ct > 0);
        }
 
@@ -157,6 +159,7 @@ getCmdOpts(
                clock_max = 600;
                kern_enable = 0;
        }
+
        if (HAVE_OPT( UPDATEINTERVAL )) {
                long val = OPT_VALUE_UPDATEINTERVAL;
                          
@@ -172,19 +175,15 @@ getCmdOpts(
                        errflg++;
                }
        }
-#ifdef SIM
-
-       /* SK:
-        * The simulator no longer takes any command line arguments. Hence,
-        * all the code that was here has been removed.
-        */
 
-#endif /* SIM */
 
-       if (errflg || argc) {
-               if (argc)
-                       fprintf(stderr, "argc after processing is <%d>\n", argc);
-               optionUsage(myOptions, 2);
+       /* save list of servers from cmd line for config_peers() use */
+       if (argc > 0) {
+               cmdline_server_count = argc;
+               cmdline_servers = argv;
        }
-       return;
+
+       /* display usage & exit with any option processing errors */
+       if (errflg)
+               optionUsage(&ntpdOptions, 2);   /* does not return */
 }
index f6e53cdaf8efe6b481266099a2e9e957d68b6caa..0261e1b5dbbd39ef28de4429f03dbc2fe00051df 100644 (file)
@@ -66,6 +66,10 @@ int resolver_pipe_fd[2];  /* used to let the resolver process alert the parent p
 #include "ntp_data_structures.h"
 
 
+/* list of servers from command line for config_peers() */
+int    cmdline_server_count;
+char **        cmdline_servers;
+
 /*
  * "logconfig" building blocks
  */
@@ -305,14 +309,11 @@ void ntpd_set_tod_using(const char *);
 static unsigned long get_pfxmatch(char **s,struct masks *m);
 static unsigned long get_match(char *s,struct masks *m);
 static unsigned long get_logmask(char *s);
-static int getnetnum(const char *num,sockaddr_u *addr, int complain,
-                    enum gnn_type a_type);
-static int get_multiple_netnums(const char *num, sockaddr_u *addr,
-                               struct addrinfo **res, int complain,
-                               enum gnn_type a_type);
-static void save_resolve(char *name, int mode, int version,
-                        int minpoll, int maxpoll, u_int flags,int ttl,
-                        keyid_t keyid,u_char *keystr);
+static int getnetnum(const char *, sockaddr_u *, int, enum gnn_type);
+static int get_multiple_netnums(const char *, sockaddr_u *, struct
+                               addrinfo **, int, enum gnn_type);
+static void save_resolve(char *, int, int, int, int, u_int, int ttl,
+                        keyid_t, u_char *);
 static void abort_resolve(void);
 static void do_resolve_internal(void);
 
@@ -3305,16 +3306,60 @@ config_peers(
        struct config_tree *ptree
        )
 {
-       struct addrinfo *res, *res_bak;
+       struct addrinfo *res;
+       struct addrinfo *one;
        sockaddr_u peeraddr;
        struct peer_node *curr_peer;
        struct attr_val *option;
        int hmode;
        int peerflags;
-       int status;
+       int rc;
        int no_needed;
        int i;
 
+       /* add servers named on the command line with iburst implied */
+       for (;
+            cmdline_server_count > 0;
+            cmdline_server_count--, cmdline_servers++) {
+
+               ZERO_SOCK(&peeraddr);
+               AF(&peeraddr) = default_ai_family;
+               rc = get_multiple_netnums(*cmdline_servers, &peeraddr,
+                                         &res, 0, t_UNK);
+               if (1 != rc) {
+                       msyslog(LOG_INFO, "Deferring DNS for %s",
+                               *cmdline_servers);
+                       save_resolve(*cmdline_servers,
+                                    MODE_CLIENT,
+                                    NTP_VERSION,
+                                    0,
+                                    0,
+                                    FLAG_IBURST,
+                                    0,
+                                    0,
+                                    (u_char *)"*");
+                       continue;
+               }
+               for (one = res; one != NULL; one = one->ai_next) {
+                       ZERO_SOCK(&peeraddr);
+                       memcpy(&peeraddr, one->ai_addr,
+                              one->ai_addrlen);
+                       if ((ipv6_works || !IS_IPV6(&peeraddr)) &&
+                           !IS_MCAST(&peeraddr))
+                               peer_config(&peeraddr,
+                                           NULL,
+                                           MODE_CLIENT,
+                                           NTP_VERSION,
+                                           0,
+                                           0,
+                                           FLAG_IBURST,
+                                           0,
+                                           0,
+                                           (u_char *)"*");
+               }
+               freeaddrinfo(res);
+       }
+
        curr_peer = queue_head(ptree->peers);
        while (curr_peer != NULL) {
                /* Find the number of associations needed.
@@ -3376,11 +3421,11 @@ config_peers(
                ZERO_SOCK(&peeraddr);
                AF(&peeraddr) = (u_short)curr_peer->addr->type;
 
-               status = get_multiple_netnums(curr_peer->addr->address,
+               rc = get_multiple_netnums(curr_peer->addr->address,
                    &peeraddr, &res, 0, t_UNK);
 
 #ifdef FORCE_DEFER_DNS /* Hack for debugging Deferred DNS */
-               if (status == 1) {
+               if (rc == 1) {
                        /* Deferring everything breaks refclocks. */
                        memcpy(&peeraddr, res->ai_addr, res->ai_addrlen);
                        if (!ISREFCLOCKADR(&peeraddr)) {
@@ -3398,7 +3443,7 @@ config_peers(
                 * The old code had this test, so I guess it must be
                 * useful
                 */
-               if (status == -1) {
+               if (rc == -1) {
                        /* Do nothing, apparently we found an IPv6
                         * address and can't do anything about it */
                }
@@ -3406,7 +3451,7 @@ config_peers(
                 * peer information in a file for asynchronous
                 * resolution later
                 */
-               else if (status != 1) {
+               else if (rc != 1) {
                        msyslog(LOG_INFO, "Deferring DNS for %s", curr_peer->addr->address);
                        save_resolve(curr_peer->addr->address,
                                     hmode,
@@ -3424,17 +3469,15 @@ config_peers(
                 * the peer
                 */
                else {
-                       res_bak = res;
-
                        /*
                         * Loop to configure the desired number of
                         * associations
                         */
-                       for (i = 0; (i < no_needed) && res; res =
-                           res->ai_next) {
-                               ++i;
-                               memcpy(&peeraddr, res->ai_addr,
-                                   res->ai_addrlen);
+                       for (i = 0, one = res; 
+                            i < no_needed && one != NULL;
+                            i++, one = one->ai_next) {
+                               memcpy(&peeraddr, one->ai_addr,
+                                      one->ai_addrlen);
                                if (is_sane_resolved_address(
                                        &peeraddr,
                                        curr_peer->host_mode))
@@ -3450,7 +3493,7 @@ config_peers(
                                            curr_peer->peerkey,
                                            (u_char *)"*");
                        }
-                       freeaddrinfo(res_bak);
+                       freeaddrinfo(res);
                }
                curr_peer = next_node(curr_peer);
        }
index 1846b552e4930e6468b8ae776b7ada29c907d680..baf4efbf7cd0988b6dac3987263dcaa2dccae24b 100644 (file)
@@ -260,7 +260,7 @@ local_clock(
                if (fabs(fp_offset) > clock_max && clock_max > 0) {
                        step_systime(fp_offset);
                        msyslog(LOG_NOTICE, "ntpd: time set %+.6f s",
-                           fp_offset);
+                           fp_offset);
                        printf("ntpd: time set %+.6fs\n", fp_offset);
                } else {
                        adj_systime(fp_offset);
@@ -344,7 +344,7 @@ local_clock(
 
                        clock_frequency = direct_freq(fp_offset);
 
-                       /* fall through to S_SPIK */
+                       /* fall through to EVNT_SPIK */
 
                /*
                 * In SPIK state we ignore succeeding outlyers until
@@ -404,7 +404,7 @@ local_clock(
                 * The offset is less than the step threshold. Calculate
                 * the jitter as the exponentially weighted offset
                 * differences.
-                */
+                */
                etemp = SQUARE(clock_jitter);
                dtemp = SQUARE(max(fabs(fp_offset - last_offset),
                    LOGTOD(sys_precision)));
@@ -629,7 +629,7 @@ local_clock(
        drift_file_sw = TRUE;
 
        /*
-        * Here we adjust the timeconstan by comparing the current
+        * Here we adjust the time constant by comparing the current
         * offset with the clock jitter. If the offset is less than the
         * clock jitter times a constant, then the averaging interval is
         * increased, otherwise it is decreased. A bit of hysteresis
@@ -713,7 +713,7 @@ adj_host_clock(
         * Implement the phase and frequency adjustments. The gain
         * factor (denominator) increases with poll interval, so is
         * dominated by the FLL above the Allan intercept.
-        */
+        */
        adjustment = clock_offset / (CLOCK_PLL * ULOGTOD(sys_poll));
        clock_offset -= adjustment;
        adj_systime(adjustment + drift_comp);
@@ -952,8 +952,8 @@ loop_config(
                        ntv.status = STA_UNSYNC;
                        ntp_adjtime(&ntv);
                        report_event(EVNT_KERN, NULL,
-                           "kernel time sync disabledx");
-                  }
+                           "kernel time sync disabled");
+               }
 #endif /* KERNEL_PLL */
 #endif /* LOCKCLOCK */
                break;
index db5e04d5c0168d5104902659552eb5af05e3f0ef..b4d5364cbae2a7b8c569892c68a12704313f027b 100644 (file)
 #include <stdio.h>
 #ifdef HAVE_LIBSCF_H
 #include <libscf.h>
+#endif
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif /* HAVE_LIBSCF_H */
-
+#endif
 
 #if defined(VMS) && defined(VMS_LOCALUNIT)     /*wjm*/
 #include "ntp_refclock.h"
@@ -1627,6 +1628,8 @@ clock_update(
        struct peer *peer       /* peer structure pointer */
        )
 {
+       struct peer *o_sys_peer;
+       u_char  o_sys_stratum;
        double  dtemp;
        l_fp    now;
 #ifdef HAVE_LIBSCF_H
@@ -1637,6 +1640,7 @@ clock_update(
         * Update the system state variables. We do this very carefully,
         * as the poll interval might need to be clamped differently.
         */
+       o_sys_peer = sys_peer;
        sys_peer = peer;
        sys_epoch = peer->epoch;
        if (sys_poll < peer->minpoll)
@@ -1644,6 +1648,7 @@ clock_update(
        if (sys_poll > peer->maxpoll)
                sys_poll = peer->maxpoll;
        poll_update(peer, sys_poll);
+       o_sys_stratum = sys_stratum;
        sys_stratum = min(peer->stratum + 1, STRATUM_UNSPEC);
        if (peer->stratum == STRATUM_REFCLOCK ||
            peer->stratum == STRATUM_UNSPEC)
@@ -1718,12 +1723,25 @@ clock_update(
                 * leap bits. If crypto, the timer will goose the setup
                 * process.
                 */
-               if (sys_leap == LEAP_NOTINSYNC) {
+               if (sys_leap == LEAP_NOTINSYNC || (o_sys_peer == NULL &&
+                   o_sys_stratum == (u_char)sys_orphan)) {
                        sys_leap = LEAP_NOWARNING;
 #ifdef OPENSSL
                        if (crypto_flags)
                                crypto_update();
 #endif /* OPENSSL */
+                       /*
+                        * If our parent process is waiting for the
+                        * first clock sync, send them home satisfied.
+                        */
+#ifdef HAVE_WORKING_FORK
+                       if (waitsync_fd_to_close != -1) {
+                               close(waitsync_fd_to_close);
+                               waitsync_fd_to_close = -1;
+                               DPRINTF(1, ("notified parent --wait-sync is done\n"));
+                       }
+#endif /* HAVE_WORKING_FORK */
+
                }
 
                /*
index 0afebc2b14ce1a2e1a735f5e598f03062dbef531..bd3ac2b84db37cfbed61175233bca732d0542b3b 100644 (file)
@@ -1,7 +1,7 @@
 /*  
  *  EDIT THIS FILE WITH CAUTION  (ntpd-opts.c)
  *  
- *  It has been AutoGen-ed  November 20, 2009 at 05:28:59 AM by AutoGen 5.10
+ *  It has been AutoGen-ed  December 19, 2009 at 03:08:03 AM by AutoGen 5.10
  *  From the definitions    ntpd-opts.def
  *  and the template file   options
  *
@@ -266,12 +266,16 @@ tSCC    zModifymmtimer_Name[]      = "modifymmtimer";
 #endif  /* SYS_WINNT */
 
 /*
- *  Nofork option description:
+ *  Nofork option description with
+ *  "Must also have options" and "Incompatible options":
  */
 tSCC    zNoforkText[] =
         "Do not fork";
 tSCC    zNofork_NAME[]             = "NOFORK";
 tSCC    zNofork_Name[]             = "nofork";
+static const int
+    aNoforkCantList[] = {
+    INDEX_OPT_WAIT_SYNC, NO_EQUIVALENT };
 #define NOFORK_FLAGS       (OPTST_DISABLED)
 
 /*
@@ -304,12 +308,17 @@ tSCC    zPriority_Name[]           = "priority";
         | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
 
 /*
- *  Quit option description:
+ *  Quit option description with
+ *  "Must also have options" and "Incompatible options":
  */
 tSCC    zQuitText[] =
         "Set the time and quit";
 tSCC    zQuit_NAME[]               = "QUIT";
 tSCC    zQuit_Name[]               = "quit";
+static const int
+    aQuitCantList[] = {
+    INDEX_OPT_SAVECONFIGQUIT,
+    INDEX_OPT_WAIT_SYNC, NO_EQUIVALENT };
 #define QUIT_FLAGS       (OPTST_DISABLED)
 
 /*
@@ -323,18 +332,24 @@ tSCC    zPropagationdelay_Name[]   = "propagationdelay";
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
- *  Saveconfigquit option description:
+ *  Saveconfigquit option description with
+ *  "Must also have options" and "Incompatible options":
  */
 #ifdef SAVECONFIG
 tSCC    zSaveconfigquitText[] =
         "Save parsed configuration and quit";
 tSCC    zSaveconfigquit_NAME[]     = "SAVECONFIGQUIT";
 tSCC    zSaveconfigquit_Name[]     = "saveconfigquit";
+static const int
+    aSaveconfigquitCantList[] = {
+    INDEX_OPT_QUIT,
+    INDEX_OPT_WAIT_SYNC, NO_EQUIVALENT };
 #define SAVECONFIGQUIT_FLAGS       (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 #else   /* disable Saveconfigquit */
 #define SAVECONFIGQUIT_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define aSaveconfigquitCantList   NULL
 #define zSaveconfigquit_NAME      NULL
 #define zSaveconfigquitText       NULL
 #define zSaveconfigquit_Name      NULL
@@ -408,6 +423,31 @@ tSCC    zDvar_Name[]               = "dvar";
 #define DVAR_FLAGS       (OPTST_DISABLED | OPTST_STACKED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
+/*
+ *  Wait_Sync option description with
+ *  "Must also have options" and "Incompatible options":
+ */
+#ifdef HAVE_WORKING_FORK
+tSCC    zWait_SyncText[] =
+        "Seconds to wait for first clock sync";
+tSCC    zWait_Sync_NAME[]          = "WAIT_SYNC";
+tSCC    zWait_Sync_Name[]          = "wait-sync";
+static const int
+    aWait_SyncCantList[] = {
+    INDEX_OPT_NOFORK,
+    INDEX_OPT_QUIT,
+    INDEX_OPT_SAVECONFIGQUIT, NO_EQUIVALENT };
+#define WAIT_SYNC_FLAGS       (OPTST_DISABLED \
+        | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
+
+#else   /* disable Wait_Sync */
+#define WAIT_SYNC_FLAGS       (OPTST_OMITTED | OPTST_NO_INIT)
+#define aWait_SyncCantList   NULL
+#define zWait_Sync_NAME      NULL
+#define zWait_SyncText       NULL
+#define zWait_Sync_Name      NULL
+#endif  /* HAVE_WORKING_FORK */
+
 /*
  *  Slew option description:
  */
@@ -483,6 +523,11 @@ tSCC zVersion_Name[]      = "version";
 #else /* not DEBUG */
 # define doOptSet_Debug_Level NULL
 #endif /* def/not DEBUG */
+#ifdef HAVE_WORKING_FORK
+  static tOptProc doOptWait_Sync;
+#else /* not HAVE_WORKING_FORK */
+# define doOptWait_Sync NULL
+#endif /* def/not HAVE_WORKING_FORK */
 #if defined(TEST_NTPD_OPTS)
 /*
  *  Under test, omit argument processing, or call optionStackArg,
@@ -498,6 +543,7 @@ static tOptProc
  *  #define map the "normal" callout procs to the test ones...
  */
 #define SET_DEBUG_LEVEL_OPT_PROC optionStackArg
+#define WAIT_SYNC_OPT_PROC optionStackArg
 
 
 #else /* NOT defined TEST_NTPD_OPTS */
@@ -513,8 +559,10 @@ static tOptProc
  *  #define map the "normal" callout procs
  */
 #define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+#define WAIT_SYNC_OPT_PROC doOptWait_Sync
 
 #define SET_DEBUG_LEVEL_OPT_PROC doOptSet_Debug_Level
+#define WAIT_SYNC_OPT_PROC doOptWait_Sync
 #endif /* defined(TEST_NTPD_OPTS) */
 #ifdef TEST_NTPD_OPTS
 # define DOVERPROC optionVersionStderr
@@ -726,7 +774,7 @@ static tOptDesc optDesc[ OPTION_CT ] = {
      /* opt state flags  */ NOFORK_FLAGS, 0,
      /* last opt argumnt */ { NULL },
      /* arg list/cookie  */ NULL,
-     /* must/cannot opts */ NULL, NULL,
+     /* must/cannot opts */ NULL, aNoforkCantList,
      /* option proc      */ NULL,
      /* desc, NAME, name */ zNoforkText, zNofork_NAME, zNofork_Name,
      /* disablement strs */ NULL, NULL },
@@ -774,7 +822,7 @@ static tOptDesc optDesc[ OPTION_CT ] = {
      /* opt state flags  */ QUIT_FLAGS, 0,
      /* last opt argumnt */ { NULL },
      /* arg list/cookie  */ NULL,
-     /* must/cannot opts */ NULL, NULL,
+     /* must/cannot opts */ NULL, aQuitCantList,
      /* option proc      */ NULL,
      /* desc, NAME, name */ zQuitText, zQuit_NAME, zQuit_Name,
      /* disablement strs */ NULL, NULL },
@@ -798,7 +846,7 @@ static tOptDesc optDesc[ OPTION_CT ] = {
      /* opt state flags  */ SAVECONFIGQUIT_FLAGS, 0,
      /* last opt argumnt */ { NULL },
      /* arg list/cookie  */ NULL,
-     /* must/cannot opts */ NULL, NULL,
+     /* must/cannot opts */ NULL, aSaveconfigquitCantList,
      /* option proc      */ NULL,
      /* desc, NAME, name */ zSaveconfigquitText, zSaveconfigquit_NAME, zSaveconfigquit_Name,
      /* disablement strs */ NULL, NULL },
@@ -875,8 +923,20 @@ static tOptDesc optDesc[ OPTION_CT ] = {
      /* desc, NAME, name */ zDvarText, zDvar_NAME, zDvar_Name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 29, VALUE_OPT_SLEW,
-     /* equiv idx, value */ 29, VALUE_OPT_SLEW,
+  {  /* entry idx, value */ 29, VALUE_OPT_WAIT_SYNC,
+     /* equiv idx, value */ 29, VALUE_OPT_WAIT_SYNC,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ WAIT_SYNC_FLAGS, 0,
+     /* last opt argumnt */ { NULL },
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, aWait_SyncCantList,
+     /* option proc      */ WAIT_SYNC_OPT_PROC,
+     /* desc, NAME, name */ zWait_SyncText, zWait_Sync_NAME, zWait_Sync_Name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 30, VALUE_OPT_SLEW,
+     /* equiv idx, value */ 30, VALUE_OPT_SLEW,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ SLEW_FLAGS, 0,
@@ -887,8 +947,8 @@ static tOptDesc optDesc[ OPTION_CT ] = {
      /* desc, NAME, name */ zSlewText, zSlew_NAME, zSlew_Name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 30, VALUE_OPT_USEPCC,
-     /* equiv idx, value */ 30, VALUE_OPT_USEPCC,
+  {  /* entry idx, value */ 31, VALUE_OPT_USEPCC,
+     /* equiv idx, value */ 31, VALUE_OPT_USEPCC,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ USEPCC_FLAGS, 0,
@@ -899,8 +959,8 @@ static tOptDesc optDesc[ OPTION_CT ] = {
      /* desc, NAME, name */ zUsepccText, zUsepcc_NAME, zUsepcc_Name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 31, VALUE_OPT_PCCFREQ,
-     /* equiv idx, value */ 31, VALUE_OPT_PCCFREQ,
+  {  /* entry idx, value */ 32, VALUE_OPT_PCCFREQ,
+     /* equiv idx, value */ 32, VALUE_OPT_PCCFREQ,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PCCFREQ_FLAGS, 0,
@@ -957,7 +1017,8 @@ static tOptDesc optDesc[ OPTION_CT ] = {
 tSCC   zPROGNAME[]   = "NTPD";
 tSCC   zUsageTitle[] =
 "ntpd - NTP daemon program - Ver. 4.2.5p247-RC\n\
-USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n";
+USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]... \\\n\
+\t\t[ <server1> ... <serverN> ]\n";
 #define zRcName     NULL
 #define apzHomeList NULL
 
@@ -965,7 +1026,7 @@ tSCC   zBugsAddr[]    = "http://bugs.ntp.org, bugs@ntp.org";
 #define zExplain NULL
 tSCC    zDetail[]     = "\n\n";
 tSCC    zFullVersion[] = NTPD_FULL_VERSION;
-/* extracted from /usr/local/gnu/share/autogen/optcode.tpl near line 495 */
+/* extracted from /usr/local/share/autogen/optcode.tpl near line 495 */
 
 #if defined(ENABLE_NLS)
 # define OPTPROC_BASE OPTPROC_TRANSLATE
@@ -986,8 +1047,7 @@ tOptions ntpdOptions = {
     + OPTPROC_SHORTOPT
     + OPTPROC_LONGOPT
     + OPTPROC_NO_REQ_OPT
-    + OPTPROC_ENVIRON
-    + OPTPROC_NO_ARGS ),
+    + OPTPROC_ENVIRON ),
     0, NULL,                    /* current option index, current option */
     NULL,         NULL,         zPROGNAME,
     zRcName,      zCopyright,   zCopyrightNotice,
@@ -1005,7 +1065,7 @@ tOptions ntpdOptions = {
       NO_EQUIVALENT, /* '-#' option index */
       NO_EQUIVALENT /* index of default opt */
     },
-    35 /* full option count */, 32 /* user option count */,
+    36 /* full option count */, 33 /* user option count */,
     ntpd_full_usage, ntpd_short_usage,
     NULL, NULL
 };
@@ -1037,7 +1097,24 @@ DESC(DEBUG_LEVEL).optOccCt = atoi( pOptDesc->pzLastArg );
 }
 #endif /* defined DEBUG */
 #endif /* defined(TEST_NTPD_OPTS) */
-/* extracted from /usr/local/gnu/share/autogen/optmain.tpl near line 109 */
+
+#if ! defined(TEST_NTPD_OPTS)
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *   For the wait-sync option, when HAVE_WORKING_FORK is #define-d.
+ */
+#ifdef HAVE_WORKING_FORK
+static void
+doOptWait_Sync(tOptions* pOptions, tOptDesc* pOptDesc)
+{
+    /* extracted from ntpdbase-opts.def, line 423 */
+extern tOptProc optionNumericVal;
+optionNumericVal(pOptions, pOptDesc);
+}
+#endif /* defined HAVE_WORKING_FORK */
+#endif /* defined(TEST_NTPD_OPTS) */
+/* extracted from /usr/local/share/autogen/optmain.tpl near line 109 */
 
 #if defined(TEST_NTPD_OPTS) /* TEST MAIN PROCEDURE: */
 
@@ -1052,7 +1129,7 @@ main(int argc, char** argv)
     return res;
 }
 #endif  /* defined TEST_NTPD_OPTS */
-/* extracted from /usr/local/gnu/share/autogen/optcode.tpl near line 627 */
+/* extracted from /usr/local/share/autogen/optcode.tpl near line 627 */
 
 #if ENABLE_NLS
 #include <stdio.h>
index 7266e1b2aea4b92f0e2b4f7db99bb4f69e1da9b7..9f51e2e24d0a17239bd59d9ffc8c4244da25c1be 100644 (file)
@@ -4,8 +4,9 @@ autogen definitions options;
 
 #include copyright.def
 
-prog-name      = "ntpd";
-prog-title     = "NTP daemon program";
+prog-name      = "ntpd";
+prog-title     = "NTP daemon program";
+argument       = "[ <server1> ... <serverN> ]";
 
 #include ntpdbase-opts.def
 
index f90f75f1b14f03d3c1a67c4ea287f834ece6146f..0410f5fb6025ccd06b69c11d5cd4bc00d5ac4889 100644 (file)
@@ -1,7 +1,7 @@
 /*  
  *  EDIT THIS FILE WITH CAUTION  (ntpd-opts.h)
  *  
- *  It has been AutoGen-ed  November 20, 2009 at 05:28:58 AM by AutoGen 5.10
+ *  It has been AutoGen-ed  December 19, 2009 at 03:08:02 AM by AutoGen 5.10
  *  From the definitions    ntpd-opts.def
  *  and the template file   options
  *
@@ -81,15 +81,16 @@ typedef enum {
     INDEX_OPT_UPDATEINTERVAL    = 26,
     INDEX_OPT_VAR               = 27,
     INDEX_OPT_DVAR              = 28,
-    INDEX_OPT_SLEW              = 29,
-    INDEX_OPT_USEPCC            = 30,
-    INDEX_OPT_PCCFREQ           = 31,
-    INDEX_OPT_VERSION           = 32,
-    INDEX_OPT_HELP              = 33,
-    INDEX_OPT_MORE_HELP         = 34
+    INDEX_OPT_WAIT_SYNC         = 29,
+    INDEX_OPT_SLEW              = 30,
+    INDEX_OPT_USEPCC            = 31,
+    INDEX_OPT_PCCFREQ           = 32,
+    INDEX_OPT_VERSION           = 33,
+    INDEX_OPT_HELP              = 34,
+    INDEX_OPT_MORE_HELP         = 35
 } teOptIndex;
 
-#define OPTION_CT    35
+#define OPTION_CT    36
 #define NTPD_VERSION       "4.2.5p247-RC"
 #define NTPD_FULL_VERSION  "ntpd - NTP daemon program - Ver. 4.2.5p247-RC"
 
@@ -234,6 +235,10 @@ typedef enum {
 #  warning undefining DVAR due to option name conflict
 #  undef   DVAR
 # endif
+# ifdef    WAIT_SYNC
+#  warning undefining WAIT_SYNC due to option name conflict
+#  undef   WAIT_SYNC
+# endif
 # ifdef    SLEW
 #  warning undefining SLEW due to option name conflict
 #  undef   SLEW
@@ -276,6 +281,7 @@ typedef enum {
 # undef UPDATEINTERVAL
 # undef VAR
 # undef DVAR
+# undef WAIT_SYNC
 # undef SLEW
 # undef USEPCC
 # undef PCCFREQ
@@ -318,9 +324,10 @@ typedef enum {
 #define OPT_VALUE_UPDATEINTERVAL (DESC(UPDATEINTERVAL).optArg.argInt)
 #define VALUE_OPT_VAR            27
 #define VALUE_OPT_DVAR           28
+#define VALUE_OPT_WAIT_SYNC      'w'
 #define VALUE_OPT_SLEW           'x'
-#define VALUE_OPT_USEPCC         30
-#define VALUE_OPT_PCCFREQ        31
+#define VALUE_OPT_USEPCC         31
+#define VALUE_OPT_PCCFREQ        32
 #define VALUE_OPT_HELP          '?'
 #define VALUE_OPT_MORE_HELP     '!'
 #define VALUE_OPT_VERSION       INDEX_OPT_VERSION
@@ -334,7 +341,7 @@ typedef enum {
                 ntpdOptions.pzCurOpt  = NULL )
 #define START_OPT       RESTART_OPT(1)
 #define USAGE(c)        (*ntpdOptions.pUsageProc)( &ntpdOptions, c )
-/* extracted from /usr/local/gnu/share/autogen/opthead.tpl near line 409 */
+/* extracted from /usr/local/share/autogen/opthead.tpl near line 409 */
 
 /* * * * * *
  *
index 629ef4d968e8c05aacbdc44fc0cf0423b97adfb4..2e0da335ceaced6a84f3430524f65746a4b7f159 100644 (file)
@@ -6,7 +6,7 @@
 # 
 # EDIT THIS FILE WITH CAUTION  (ntpd-opts.texi)
 # 
-# It has been AutoGen-ed  November 20, 2009 at 05:29:01 AM by AutoGen 5.10
+# It has been AutoGen-ed  December 19, 2009 at 03:09:15 AM by AutoGen 5.10
 # From the definitions    ntpd-opts.def
 # and the template file   aginfo.tpl
 @end ignore
@@ -53,6 +53,7 @@ This software is released under a specialized copyright license.
 * ntpd usepcc::                 usepcc option
 * ntpd user::                   user option (-u)
 * ntpd var::                    var option
+* ntpd wait-sync::              wait-sync option (-w)
 @end menu
 
 @node ntpd usage
@@ -63,12 +64,16 @@ This is the automatically generated usage text for ntpd:
 
 @exampleindent 0
 @example
-ntpd - NTP daemon program - Ver. 4.2.5p242-RC
-USAGE:  ntpd [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
+ntpd - NTP daemon program - Ver. 4.2.5p247-RC
+USAGE:  ntpd [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]... \
+                [ <server1> ... <serverN> ]
   Flg Arg Option-Name    Description
    -4 no  ipv4           Force IPv4 DNS name resolution
+                                - prohibits these options:
+                                ipv6
    -6 no  ipv6           Force IPv6 DNS name resolution
-                                - an alternate for ipv4
+                                - prohibits these options:
+                                ipv4
    -a no  authreq        Require crypto authentication
                                 - prohibits these options:
                                 authnoreq
@@ -84,29 +89,44 @@ USAGE:  ntpd [ -<flag> [<val>] | --<name>[@{=| @}<val>] ]...
    -f Str driftfile      frequency drift file name
    -g no  panicgate      Allow the first adjustment to be Big
                                 - may appear multiple times
+   -i --- jaildir        built without --enable-clockctl or --enable-linuxcaps
    -I Str interface      Listen on an interface name or address
                                 - may appear multiple times
    -k Str keyfile        path to symmetric keys
    -l Str logfile        path to the log file
    -L no  novirtualips   Do not listen to virtual interfaces
    -n no  nofork         Do not fork
+                                - prohibits these options:
+                                wait-sync
    -N no  nice           Run at high priority
    -p Str pidfile        path to the PID file
    -P Num priority       Process priority
    -q no  quit           Set the time and quit
+                                - prohibits these options:
+                                saveconfigquit
+                                wait-sync
    -r Str propagationdelay Broadcast/propagation delay
       Str saveconfigquit Save parsed configuration and quit
+                                - prohibits these options:
+                                quit
+                                wait-sync
    -s Str statsdir       Statistics file location
    -t Str trustedkey     Trusted key number
                                 - may appear multiple times
+   -u --- user           built without --enable-clockctl or --enable-linuxcaps
    -U Num updateinterval interval in seconds between scans for new or dropped interfaces
       Str var            make ARG an ntp variable (RW)
                                 - may appear multiple times
       Str dvar           make ARG an ntp variable (RW|DEF)
                                 - may appear multiple times
+   -w Str wait-sync      Seconds to wait for first clock sync
+                                - prohibits these options:
+                                nofork
+                                quit
+                                saveconfigquit
    -x no  slew           Slew up to 600 seconds
-      opt version        Output version information and exit
-   -? no  help           Display usage information and exit
+   -! opt version        Output version information and exit
+   -? no  help           Display extended usage information and exit
    -! no  more-help      Extended usage information passed thru pager
 
 Options are specified by doubled hyphens and their name
@@ -375,6 +395,14 @@ avoiding timekeeping glitches associated with changes.
 
 This is the ``do not fork'' option.
 
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+wait-sync.
+@end itemize
+
+
 
 @node ntpd nice
 @subsection nice option (-N)
@@ -413,10 +441,19 @@ priority.
 @cindex ntpd-quit
 
 This is the ``set the time and quit'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must not appear in combination with any of the following options:
+saveconfigquit, wait-sync.
+@end itemize
+
 ntpd
-will exit just after the first time the clock is set. This behavior mimics that of the
+will not daemonize and will exit after the clock is first
+synchronized.  This behavior mimics that of the
 ntpdate
-program, which is to be retired.
+program, which will soon be replaced with a shell script.
 The
 -g
 and
@@ -441,6 +478,9 @@ This option has some usage constraints.  It:
 @itemize @bullet
 @item
 must be compiled in by defining @code{SAVECONFIG} during the compilation.
+@item
+must not appear in combination with any of the following options:
+quit, wait-sync.
 @end itemize
 
 Cause ntpd to parse its startup configuration file and save an
@@ -530,6 +570,30 @@ may appear an unlimited number of times.
 
 
 
+@node ntpd wait-sync
+@subsection wait-sync option (-w)
+@cindex ntpd-wait-sync
+
+This is the ``seconds to wait for first clock sync'' option.
+
+This option has some usage constraints.  It:
+@itemize @bullet
+@item
+must be compiled in by defining @code{HAVE_WORKING_FORK} during the compilation.
+@item
+must not appear in combination with any of the following options:
+nofork, quit, saveconfigquit.
+@end itemize
+
+If greater than zero, alters ntpd behavior when forking to
+daemonize.  Instead of exiting with status 0 immediately after
+the fork, the parent waits up to the specified number of
+seconds for the child to first synchronize the clock.  The exit
+status is zero (success) if the clock was synchronized,
+otherwise it is ETIMEDOUT.
+This provides the option for a script starting ntpd to easily
+wait for the first set of the clock before proceeding.
+
 @node ntpd slew
 @subsection slew option (-x)
 @cindex ntpd-slew
index 508ca9222ce813af1bec72703877bc684285edcb..8acc5fd34f19294b65690e032f13af1345f8d6c2 100644 (file)
@@ -1,7 +1,7 @@
-.TH NTPD 1 2009-11-20 "( 4.2.5p247-RC)" "Programmer's Manual"
+.TH NTPD 1 2009-12-19 "( 4.2.5p247-RC)" "Programmer's Manual"
 .\"  EDIT THIS FILE WITH CAUTION  (ntpd.1)
 .\"  
-.\"  It has been AutoGen-ed  November 20, 2009 at 05:29:00 AM by AutoGen 5.10
+.\"  It has been AutoGen-ed  December 19, 2009 at 03:08:03 AM by AutoGen 5.10
 .\"  From the definitions    ntpd-opts.def
 .\"  and the template file   agman1.tpl
 .\"
@@ -11,8 +11,9 @@ ntpd \- NTP daemon program
 .B ntpd
 .\" Mixture of short (flag) options and long options
 .RB [ \-\fIflag\fP " [\fIvalue\fP]]... [" \--\fIopt-name\fP " [[=| ]\fIvalue\fP]]..."
-.PP
-All arguments must be options.
+.br
+.in +8
+[ <server1> ... <serverN> ]
 .SH "DESCRIPTION"
 This manual page briefly documents the \fBntpd\fP command.
 
@@ -170,6 +171,8 @@ avoiding timekeeping glitches associated with changes.
 .TP
 .BR \-n ", " \--nofork
 Do not fork.
+This option must not appear in combination with any of the following options:
+wait-sync.
 .sp
 
 .TP
@@ -202,11 +205,14 @@ priority.
 .TP
 .BR \-q ", " \--quit
 Set the time and quit.
+This option must not appear in combination with any of the following options:
+saveconfigquit, wait-sync.
 .sp
 ntpd
-will exit just after the first time the clock is set. This behavior mimics that of the
+will not daemonize and will exit after the clock is first
+synchronized.  This behavior mimics that of the
 ntpdate
-program, which is to be retired.
+program, which will soon be replaced with a shell script.
 The
 -g
 and
@@ -221,6 +227,8 @@ Specify the default propagation delay from the broadcast/multicast server to thi
 .TP
 .BR \--saveconfigquit "=\fIstring\fP"
 Save parsed configuration and quit.
+This option must not appear in combination with any of the following options:
+quit, wait-sync.
 .sp
 Cause ntpd to parse its startup configuration file and save an
 equivalent to the given filename and exit.  This option was
@@ -272,6 +280,20 @@ make ARG an ntp variable (RW|DEF).
 This option may appear an unlimited number of times.
 .sp
 
+.TP
+.BR \-w " \fIstring\fP, " \--wait-sync "=" \fIstring\fP
+Seconds to wait for first clock sync.
+This option must not appear in combination with any of the following options:
+nofork, quit, saveconfigquit.
+.sp
+If greater than zero, alters ntpd behavior when forking to
+daemonize.  Instead of exiting with status 0 immediately after
+the fork, the parent waits up to the specified number of
+seconds for the child to first synchronize the clock.  The exit
+status is zero (success) if the clock was synchronized,
+otherwise it is ETIMEDOUT.
+This provides the option for a script starting ntpd to easily
+wait for the first set of the clock before proceeding.
 .TP
 .BR \-x ", " \--slew
 Slew up to 600 seconds.
index 62e4f98052e511372b1caff85cb6f11abfe39d65..06a943ae464c9d967d393d5c68636336fe95be6f 100644 (file)
 # include <sys/stat.h>
 #endif
 #include <stdio.h>
-#if !defined(VMS)      /*wjm*/
-# ifdef HAVE_SYS_PARAM_H
-#  include <sys/param.h>
-# endif
-#endif /* VMS */
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
 #ifdef HAVE_SYS_SIGNAL_H
 # include <sys/signal.h>
 #else
 DNSServiceRef mdns;
 #endif
 
+#ifdef HAVE_SETPGRP_0
+#define ntp_setpgrp(x, y)      setpgrp()
+#else
+#define ntp_setpgrp(x, y)      setpgrp(x, y)
+#endif
+
 /*
  * Scheduling priority we run at
  */
@@ -182,6 +186,10 @@ struct group *gr;
 struct passwd *pw;
 #endif /* HAVE_DROPROOT */
 
+#ifdef HAVE_WORKING_FORK
+int    waitsync_fd_to_close = -1;      /* -w/--wait-sync */
+#endif
+
 /*
  * Initializing flag.  All async routines watch this and only do their
  * thing when it is clear.
@@ -205,35 +213,44 @@ extern int syscall        (int, ...);
 #endif /* DECL_SYSCALL */
 
 
-#ifdef SIGDIE2
+#if !defined(SIM) && defined(SIGDIE2)
 static RETSIGTYPE      finish          (int);
-#endif /* SIGDIE2 */
+#endif
 
-#ifdef DEBUG
-#ifndef SYS_WINNT
+#if !defined(SIM) && defined(HAVE_WORKING_FORK)
+static int     wait_child_sync_if      (int, long);
+#endif
+
+#if !defined(SIM) && !defined(SYS_WINNT)
+# ifdef        DEBUG
 static RETSIGTYPE      moredebug       (int);
 static RETSIGTYPE      lessdebug       (int);
-#endif
-#else /* not DEBUG */
+# else /* !DEBUG follows */
 static RETSIGTYPE      no_debug        (int);
-#endif /* not DEBUG */
+# endif        /* !DEBUG */
+#endif /* !SIM && !SYS_WINNT */
 
+#ifndef SIM
 int            ntpdmain                (int, char **);
 static void    set_process_priority    (void);
+static void    assertion_failed        (const char *, int,
+                                        isc_assertiontype_t,
+                                        const char *);
+static void    library_fatal_error     (const char *, int, 
+                                        const char *, va_list)
+                                       ISC_FORMAT_PRINTF(3, 0);
+static void    library_unexpected_error(const char *, int,
+                                        const char *, va_list)
+                                       ISC_FORMAT_PRINTF(3, 0);
+#endif /* !SIM */
 void           init_logging            (char const *, int);
 void           setup_logfile           (void);
 static void    process_commandline_opts(int *, char ***);
 
-static void    assertion_failed        (const char *file, int line,
-       isc_assertiontype_t type, const char *cond);
-static void    library_fatal_error     (const char *file, int line,
-       const char *format, va_list args) ISC_FORMAT_PRINTF(3, 0);
-static void    library_unexpected_error(const char *file, int line,
-       const char *format, va_list args) ISC_FORMAT_PRINTF(3, 0);
-
 
 /*
- * Initialize the logging
+ * init_logging - connect to syslog 
+ *               (-l/--logfile and ntp.conf logfile are handled later)
  */
 void
 init_logging(
@@ -341,10 +358,10 @@ main(
 
        return ntpsim(argc, argv);
 }
-#else /* SIM */
+#else  /* !SIM follows */
 #ifdef NO_MAIN_ALLOWED
 CALL(ntpd,"ntpd",ntpdmain);
-#else
+#else  /* !NO_MAIN_ALLOWED follows */
 #ifndef SYS_WINNT
 int
 main(
@@ -354,9 +371,9 @@ main(
 {
        return ntpdmain(argc, argv);
 }
-#endif /* SYS_WINNT */
-#endif /* NO_MAIN_ALLOWED */
-#endif /* SIM */
+#endif /* !SYS_WINNT */
+#endif /* !NO_MAIN_ALLOWED */
+#endif /* !SIM */
 
 #ifdef _AIX
 /*
@@ -395,11 +412,12 @@ catch_danger(int signo)
 /*
  * Set the process priority
  */
+#ifndef SIM
 static void
 set_process_priority(void)
 {
 
-#ifdef DEBUG
+# ifdef DEBUG
        if (debug > 1)
                msyslog(LOG_DEBUG, "set_process_priority: %s: priority_done is <%d>",
                        ((priority_done)
@@ -407,9 +425,9 @@ set_process_priority(void)
                         : "Attempt to set priority"
                                ),
                        priority_done);
-#endif /* DEBUG */
+# endif /* DEBUG */
 
-#if defined(HAVE_SCHED_SETSCHEDULER)
+# if defined(HAVE_SCHED_SETSCHEDULER)
        if (!priority_done) {
                extern int config_priority_override, config_priority;
                int pmax, pmin;
@@ -431,9 +449,9 @@ set_process_priority(void)
                else
                        ++priority_done;
        }
-#endif /* HAVE_SCHED_SETSCHEDULER */
-#if defined(HAVE_RTPRIO)
-# ifdef RTP_SET
+# endif /* HAVE_SCHED_SETSCHEDULER */
+# ifdef HAVE_RTPRIO
+#  ifdef RTP_SET
        if (!priority_done) {
                struct rtprio srtp;
 
@@ -445,17 +463,17 @@ set_process_priority(void)
                else
                        ++priority_done;
        }
-# else /* not RTP_SET */
+#  else        /* !RTP_SET follows */
        if (!priority_done) {
                if (rtprio(0, 120) < 0)
                        msyslog(LOG_ERR, "rtprio() error: %m");
                else
                        ++priority_done;
        }
-# endif /* not RTP_SET */
-#endif  /* HAVE_RTPRIO */
-#if defined(NTPD_PRIO) && NTPD_PRIO != 0
-# ifdef HAVE_ATT_NICE
+#  endif       /* !RTP_SET */
+# endif        /* HAVE_RTPRIO */
+# if defined(NTPD_PRIO) && NTPD_PRIO != 0
+#  ifdef HAVE_ATT_NICE
        if (!priority_done) {
                errno = 0;
                if (-1 == nice (NTPD_PRIO) && errno != 0)
@@ -463,25 +481,27 @@ set_process_priority(void)
                else
                        ++priority_done;
        }
-# endif /* HAVE_ATT_NICE */
-# ifdef HAVE_BSD_NICE
+#  endif       /* HAVE_ATT_NICE */
+#  ifdef HAVE_BSD_NICE
        if (!priority_done) {
                if (-1 == setpriority(PRIO_PROCESS, 0, NTPD_PRIO))
                        msyslog(LOG_ERR, "setpriority() error: %m");
                else
                        ++priority_done;
        }
-# endif /* HAVE_BSD_NICE */
-#endif /* NTPD_PRIO && NTPD_PRIO != 0 */
+#  endif       /* HAVE_BSD_NICE */
+# endif        /* NTPD_PRIO && NTPD_PRIO != 0 */
        if (!priority_done)
                msyslog(LOG_ERR, "set_process_priority: No way found to improve our priority");
 }
+#endif /* !SIM */
 
 
 /*
  * Main program.  Initialize us, disconnect us from the tty if necessary,
  * and loop waiting for I/O and/or timer expiries.
  */
+#ifndef SIM
 int
 ntpdmain(
        int argc,
@@ -490,46 +510,70 @@ ntpdmain(
 {
        l_fp now;
        struct recvbuf *rbuf;
-#ifdef _AIX                    /* HMS: ifdef SIGDANGER? */
+# ifdef HAVE_UMASK
+       mode_t  uv;
+# endif
+# if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
+       uid_t   uid;
+# endif
+# if defined(HAVE_WORKING_FORK)
+       long    wait_sync = 0;
+       int     s;
+       int     pipe_fds[2];
+       int     rc;
+       int     exit_code;
+#  ifdef F_CLOSEM
+       int     f_closem_errno;
+       int     first_to_close;
+#  else                /* !F_CLOSEM follows */
+       int     max_fd;
+#  endif       /* !F_CLOSEM */
+#  ifdef _AIX
        struct sigaction sa;
-#endif
+#  endif
+#  if !defined(HAVE_SETSID) && !defined (HAVE_SETPGID) && defined(TIOCNOTTY)
+       int     fid;
+#  endif
+# endif        /* HAVE_WORKING_FORK*/
+# ifdef SCO5_CLOCK
+       int     fd;
+       int     zero;
+# endif
+# if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE)
+#  ifdef HAVE_SETRLIMIT
+       struct rlimit rl;
+#  endif
+# endif
 
        progname = argv[0];
        initializing = 1;               /* mark that we are initializing */
        process_commandline_opts(&argc, &argv);
        init_logging(progname, 1);      /* Open the log file */
 
-#ifdef HAVE_UMASK
-       {
-               mode_t uv;
-
-               uv = umask(0);
-               if(uv)
-                       (void) umask(uv);
-               else
-                       (void) umask(022);
-       }
-#endif
-
-#if defined(HAVE_GETUID) && !defined(MPE) /* MPE lacks the concept of root */
-       {
-               uid_t uid;
+# ifdef HAVE_UMASK
+       uv = umask(0);
+       if (uv)
+               umask(uv);
+       else
+               umask(022);
+# endif
 
-               uid = getuid();
-               if (uid && !HAVE_OPT( SAVECONFIGQUIT )) {
-                       msyslog(LOG_ERR, "ntpd: must be run as root, not uid %ld", (long)uid);
-                       printf("must be run as root, not uid %ld\n", (long)uid);
-                       exit(1);
-               }
+       /* MPE lacks the concept of root */
+# if defined(HAVE_GETUID) && !defined(MPE)
+       uid = getuid();
+       if (uid && !HAVE_OPT( SAVECONFIGQUIT )) {
+               msyslog(LOG_ERR,
+                       "must be run as root, not uid %d", (int)uid);
+               printf("%s must be run as root, not uid %d\n",
+                      progname, (int)uid);
+               exit(1);
        }
-#endif
-
-       /* getstartup(argc, argv); / * startup configuration, may set debug */
+# endif
 
-#ifdef DEBUG
+# ifdef DEBUG
        debug = DESC(DEBUG_LEVEL).optOccCt;
        DPRINTF(1, ("%s\n", Version));
-#endif
+# endif
 
        /* honor -l/--logfile option to log to a file */
        setup_logfile();
@@ -537,15 +581,15 @@ ntpdmain(
 /*
  * Enable the Multi-Media Timer for Windows?
  */
-#ifdef SYS_WINNT
+# ifdef SYS_WINNT
        if (HAVE_OPT( MODIFYMMTIMER ))
                set_mm_timer(MM_TIMER_HIRES);
-#endif
+# endif
 
        if (HAVE_OPT( NOFORK ) || HAVE_OPT( QUIT )
-#ifdef DEBUG
+# ifdef DEBUG
            || debug
-#endif
+# endif
            || HAVE_OPT( SAVECONFIGQUIT ))
                nofork = 1;
 
@@ -573,21 +617,43 @@ ntpdmain(
        if (HAVE_OPT( NICE ))
                priority_done = 0;
 
-#if defined(HAVE_SCHED_SETSCHEDULER)
+# ifdef HAVE_SCHED_SETSCHEDULER
        if (HAVE_OPT( PRIORITY )) {
                config_priority = OPT_VALUE_PRIORITY;
                config_priority_override = 1;
                priority_done = 0;
        }
-#endif
+# endif
+
+# ifdef HAVE_WORKING_FORK
+       do {                                    /* 'loop' once */
+               if (!HAVE_OPT( WAIT_SYNC ))
+                       break;
+/* should be   wait_sync = OPT_VALUE_WAIT_SYNC;  after Autogen 5.10 fixed */
+               wait_sync = DESC(WAIT_SYNC).optArg.argInt;
+               if (wait_sync <= 0) {
+                       wait_sync = 0;
+                       break;
+               }
+               /* -w requires a fork() even with debug > 0 */
+               nofork = 0;
+               if (pipe(pipe_fds)) {
+                       exit_code = (errno) ? errno : -1;
+                       msyslog(LOG_ERR,
+                               "Pipe creation failed for --wait-sync: %m");
+                       exit(exit_code);
+               }
+               waitsync_fd_to_close = pipe_fds[1];
+       } while (0);                            /* 'loop' once */
+# endif        /* HAVE_WORKING_FORK */
 
-#ifdef SYS_WINNT
+# ifdef SYS_WINNT
        /*
         * Start interpolation thread, must occur before first
         * get_systime()
         */
        init_winnt_time();
-#endif
+# endif
        /*
         * Initialize random generator and public key pair
         */
@@ -595,8 +661,6 @@ ntpdmain(
 
        ntp_srandom((int)(now.l_i * now.l_uf));
 
-#if !defined(VMS)
-# ifndef NODETACH
        /*
         * Detach us from the terminal.  May need an #ifndef GIZMO.
         */
@@ -605,231 +669,219 @@ ntpdmain(
                /*
                 * Install trap handlers to log errors and assertion
                 * failures.  Default handlers print to stderr which 
-                * doesn't work if detached.
+                * doesn't work if detached or running as a windows
+                * service.
                 */
                isc_assertion_setcallback(assertion_failed);
                isc_error_setfatal(library_fatal_error);
                isc_error_setunexpected(library_unexpected_error);
 
-#  ifndef SYS_WINNT
-#   ifdef HAVE_DAEMON
-               daemon(0, 0);
-#   else /* not HAVE_DAEMON */
-               if (fork())     /* HMS: What about a -1? */
-                       exit(0);
-
+# ifdef HAVE_WORKING_FORK
+               rc = fork();
+               if (-1 == rc) {
+                       exit_code = (errno) ? errno : -1;
+                       msyslog(LOG_ERR, "fork: %m");
+                       exit(exit_code);
+               }
+               if (rc > 0) {   
+                       /* parent */
+                       exit_code = wait_child_sync_if(pipe_fds[0],
+                                                      wait_sync);
+                       exit(exit_code);
+               }
+               
+               /*
+                * child/daemon 
+                * close all open files excepting waitsync_fd_to_close.
+                */
+               if (syslog_file != NULL) {
+                       fclose(syslog_file);
+                       syslog_file = NULL;
+                       /* no msyslog() until after init_logging() */
+               }
+#  ifdef F_CLOSEM
+               /*
+                * From 'Writing Reliable AIX Daemons,' SG24-4946-00,
+                * by Eric Agar (saves us from doing 32767 system
+                * calls)
+                */
+               first_to_close = (-1 == waitsync_fd_to_close)
+                                    ? 0
+                                    : waitsync_fd_to_close + 1;
+               rc = fcntl(first_to_close, F_CLOSEM, 0);
+               f_closem_errno = (-1 == rc) ? errno : 0;
+               if (first_to_close != 0)
+                       for (s = 0; s < waitsync_fd_to_close; s++)
+                               close(s);
+#  else                /* !F_CLOSEM follows */
+#   if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
+               max_fd = sysconf(_SC_OPEN_MAX);
+#   else
+               max_fd = getdtablesize();
+#   endif
+               for (s = 0; s < max_fd; s++)
+                       if (s != waitsync_fd_to_close)
+                               close(s);
+#  endif       /* !F_CLOSEM */
+               open("/", 0);
+               dup2(0, 1);
+               dup2(0, 2);
+
+               init_logging(progname, 0);
+               /* we lost our logfile (if any) daemonizing */
+               setup_logfile();
+
+#  ifdef F_CLOSEM      /* msyslog() once again possible */
+               if (f_closem_errno != 0)
+                       msyslog(LOG_ERR, 
+                               "ntpd: failed to close open files(): %s",
+                               strerror(f_closem_errno));
+#  endif
+#  ifdef SYS_DOMAINOS
                {
-#if !defined(F_CLOSEM)
-                       u_long s;
-                       int max_fd;
-#endif /* !FCLOSEM */
-                       if (syslog_file != NULL) {
-                               fclose(syslog_file);
-                               syslog_file = NULL;
-                       }
-#if defined(F_CLOSEM)
-                       /*
-                        * From 'Writing Reliable AIX Daemons,' SG24-4946-00,
-                        * by Eric Agar (saves us from doing 32767 system
-                        * calls)
-                        */
-                       if (fcntl(0, F_CLOSEM, 0) == -1)
-                           msyslog(LOG_ERR, "ntpd: failed to close open files(): %m");
-#else  /* not F_CLOSEM */
-
-# if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
-                       max_fd = sysconf(_SC_OPEN_MAX);
-# else /* HAVE_SYSCONF && _SC_OPEN_MAX */
-                       max_fd = getdtablesize();
-# endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
-                       for (s = 0; s < max_fd; s++)
-                               (void) close((int)s);
-#endif /* not F_CLOSEM */
-                       (void) open("/", 0);
-                       (void) dup2(0, 1);
-                       (void) dup2(0, 2);
-
-                       init_logging(progname, 0);
-                       /* we lost our logfile (if any) daemonizing */
-                       setup_logfile();
+                       uid_$t puid;
+                       status_$t st;
 
-#ifdef SYS_DOMAINOS
-                       {
-                               uid_$t puid;
-                               status_$t st;
-
-                               proc2_$who_am_i(&puid);
-                               proc2_$make_server(&puid, &st);
-                       }
-#endif /* SYS_DOMAINOS */
-#if defined(HAVE_SETPGID) || defined(HAVE_SETSID)
-# ifdef HAVE_SETSID
-                       if (setsid() == (pid_t)-1)
-                               msyslog(LOG_ERR, "ntpd: setsid(): %m");
-# else
-                       if (setpgid(0, 0) == -1)
-                               msyslog(LOG_ERR, "ntpd: setpgid(): %m");
-# endif
-#else /* HAVE_SETPGID || HAVE_SETSID */
-                       {
-# if defined(TIOCNOTTY)
-                               int fid;
-
-                               fid = open("/dev/tty", 2);
-                               if (fid >= 0)
-                               {
-                                       (void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);
-                                       (void) close(fid);
-                               }
-# endif /* defined(TIOCNOTTY) */
-# ifdef HAVE_SETPGRP_0
-                               (void) setpgrp();
-# else /* HAVE_SETPGRP_0 */
-                               (void) setpgrp(0, getpid());
-# endif /* HAVE_SETPGRP_0 */
-                       }
-#endif /* HAVE_SETPGID || HAVE_SETSID */
-#ifdef _AIX
-                       /* Don't get killed by low-on-memory signal. */
-                       sa.sa_handler = catch_danger;
-                       sigemptyset(&sa.sa_mask);
-                       sa.sa_flags = SA_RESTART;
-
-                       (void) sigaction(SIGDANGER, &sa, NULL);
-#endif /* _AIX */
+                       proc2_$who_am_i(&puid);
+                       proc2_$make_server(&puid, &st);
+               }
+#  endif       /* SYS_DOMAINOS */
+#  ifdef HAVE_SETSID
+               if (setsid() == (pid_t)-1)
+                       msyslog(LOG_ERR, "setsid(): %m");
+#  elif defined(HAVE_SETPGID)
+               if (setpgid(0, 0) == -1)
+                       msyslog(LOG_ERR, "setpgid(): %m");
+#  else                /* !HAVE_SETSID && !HAVE_SETPGID follows */
+#   ifdef TIOCNOTTY
+               fid = open("/dev/tty", 2);
+               if (fid >= 0) {
+                       ioctl(fid, (u_long)TIOCNOTTY, NULL);
+                       close(fid);
                }
-#   endif /* not HAVE_DAEMON */
-#  endif /* SYS_WINNT */
+#   endif      /* TIOCNOTTY */
+               ntp_setpgrp(0, getpid());
+#  endif       /* !HAVE_SETSID && !HAVE_SETPGID */
+#  ifdef _AIX                  /* HMS: ifdef SIGDANGER? */
+               /* Don't get killed by low-on-memory signal. */
+               sa.sa_handler = catch_danger;
+               sigemptyset(&sa.sa_mask);
+               sa.sa_flags = SA_RESTART;
+               sigaction(SIGDANGER, &sa, NULL);
+#  endif       /* _AIX */
+# endif                /* HAVE_WORKING_FORK */
        }
-# endif /* NODETACH */
-#endif /* VMS */
 
-#ifdef SCO5_CLOCK
+# ifdef SCO5_CLOCK
        /*
         * SCO OpenServer's system clock offers much more precise timekeeping
         * on the base CPU than the other CPUs (for multiprocessor systems),
         * so we must lock to the base CPU.
         */
-       {
-           int fd = open("/dev/at1", O_RDONLY);
-           if (fd >= 0) {
-               int zero = 0;
+       fd = open("/dev/at1", O_RDONLY);                
+       if (fd >= 0) {
+               zero = 0;
                if (ioctl(fd, ACPU_LOCK, &zero) < 0)
-                   msyslog(LOG_ERR, "cannot lock to base CPU: %m");
-               close( fd );
-           } /* else ...
-              *   If we can't open the device, this probably just isn't
-              *   a multiprocessor system, so we're A-OK.
-              */
+                       msyslog(LOG_ERR, "cannot lock to base CPU: %m");
+               close(fd);
        }
-#endif
+# endif
 
-#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE)
-# ifdef HAVE_SETRLIMIT
+# if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT) && defined(MCL_FUTURE)
+#  ifdef HAVE_SETRLIMIT
        /*
         * Set the stack limit to something smaller, so that we don't lock a lot
         * of unused stack memory.
         */
-       {
-           struct rlimit rl;
-
-           /* HMS: must make the rlim_cur amount configurable */
-           if (getrlimit(RLIMIT_STACK, &rl) != -1
-               && (rl.rlim_cur = 50 * 4096) < rl.rlim_max)
-           {
-                   if (setrlimit(RLIMIT_STACK, &rl) == -1)
-                   {
-                           msyslog(LOG_ERR,
-                               "Cannot adjust stack limit for mlockall: %m");
-                   }
-           }
-#  ifdef RLIMIT_MEMLOCK
-           /*
-            * The default RLIMIT_MEMLOCK is very low on Linux systems.
-            * Unless we increase this limit malloc calls are likely to
-            * fail if we drop root privlege.  To be useful the value
-            * has to be larger than the largest ntpd resident set size.
-            */
-           rl.rlim_cur = rl.rlim_max = 32*1024*1024;
-           if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1) {
+       /* HMS: must make the rlim_cur amount configurable */
+       if (getrlimit(RLIMIT_STACK, &rl) != -1
+           && (rl.rlim_cur = 50 * 4096) < rl.rlim_max
+           && setrlimit(RLIMIT_STACK, &rl) == -1)
+               msyslog(LOG_ERR,
+                       "Cannot adjust stack limit for mlockall: %m");
+#   ifdef RLIMIT_MEMLOCK
+       /*
+        * The default RLIMIT_MEMLOCK is very low on Linux systems.
+        * Unless we increase this limit malloc calls are likely to
+        * fail if we drop root privlege.  To be useful the value
+        * has to be larger than the largest ntpd resident set size.
+        */
+       rl.rlim_cur = rl.rlim_max = 32 * 1024 * 1024;
+       if (setrlimit(RLIMIT_MEMLOCK, &rl) == -1)
                msyslog(LOG_ERR, "Cannot set RLIMIT_MEMLOCK: %m");
-           }
-#  endif /* RLIMIT_MEMLOCK */
-       }
-# endif /* HAVE_SETRLIMIT */
+#   endif      /* RLIMIT_MEMLOCK */
+#  endif       /* HAVE_SETRLIMIT */
        /*
         * lock the process into memory
         */
        if (mlockall(MCL_CURRENT|MCL_FUTURE) < 0)
                msyslog(LOG_ERR, "mlockall(): %m");
-#else /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
-# ifdef HAVE_PLOCK
-#  ifdef PROCLOCK
-#   ifdef _AIX
+# else /* !HAVE_MLOCKALL || !MCL_CURRENT || !MCL_FUTURE follows */
+#  ifdef HAVE_PLOCK
+#   ifdef PROCLOCK
+#    ifdef _AIX
        /*
         * set the stack limit for AIX for plock().
         * see get_aix_stack() for more info.
         */
-       if (ulimit(SET_STACKLIM, (get_aix_stack() - 8*4096)) < 0)
-       {
-               msyslog(LOG_ERR,"Cannot adjust stack limit for plock on AIX: %m");
-       }
-#   endif /* _AIX */
+       if (ulimit(SET_STACKLIM, (get_aix_stack() - 8 * 4096)) < 0)
+               msyslog(LOG_ERR,
+                       "Cannot adjust stack limit for plock: %m");
+#    endif     /* _AIX */
        /*
         * lock the process into memory
         */
        if (plock(PROCLOCK) < 0)
                msyslog(LOG_ERR, "plock(PROCLOCK): %m");
-#  else /* not PROCLOCK */
-#   ifdef TXTLOCK
+#   else       /* !PROCLOCK follows  */
+#    ifdef TXTLOCK
        /*
         * Lock text into ram
         */
        if (plock(TXTLOCK) < 0)
                msyslog(LOG_ERR, "plock(TXTLOCK) error: %m");
-#   else /* not TXTLOCK */
+#    else      /* !TXTLOCK follows */
        msyslog(LOG_ERR, "plock() - don't know what to lock!");
-#   endif /* not TXTLOCK */
-#  endif /* not PROCLOCK */
-# endif /* HAVE_PLOCK */
-#endif /* not (HAVE_MLOCKALL && MCL_CURRENT && MCL_FUTURE) */
+#    endif     /* !TXTLOCK */
+#   endif      /* !PROCLOCK */
+#  endif       /* HAVE_PLOCK */
+# endif        /* !HAVE_MLOCKALL || !MCL_CURRENT || !MCL_FUTURE */
 
        /*
         * Set up signals we pay attention to locally.
         */
-#ifdef SIGDIE1
-       (void) signal_no_reset(SIGDIE1, finish);
-#endif /* SIGDIE1 */
-#ifdef SIGDIE2
-       (void) signal_no_reset(SIGDIE2, finish);
-#endif /* SIGDIE2 */
-#ifdef SIGDIE3
-       (void) signal_no_reset(SIGDIE3, finish);
-#endif /* SIGDIE3 */
-#ifdef SIGDIE4
-       (void) signal_no_reset(SIGDIE4, finish);
-#endif /* SIGDIE4 */
-
-#ifdef SIGBUS
-       (void) signal_no_reset(SIGBUS, finish);
-#endif /* SIGBUS */
-
-#if !defined(SYS_WINNT) && !defined(VMS)
-# ifdef DEBUG
+# ifdef SIGDIE1
+       signal_no_reset(SIGDIE1, finish);
+# endif
+# ifdef SIGDIE2
+       signal_no_reset(SIGDIE2, finish);
+# endif
+# ifdef SIGDIE3
+       signal_no_reset(SIGDIE3, finish);
+# endif
+# ifdef SIGDIE4
+       signal_no_reset(SIGDIE4, finish);
+# endif
+# ifdef SIGBUS
+       signal_no_reset(SIGBUS, finish);
+# endif
+
+# if !defined(SYS_WINNT) && !defined(VMS)
+#  ifdef DEBUG
        (void) signal_no_reset(MOREDEBUGSIG, moredebug);
        (void) signal_no_reset(LESSDEBUGSIG, lessdebug);
-# else
+#  else
        (void) signal_no_reset(MOREDEBUGSIG, no_debug);
        (void) signal_no_reset(LESSDEBUGSIG, no_debug);
-# endif /* DEBUG */
-#endif /* !SYS_WINNT && !VMS */
+#  endif       /* DEBUG */
+# endif        /* !SYS_WINNT && !VMS */
 
        /*
         * Set up signals we should never pay attention to.
         */
-#if defined SIGPIPE
-       (void) signal_no_reset(SIGPIPE, SIG_IGN);
-#endif /* SIGPIPE */
+# ifdef SIGPIPE
+       signal_no_reset(SIGPIPE, SIG_IGN);
+# endif
 
        /*
         * Call the init_ routines to initialize the data structures.
@@ -845,9 +897,9 @@ ntpdmain(
        init_request();
        init_control();
        init_peer();
-#ifdef REFCLOCK
+# ifdef REFCLOCK
        init_refclock();
-#endif
+# endif
        set_process_priority();
        init_proto();           /* Call at high priority */
        init_io();
@@ -864,23 +916,23 @@ ntpdmain(
        loop_config(LOOP_DRIFTCOMP, old_drift);
        initializing = 0;
 
-#ifdef HAVE_DROPROOT
-       if( droproot ) {
+# ifdef HAVE_DROPROOT
+       if (droproot) {
                /* Drop super-user privileges and chroot now if the OS supports this */
 
-#ifdef HAVE_LINUX_CAPABILITIES
+#  ifdef HAVE_LINUX_CAPABILITIES
                /* set flag: keep privileges accross setuid() call (we only really need cap_sys_time): */
                if (prctl( PR_SET_KEEPCAPS, 1L, 0L, 0L, 0L ) == -1) {
                        msyslog( LOG_ERR, "prctl( PR_SET_KEEPCAPS, 1L ) failed: %m" );
                        exit(-1);
                }
-#else
+#  else
                /* we need a user to switch to */
                if (user == NULL) {
                        msyslog(LOG_ERR, "Need user name to drop root privileges (see -u flag!)" );
                        exit(-1);
                }
-#endif /* HAVE_LINUX_CAPABILITIES */
+#  endif       /* HAVE_LINUX_CAPABILITIES */
 
                if (user != NULL) {
                        if (isdigit((unsigned char)*user)) {
@@ -969,21 +1021,21 @@ getgroup:
                        exit (-1);
                }
 
-#ifndef HAVE_LINUX_CAPABILITIES
+#  ifndef HAVE_LINUX_CAPABILITIES
                /*
                 * for now assume that the privilege to bind to privileged ports
                 * is associated with running with uid 0 - should be refined on
                 * ports that allow binding to NTP_PORT with uid != 0
                 */
                disable_dynamic_updates |= (sw_uid != 0);  /* also notifies routing message listener */
-#endif
+#  endif
 
                if (disable_dynamic_updates && interface_interval) {
                        interface_interval = 0;
                        msyslog(LOG_INFO, "running in unprivileged mode disables dynamic interface tracking");
                }
 
-#ifdef HAVE_LINUX_CAPABILITIES
+#  ifdef HAVE_LINUX_CAPABILITIES
                do {
                        /*
                         *  We may be running under non-root uid now, but we still hold full root privileges!
@@ -1004,10 +1056,10 @@ getgroup:
                        }
                        cap_free( caps );
                } while(0);
-#endif /* HAVE_LINUX_CAPABILITIES */
+#  endif       /* HAVE_LINUX_CAPABILITIES */
 
-       }    /* if( droproot ) */
-#endif /* HAVE_DROPROOT */
+       }       /* if (droproot) */
+# endif /* HAVE_DROPROOT */
 
        /*
         * Use select() on all on all input fd's for unlimited
@@ -1024,23 +1076,20 @@ getgroup:
         * and - lacking a hardware reference clock - I have
         * yet to learn about anything else that is.
         */
-#if defined(HAVE_IO_COMPLETION_PORT)
+# ifdef HAVE_IO_COMPLETION_PORT
 
        for (;;) {
                GetReceivedBuffers();
-#else /* normal I/O */
+# else /* normal I/O */
 
        BLOCK_IO_AND_ALARM();
        was_alarmed = 0;
        for (;;)
        {
-# if !defined(HAVE_SIGNALED_IO)
-               extern fd_set activefds;
-               extern int maxactivefd;
-
+#  ifndef HAVE_SIGNALED_IO
                fd_set rdfdes;
                int nfound;
-# endif
+#  endif
 
                if (alarm_flag)         /* alarmed? */
                {
@@ -1053,9 +1102,9 @@ getgroup:
                        /*
                         * Nothing to do.  Wait for something.
                         */
-# ifndef HAVE_SIGNALED_IO
+#  ifndef HAVE_SIGNALED_IO
                        rdfdes = activefds;
-#  if defined(VMS) || defined(SYS_VXWORKS)
+#   if defined(VMS) || defined(SYS_VXWORKS)
                        /* make select() wake up after one second */
                        {
                                struct timeval t1;
@@ -1064,10 +1113,10 @@ getgroup:
                                nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
                                                (fd_set *)0, &t1);
                        }
-#  else
+#   else
                        nfound = select(maxactivefd+1, &rdfdes, (fd_set *)0,
                                        (fd_set *)0, (struct timeval *)0);
-#  endif /* VMS */
+#   endif /* VMS */
                        if (nfound > 0)
                        {
                                l_fp ts;
@@ -1078,14 +1127,14 @@ getgroup:
                        }
                        else if (nfound == -1 && errno != EINTR)
                                msyslog(LOG_ERR, "select() error: %m");
-#  ifdef DEBUG
+#   ifdef DEBUG
                        else if (debug > 5)
                                msyslog(LOG_DEBUG, "select(): nfound=%d, error: %m", nfound);
-#  endif /* DEBUG */
-# else /* HAVE_SIGNALED_IO */
+#   endif /* DEBUG */
+#  else /* HAVE_SIGNALED_IO */
 
                        wait_for_signal();
-# endif /* HAVE_SIGNALED_IO */
+#  endif /* HAVE_SIGNALED_IO */
                        if (alarm_flag)         /* alarmed? */
                        {
                                was_alarmed = 1;
@@ -1105,9 +1154,9 @@ getgroup:
                        BLOCK_IO_AND_ALARM();
                }
 
-#endif /* ! HAVE_IO_COMPLETION_PORT */
+# endif                /* !HAVE_IO_COMPLETION_PORT */
 
-#ifdef DEBUG_TIMING
+# ifdef DEBUG_TIMING
                {
                        l_fp pts;
                        l_fp tsa, tsb;
@@ -1115,7 +1164,7 @@ getgroup:
 
                        get_systime(&pts);
                        tsa = pts;
-#endif
+# endif
                        rbuf = get_full_recv_buffer();
                        while (rbuf != NULL)
                        {
@@ -1138,14 +1187,14 @@ getgroup:
                                 */
                                if (rbuf->receiver != NULL)     /* This should always be true */
                                {
-#ifdef DEBUG_TIMING
+# ifdef DEBUG_TIMING
                                        l_fp dts = pts;
 
                                        L_SUB(&dts, &rbuf->recv_time);
                                        DPRINTF(2, ("processing timestamp delta %s (with prec. fuzz)\n", lfptoa(&dts, 9)));
                                        collect_timing(rbuf, "buffer processing delay", 1, &dts);
                                        bufcount++;
-#endif
+# endif
                                        (rbuf->receiver)(rbuf);
                                } else {
                                        msyslog(LOG_ERR, "receive buffer corruption - receiver found to be NULL - ABORTING");
@@ -1156,7 +1205,7 @@ getgroup:
                                freerecvbuf(rbuf);
                                rbuf = get_full_recv_buffer();
                        }
-#ifdef DEBUG_TIMING
+# ifdef DEBUG_TIMING
                        get_systime(&tsb);
                        L_SUB(&tsb, &tsa);
                        if (bufcount) {
@@ -1164,13 +1213,13 @@ getgroup:
                                DPRINTF(2, ("processing time for %d buffers %s\n", bufcount, lfptoa(&tsb, 9)));
                        }
                }
-#endif
+# endif
 
                /*
                 * Go around again
                 */
 
-#ifdef HAVE_DNSREGISTRATION
+# ifdef HAVE_DNSREGISTRATION
                if (mdnsreg && (current_time - mdnsreg ) > 60 && mdnstries && sys_leap != LEAP_NOTINSYNC) {
                        mdnsreg = current_time;
                        msyslog(LOG_INFO, "Attemping to register mDNS");
@@ -1186,15 +1235,16 @@ getgroup:
                                mdnsreg = 0;
                        }
                }
-#endif /* HAVE_DNSREGISTRATION */
+# endif /* HAVE_DNSREGISTRATION */
 
        }
        UNBLOCK_IO_AND_ALARM();
        return 1;
 }
+#endif /* !SIM */
 
 
-#ifdef SIGDIE2
+#if !defined (SIM) && defined(SIGDIE2)
 /*
  * finish - exit gracefully
  */
@@ -1204,10 +1254,10 @@ finish(
        )
 {
        msyslog(LOG_NOTICE, "ntpd exiting on signal %d", sig);
-#ifdef HAVE_DNSREGISTRATION
+# ifdef HAVE_DNSREGISTRATION
        if (mdns != NULL)
                DNSServiceRefDeallocate(mdns);
-#endif
+# endif
        switch (sig) {
 # ifdef SIGBUS
        case SIGBUS:
@@ -1221,21 +1271,90 @@ finish(
                exit(0);
        }
 }
-#endif /* SIGDIE2 */
-
+#endif /* !SIM && SIGDIE2 */
 
-/* assertion_failed
- * Redirect trap messages from ISC libraries to syslog.
- * This code was cloned and simplified from BIND.
+#ifndef SIM
+/*
+ * wait_child_sync_if - implements parent side of -w/--wait-sync
  */
+# ifdef HAVE_WORKING_FORK
+static int
+wait_child_sync_if(
+       int     pipe_read_fd,
+       long    wait_sync
+       )
+{
+       int     rc;
+       int     exit_code;
+       time_t  wait_end_time;
+       time_t  cur_time;
+       time_t  wait_rem;
+       fd_set  readset;
+       struct timeval wtimeout;
+
+       if (0 == wait_sync) 
+               return 0;
+
+       /* waitsync_fd_to_close used solely by child */
+       close(waitsync_fd_to_close);
+       wait_end_time = time(NULL) + wait_sync;
+       do {
+               cur_time = time(NULL);
+               wait_rem = (wait_end_time > cur_time)
+                               ? (wait_end_time - cur_time)
+                               : 0;
+               wtimeout.tv_sec = wait_rem;
+               wtimeout.tv_usec = 0;
+               FD_ZERO(&readset);
+               FD_SET(pipe_read_fd, &readset);
+               rc = select(pipe_read_fd + 1, &readset, NULL, NULL,
+                           &wtimeout);
+               if (-1 == rc) {
+                       if (EINTR == errno)
+                               continue;
+                       exit_code = (errno) ? errno : -1;
+                       msyslog(LOG_ERR,
+                               "--wait-sync select failed: %m");
+                       return exit_code;
+               }
+               if (0 == rc) {
+                       /*
+                        * select() indicated a timeout, but in case
+                        * its timeouts are affected by a step of the
+                        * system clock, select() again with a zero 
+                        * timeout to confirm.
+                        */
+                       FD_ZERO(&readset);
+                       FD_SET(pipe_read_fd, &readset);
+                       wtimeout.tv_sec = 0;
+                       wtimeout.tv_usec = 0;
+                       rc = select(pipe_read_fd + 1, &readset, NULL,
+                                   NULL, &wtimeout);
+                       if (0 == rc)    /* select() timeout */
+                               break;
+                       else            /* readable */
+                               return 0;
+               } else                  /* readable */
+                       return 0;
+       } while (wait_rem > 0);
+
+       fprintf(stderr, "%s: -w/--wait-sync %ld timed out.\n",
+               progname, wait_sync);
+       return ETIMEDOUT;
+}
+# endif        /* HAVE_WORKING_FORK */
+
 
 /*
- * assertion_failed - Handle assertion failures.
+ * assertion_failed - Redirect assertion failures to msyslog().
  */
-
 static void
-assertion_failed(const char *file, int line, isc_assertiontype_t type,
-                 const char *cond)
+assertion_failed(
+       const char *file,
+       int line,
+       isc_assertiontype_t type,
+       const char *cond
+       )
 {
        isc_assertion_setcallback(NULL);    /* Avoid recursion */
 
@@ -1246,13 +1365,17 @@ assertion_failed(const char *file, int line, isc_assertiontype_t type,
        abort();
 }
 
+
 /*
  * library_fatal_error - Handle fatal errors from our libraries.
  */
-
 static void
-library_fatal_error(const char *file, int line, const char *format,
-                    va_list args)
+library_fatal_error(
+       const char *file,
+       int line,
+       const char *format,
+       va_list args
+       )
 {
        char errbuf[256];
 
@@ -1266,14 +1389,19 @@ library_fatal_error(const char *file, int line, const char *format,
        abort();
 }
 
+
 /*
  * library_unexpected_error - Handle non fatal errors from our libraries.
  */
-#define MAX_UNEXPECTED_ERRORS 100
+# define MAX_UNEXPECTED_ERRORS 100
 int unexpected_error_cnt = 0;
 static void
-library_unexpected_error(const char *file, int line, const char *format,
-                         va_list args)
+library_unexpected_error(
+       const char *file,
+       int line,
+       const char *format,
+       va_list args
+       )
 {
        char errbuf[256];
 
@@ -1290,10 +1418,11 @@ library_unexpected_error(const char *file, int line, const char *format,
        }
 
 }
+#endif /* !SIM */
 
+#if !defined(SIM) && !defined(SYS_WINNT)
+# ifdef DEBUG
 
-#ifdef DEBUG
-#ifndef SYS_WINNT
 /*
  * moredebug - increase debugging verbosity
  */
@@ -1312,6 +1441,7 @@ moredebug(
        errno = saved_errno;
 }
 
+
 /*
  * lessdebug - decrease debugging verbosity
  */
@@ -1329,9 +1459,10 @@ lessdebug(
        }
        errno = saved_errno;
 }
-#endif
-#else /* not DEBUG */
-#ifndef SYS_WINNT
+
+# else /* !DEBUG follows */
+
+
 /*
  * no_debug - We don't do the debug here.
  */
@@ -1345,5 +1476,5 @@ no_debug(
        msyslog(LOG_DEBUG, "ntpd not compiled for debugging (signal %d)", sig);
        errno = saved_errno;
 }
-#endif  /* not SYS_WINNT */
-#endif /* not DEBUG */
+# endif        /* !DEBUG */
+#endif /* !SIM && !SYS_WINNT */
index 586a33e055dcf0ed6163234f6b58ca90b91b9d16..80ec5159b1bbf3c1daa4cfe4c5f463b05735dc09 100644 (file)
@@ -240,6 +240,7 @@ flag = {
 flag = {
     name      = nofork;
     value     = n;
+    flags-cant = wait-sync;
     descrip   = "Do not fork";
     doc = <<-  _EndOfDoc_
        _EndOfDoc_;
@@ -288,12 +289,15 @@ flag = {
 flag = {
     name      = quit;
     value     = q;
+    flags-cant = saveconfigquit;
+    flags-cant = wait-sync;
     descrip   = "Set the time and quit";
     doc = <<-  _EndOfDoc_
        ntpd
-       will exit just after the first time the clock is set. This behavior mimics that of the
+       will not daemonize and will exit after the clock is first
+       synchronized.  This behavior mimics that of the
        ntpdate
-       program, which is to be retired.
+       program, which will soon be replaced with a shell script.
        The
        -g
        and
@@ -317,6 +321,8 @@ flag = {
     ifdef     = SAVECONFIG;
     name      = saveconfigquit;
     arg-type  = string;
+    flags-cant = quit;
+    flags-cant = wait-sync;
     descrip   = "Save parsed configuration and quit";
     doc = <<-  _EndOfDoc_
        Cause ntpd to parse its startup configuration file and save an
@@ -407,6 +413,32 @@ flag = {
        _EndOfDoc_;
 };
 
+flag = {
+    ifdef     = HAVE_WORKING_FORK;
+    name      = wait-sync;
+    value     = w;
+    /* arg-type  = number; */ /* doesn't compile on Windows with Autogen 5.10 output, instead: */
+    arg-type  = string;
+    flag-code = <<- _EOF_
+       extern tOptProc optionNumericVal;
+       optionNumericVal(pOptions, pOptDesc);
+       _EOF_;
+    flags-cant = nofork;
+    flags-cant = quit;
+    flags-cant = saveconfigquit;
+    descrip   = "Seconds to wait for first clock sync";
+    doc = <<-  _EndOfDoc_
+       If greater than zero, alters ntpd behavior when forking to
+       daemonize.  Instead of exiting with status 0 immediately after
+       the fork, the parent waits up to the specified number of
+       seconds for the child to first synchronize the clock.  The exit
+       status is zero (success) if the clock was synchronized,
+       otherwise it is ETIMEDOUT.
+       This provides the option for a script starting ntpd to easily
+       wait for the first set of the clock before proceeding.
+       _EndOfDoc_;
+};
+
 flag = {
     name      = slew;
     value     = x;
index d4da614ac417491f38ef6983e4914077cffd651c..9f5b86e2d678f8d36b1e48dbfc8fd2687ae04a8a 100644 (file)
@@ -191,8 +191,10 @@ int
 netsnmp_daemonize(int quit_immediately, int stderr_log)
 {
     int i = 0;
+    int saved_errno;
+
     DEBUGMSGT(("daemonize","deamonizing...\n"));
-#if HAVE_FORK
+#ifdef HAVE_WORKING_FORK
     /*
      * Fork to return control to the invoking process and to
      * guarantee that we aren't a process group leader.
@@ -200,10 +202,11 @@ netsnmp_daemonize(int quit_immediately, int stderr_log)
     i = fork();
     if (i != 0) {
         /* Parent. */
+       saved_errno = errno;
         DEBUGMSGT(("daemonize","first fork returned %d.\n", i));
         if(i == -1) {
             snmp_log(LOG_ERR,"first fork failed (errno %d) in "
-                     "netsnmp_daemonize()\n", errno);
+                     "netsnmp_daemonize()\n", saved_errno);
             return -1;
         }
         if (quit_immediately) {
@@ -220,10 +223,11 @@ netsnmp_daemonize(int quit_immediately, int stderr_log)
          * Fork to let the process/session group leader exit.
          */
         if ((i = fork()) != 0) {
+           saved_errno = errno;
             DEBUGMSGT(("daemonize","second fork returned %d.\n", i));
             if(i == -1) {
                 snmp_log(LOG_ERR,"second fork failed (errno %d) in "
-                         "netsnmp_daemonize()\n", errno);
+                         "netsnmp_daemonize()\n", saved_errno);
             }
             /* Parent. */
             exit(0);