[git commit master] ntpd: add -S PROG option. This feature is crucial for CMOS/RTC syncronization

Denys Vlasenko vda.linux at googlemail.com
Wed Jan 6 11:27:47 UTC 2010


commit: http://git.busybox.net/busybox/commit/?id=ede737b7cfb2d86965ebde07004ede3d8c3f1ab8
branch: http://git.busybox.net/busybox/commit/?id=refs/heads/master

function                                             old     new   delta
run_script                                           112     278    +166
ntpd_main                                            779     825     +46
update_local_clock                                   824     858     +34
packed_usage                                       26518   26540     +22
ntp_init                                             366     371      +5
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 5/0 up/down: 273/0)             Total: 273 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 include/usage.h   |    3 +-
 networking/ntpd.c |   61 +++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/include/usage.h b/include/usage.h
index 8c5a2db..c5707d8 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -3226,7 +3226,7 @@
        "Address:    127.0.0.1\n"
 
 #define ntpd_trivial_usage \
-	"[-dnqwl] [-p PEER]..."
+	"[-dnqwl] [-S PROG] [-p PEER]..."
 #define ntpd_full_usage "\n\n" \
        "NTP client/server\n" \
      "\nOptions:" \
@@ -3238,6 +3238,7 @@
 /*   "\n	-N	Run at high priority" */ \
      "\n	-w	Do not set time (only query peers), implies -n" \
      "\n	-l	Run as server on port 123" \
+     "\n	-S PROG	Run PROG after stepping time, stratum change, and every 11 mins" \
      "\n	-p PEER	Obtain time from PEER (may be repeated)" \
 
 #define od_trivial_usage \
diff --git a/networking/ntpd.c b/networking/ntpd.c
index ab1c58c..8147454 100644
--- a/networking/ntpd.c
+++ b/networking/ntpd.c
@@ -194,7 +194,8 @@ enum {
 	/* Non-compat options: */
 	OPT_w = (1 << 4),
 	OPT_p = (1 << 5),
-	OPT_l = (1 << 6) * ENABLE_FEATURE_NTPD_SERVER,
+	OPT_S = (1 << 6),
+	OPT_l = (1 << 7) * ENABLE_FEATURE_NTPD_SERVER,
 };
 
 struct globals {
@@ -205,6 +206,9 @@ struct globals {
 	double   reftime;
 	/* total dispersion to currently selected reference clock */
 	double   rootdisp;
+
+	double   last_script_run;
+	char     *script_name;
 	llist_t  *ntp_peers;
 #if ENABLE_FEATURE_NTPD_SERVER
 	int      listen_fd;
@@ -682,6 +686,38 @@ send_query_to_peer(peer_t *p)
 }
 
 
+static void run_script(const char *action)
+{
+	char *argv[3];
+	char *env1, *env2;
+
+	if (!G.script_name)
+		return;
+
+	argv[0] = (char*) G.script_name;
+	argv[1] = (char*) action;
+	argv[2] = NULL;
+
+	VERB1 bb_error_msg("executing '%s %s'", G.script_name, action);
+
+	env1 = xasprintf("stratum=%u", G.stratum);
+	putenv(env1);
+	env2 = xasprintf("freq_drift_ppm=%ld", G.kernel_freq_drift);
+	putenv(env2);
+	/* Other items of potential interest: selected peer,
+	 * rootdelay, reftime, rootdisp, refid, ntp_status, poll_exp,
+	 * last_update_offset, last_update_recv_time, discipline_jitter
+	 */
+
+	wait4pid(spawn(argv));
+	G.last_script_run = G.cur_time;
+
+	unsetenv("stratum");
+	unsetenv("freq_drift_ppm");
+	free(env1);
+	free(env2);
+}
+
 static NOINLINE void
 step_time(double offset)
 {
@@ -1140,6 +1176,9 @@ update_local_clock(peer_t *p)
 		G.polladj_count = 0;
 		G.poll_exp = MINPOLL;
 		G.stratum = MAXSTRAT;
+
+		run_script("step");
+
 		if (G.discipline_state == STATE_NSET) {
 			set_new_values(STATE_FREQ, /*offset:*/ 0, recv_time);
 			return 1; /* "ok to increase poll interval" */
@@ -1225,7 +1264,10 @@ update_local_clock(peer_t *p)
 			set_new_values(STATE_SYNC, offset, recv_time);
 			break;
 		}
-		G.stratum = p->lastpkt_stratum + 1;
+		if (G.stratum != p->lastpkt_stratum + 1) {
+			G.stratum = p->lastpkt_stratum + 1;
+			run_script("stratum");
+		}
 	}
 
 	G.reftime = G.cur_time;
@@ -1729,17 +1771,17 @@ static NOINLINE void ntp_init(char **argv)
 	G.stratum = MAXSTRAT;
 	if (BURSTPOLL != 0)
 		G.poll_exp = BURSTPOLL; /* speeds up initial sync */
-	G.reftime = G.last_update_recv_time = gettime1900d(); /* sets G.cur_time too */
+	G.last_script_run = G.reftime = G.last_update_recv_time = gettime1900d(); /* sets G.cur_time too */
 
 	/* Parse options */
 	peers = NULL;
 	opt_complementary = "dd:p::wn"; /* d: counter; p: list; -w implies -n */
 	opts = getopt32(argv,
 			"nqNx" /* compat */
-			"wp:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */
+			"wp:S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */
 			"d" /* compat */
 			"46aAbgL", /* compat, ignored */
-			&peers, &G.verbose);
+			&peers, &G.script_name, &G.verbose);
 	if (!(opts & (OPT_p|OPT_l)))
 		bb_show_usage();
 //	if (opts & OPT_x) /* disable stepping, only slew is allowed */
@@ -1854,8 +1896,15 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv)
 		VERB2 bb_error_msg("poll %us, sockets:%u", timeout, i);
 		nfds = poll(pfd, i, timeout * 1000);
 		gettime1900d(); /* sets G.cur_time */
-		if (nfds <= 0)
+		if (nfds <= 0) {
+			if (G.adjtimex_was_done
+			 && G.cur_time - G.last_script_run > 11*60
+			) {
+				/* Useful for updating battery-backed RTC and such */
+				run_script("periodic");
+			}
 			continue;
+		}
 
 		/* Process any received packets */
 		j = 0;
-- 
1.6.3.3



More information about the busybox-cvs mailing list