From: Dave Hart Date: Sat, 19 Dec 2009 03:29:38 +0000 (+0000) Subject: [Bug 1395] ease ntpdate elimination with ntpd -w/--wait-sync X-Git-Tag: NTP_4_2_7P40~2^2~2^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=04987e061ef45932d88719bbdb4c43006c7d93f6;p=thirdparty%2Fntp.git [Bug 1395] ease ntpdate elimination with ntpd -w/--wait-sync [Bug 1396] allow servers on ntpd command line like ntpdate bk: 4b2c48a2vyaDih9UpW3W_Q4k3yB-fQ --- diff --git a/ChangeLog b/ChangeLog index 2e96bac71..23d567a89 100644 --- 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. diff --git a/include/ntp_config.h b/include/ntp_config.h index 4a9be31a4..4cd99e787 100644 --- a/include/ntp_config.h +++ b/include/ntp_config.h @@ -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 @@ -71,6 +71,10 @@ #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 { diff --git a/include/ntp_machine.h b/include/ntp_machine.h index 73fd172a2..4852d9213 100644 --- a/include/ntp_machine.h +++ b/include/ntp_machine.h @@ -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 */ diff --git a/include/ntp_proto.h b/include/ntp_proto.h index e6e785533..1a5b03efb 100644 --- a/include/ntp_proto.h +++ b/include/ntp_proto.h @@ -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 @@ -7,4 +7,4 @@ #define NTP_MAXFREQ 500e-6 -#endif /* __ntp_proto_h */ +#endif /* NTP_PROTO_H */ diff --git a/include/ntpd.h b/include/ntpd.h index 14cf0add2..c6044d841 100644 --- a/include/ntpd.h +++ b/include/ntpd.h @@ -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 diff --git a/include/ntpsim.h b/include/ntpsim.h index dbbfea057..971c7f163 100644 --- a/include/ntpsim.h +++ b/include/ntpsim.h @@ -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 diff --git a/ntpd/Makefile.am b/ntpd/Makefile.am index 972c3006d..033d19e0f 100644 --- a/ntpd/Makefile.am +++ b/ntpd/Makefile.am @@ -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 \ diff --git a/ntpd/cmd_args.c b/ntpd/cmd_args.c index 1047b8b7f..6c6885ece 100644 --- a/ntpd/cmd_args.c +++ b/ntpd/cmd_args.c @@ -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 */ } diff --git a/ntpd/ntp_config.c b/ntpd/ntp_config.c index f6e53cdaf..0261e1b5d 100644 --- a/ntpd/ntp_config.c +++ b/ntpd/ntp_config.c @@ -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); } diff --git a/ntpd/ntp_loopfilter.c b/ntpd/ntp_loopfilter.c index 1846b552e..baf4efbf7 100644 --- a/ntpd/ntp_loopfilter.c +++ b/ntpd/ntp_loopfilter.c @@ -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; diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index db5e04d5c..b4d5364cb 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -17,9 +17,10 @@ #include #ifdef HAVE_LIBSCF_H #include +#endif +#ifdef HAVE_UNISTD_H #include -#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 */ + } /* diff --git a/ntpd/ntpd-opts.c b/ntpd/ntpd-opts.c index 0afebc2b1..bd3ac2b84 100644 --- a/ntpd/ntpd-opts.c +++ b/ntpd/ntpd-opts.c @@ -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 [ - [] | --[{=| }] ]...\n"; +USAGE: %s [ - [] | --[{=| }] ]... \\\n\ +\t\t[ ... ]\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 diff --git a/ntpd/ntpd-opts.def b/ntpd/ntpd-opts.def index 7266e1b2a..9f51e2e24 100644 --- a/ntpd/ntpd-opts.def +++ b/ntpd/ntpd-opts.def @@ -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 = "[ ... ]"; #include ntpdbase-opts.def diff --git a/ntpd/ntpd-opts.h b/ntpd/ntpd-opts.h index f90f75f1b..0410f5fb6 100644 --- a/ntpd/ntpd-opts.h +++ b/ntpd/ntpd-opts.h @@ -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 */ /* * * * * * * diff --git a/ntpd/ntpd-opts.texi b/ntpd/ntpd-opts.texi index 629ef4d96..2e0da335c 100644 --- a/ntpd/ntpd-opts.texi +++ b/ntpd/ntpd-opts.texi @@ -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 [ - [] | --[@{=| @}] ]... +ntpd - NTP daemon program - Ver. 4.2.5p247-RC +USAGE: ntpd [ - [] | --[@{=| @}] ]... \ + [ ... ] 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 [ - [] | --[@{=| @}] ]... -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 diff --git a/ntpd/ntpd.1 b/ntpd/ntpd.1 index 508ca9222..8acc5fd34 100644 --- a/ntpd/ntpd.1 +++ b/ntpd/ntpd.1 @@ -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 +[ ... ] .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. diff --git a/ntpd/ntpd.c b/ntpd/ntpd.c index 62e4f9805..06a943ae4 100644 --- a/ntpd/ntpd.c +++ b/ntpd/ntpd.c @@ -31,11 +31,9 @@ # include #endif #include -#if !defined(VMS) /*wjm*/ -# ifdef HAVE_SYS_PARAM_H -# include -# endif -#endif /* VMS */ +#ifdef HAVE_SYS_PARAM_H +# include +#endif #ifdef HAVE_SYS_SIGNAL_H # include #else @@ -135,6 +133,12 @@ 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 */ diff --git a/ntpd/ntpdbase-opts.def b/ntpd/ntpdbase-opts.def index 586a33e05..80ec5159b 100644 --- a/ntpd/ntpdbase-opts.def +++ b/ntpd/ntpdbase-opts.def @@ -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; diff --git a/ntpsnmpd/netsnmp_daemonize.c b/ntpsnmpd/netsnmp_daemonize.c index d4da614ac..9f5b86e2d 100644 --- a/ntpsnmpd/netsnmp_daemonize.c +++ b/ntpsnmpd/netsnmp_daemonize.c @@ -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);