+* [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.
* 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 {
#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
*/
-#ifndef __ntp_proto_h
-#define __ntp_proto_h
+#ifndef NTP_PROTO_H
+#define NTP_PROTO_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#define NTP_MAXFREQ 500e-6
-#endif /* __ntp_proto_h */
+#endif /* NTP_PROTO_H */
#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 */
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
#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
test -z "@MAKE_CHECK_Y2K@" || ./@MAKE_CHECK_Y2K@
ntpd_SOURCES = \
- cmd_args.c \
ntp_config.c \
ntp_data_structures.c \
ntp_io.c \
# libntpd_a_SOURCES do not use #ifdef SIM
libntpd_a_SOURCES = \
+ cmd_args.c \
jupiter.h \
ntp_control.c \
ntp_crypto.c \
#include "ntpd.h"
#include "ntp_stdlib.h"
+#include "ntp_config.h"
#include "ntp_cmdargs.h"
#include "ntpd-opts.h"
{
extern const char *config_file;
int errflg;
- tOptions *myOptions = &ntpdOptions;
/*
* Initialize, initialize
#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);
}
clock_max = 600;
kern_enable = 0;
}
+
if (HAVE_OPT( UPDATEINTERVAL )) {
long val = OPT_VALUE_UPDATEINTERVAL;
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 */
}
#include "ntp_data_structures.h"
+/* list of servers from command line for config_peers() */
+int cmdline_server_count;
+char ** cmdline_servers;
+
/*
* "logconfig" building blocks
*/
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);
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.
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)) {
* 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 */
}
* 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,
* 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))
curr_peer->peerkey,
(u_char *)"*");
}
- freeaddrinfo(res_bak);
+ freeaddrinfo(res);
}
curr_peer = next_node(curr_peer);
}
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);
clock_frequency = direct_freq(fp_offset);
- /* fall through to S_SPIK */
+ /* fall through to EVNT_SPIK */
/*
* In SPIK state we ignore succeeding outlyers until
* 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)));
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
* 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);
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;
#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"
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
* 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)
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)
* 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 */
+
}
/*
/*
* 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
*
#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)
/*
| 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)
/*
| 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
#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:
*/
#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,
* #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 */
* #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
/* 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 },
/* 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 },
/* 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 },
/* 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,
/* 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,
/* 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,
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
#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
+ 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,
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
};
}
#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: */
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>
#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
/*
* 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
*
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"
# 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
# undef UPDATEINTERVAL
# undef VAR
# undef DVAR
+# undef WAIT_SYNC
# undef SLEW
# undef USEPCC
# undef PCCFREQ
#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
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 */
/* * * * * *
*
#
# 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
* 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
@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
-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
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)
@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
@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
+@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
-.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
.\"
.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.
.TP
.BR \-n ", " \--nofork
Do not fork.
+This option must not appear in combination with any of the following options:
+wait-sync.
.sp
.TP
.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
.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
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.
# 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
*/
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.
#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(
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(
{
return ntpdmain(argc, argv);
}
-#endif /* SYS_WINNT */
-#endif /* NO_MAIN_ALLOWED */
-#endif /* SIM */
+#endif /* !SYS_WINNT */
+#endif /* !NO_MAIN_ALLOWED */
+#endif /* !SIM */
#ifdef _AIX
/*
/*
* 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)
: "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;
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;
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)
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,
{
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();
/*
* 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;
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
*/
ntp_srandom((int)(now.l_i * now.l_uf));
-#if !defined(VMS)
-# ifndef NODETACH
/*
* Detach us from the terminal. May need an #ifndef GIZMO.
*/
/*
* 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.
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();
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)) {
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!
}
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
* 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? */
{
/*
* 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;
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;
}
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;
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;
get_systime(&pts);
tsa = pts;
-#endif
+# endif
rbuf = get_full_recv_buffer();
while (rbuf != NULL)
{
*/
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");
freerecvbuf(rbuf);
rbuf = get_full_recv_buffer();
}
-#ifdef DEBUG_TIMING
+# ifdef DEBUG_TIMING
get_systime(&tsb);
L_SUB(&tsb, &tsa);
if (bufcount) {
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");
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
*/
)
{
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:
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 */
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];
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];
}
}
+#endif /* !SIM */
+#if !defined(SIM) && !defined(SYS_WINNT)
+# ifdef DEBUG
-#ifdef DEBUG
-#ifndef SYS_WINNT
/*
* moredebug - increase debugging verbosity
*/
errno = saved_errno;
}
+
/*
* lessdebug - decrease debugging verbosity
*/
}
errno = saved_errno;
}
-#endif
-#else /* not DEBUG */
-#ifndef SYS_WINNT
+
+# else /* !DEBUG follows */
+
+
/*
* no_debug - We don't do the debug here.
*/
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 */
flag = {
name = nofork;
value = n;
+ flags-cant = wait-sync;
descrip = "Do not fork";
doc = <<- _EndOfDoc_
_EndOfDoc_;
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
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
_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;
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.
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) {
* 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);