System: ntp version 3.4
Patch #: 10
Priority: 

From:

Description:
In the Makefile, remove references to the readclock.c module.

New clockhopper supression code.

Fix minor problem in ntp.c to get sin_family set in the proper place.
Specify default file for drift value and more peer flag definitions to
reflect various stages of clock selection critera.

Add code to count number of peer switches and inhibited peer switches.  Clock
selection code has been updated to reflect 21 April 1989 draft of NTP spec.

Add code to save the value of the drift compensation register to a file every
hour.  Add additional configuration file directives which can specify the same
information as on the command line.

ntpdc now will display addional peer flags which indicate how far through
the clock selection process a peer was considered.


Repeat-By:

Fix:	From rn, say "| patch -p -N -d DIR", where DIR is your ntp source
	directory.  Outside of rn, say "cd DIR; patch -p -N <thisarticle".
	If you don't have the patch program, apply the following by hand,
	or get patch (version 2.0, latest patchlevel).

	After patching:
		make depend
		make
		make install

	If patch indicates that patchlevel is the wrong version, you may need
	to apply one or more previous patches, or the patch may already
	have been applied.  See the patchlevel.h file to find out what has or
	has not been applied.  In any event, don't continue with the patch.

	If you are missing previous patches they can be obtained from me:

	Louis A. Mamakos
	louie@trantor.umd.edu

	You can also get the patches via anonymous FTP from
	trantor.umd.edu.

Index: patchlevel.h
Prereq: 9
1c1
< #define PATCHLEVEL 9
---
> #define PATCHLEVEL 10

Index: Makefile
*** Makefile.old	Wed May  3 15:17:41 1989
--- Makefile	Wed May  3 15:17:44 1989
***************
*** 1,6 ****
! # $Source: /usr/users/louie/ntp/RCS/Makefile,v $ $Revision: 3.4.1.5 $ $Date: 89/04/10 15:54:19 $
  #
  # $Log:	Makefile,v $
  # Revision 3.4.1.5  89/04/10  15:54:19  louie
  # Add dependency for ntpd.o on ntp.h so things sorta work even without doing a
  # "make depend".  Trash "ci" rule.
--- 1,9 ----
! # $Source: /usr/users/louie/ntp/RCS/Makefile,v $ $Revision: 3.4.1.6 $ $Date: 89/05/03 15:08:06 $
  #
  # $Log:	Makefile,v $
+ # Revision 3.4.1.6  89/05/03  15:08:06  louie
+ # In the Makefile, remove references to the readclock.c module.
+ # 
  # Revision 3.4.1.5  89/04/10  15:54:19  louie
  # Add dependency for ntpd.o on ntp.h so things sorta work even without doing a
  # "make depend".  Trash "ci" rule.
***************
*** 106,121 ****
  # Source files
  #
  SRCS=	ntp.c ntpd.c ntpdc.c ntpsubs.c ntp_proto.c ntp_sock.c ntp_adjust.c
! NTPDSRC= ntpd.c ntpsubs.c ntp_proto.c ntp_sock.c ntp_adjust.c readclock.c
  
  # Object files
  #
  OBJS=	ntp.o ntpd.o ntpdc.o ntpsubs.o ntp_proto.o ntp_sock.o ntp_adjust.o
  NTPDOBJ= ntpd.o ntpsubs.o ntp_proto.o ntp_sock.o ntp_adjust.o
- #
- # if using REFCLOCK
- #
- #NTPDOBJ= ntpd.o ntpsubs.o ntp_proto.o ntp_sock.o ntp_adjust.o readclock.o
  
  DIST= README Makefile man ${SRCS} ${HDRS} ntp.conf test.c extract.pl stat.pl
  PROGS=	ntp ntpd ntpdc ntest
--- 109,120 ----
  # Source files
  #
  SRCS=	ntp.c ntpd.c ntpdc.c ntpsubs.c ntp_proto.c ntp_sock.c ntp_adjust.c
! NTPDSRC= ntpd.c ntpsubs.c ntp_proto.c ntp_sock.c ntp_adjust.c
  
  # Object files
  #
  OBJS=	ntp.o ntpd.o ntpdc.o ntpsubs.o ntp_proto.o ntp_sock.o ntp_adjust.o
  NTPDOBJ= ntpd.o ntpsubs.o ntp_proto.o ntp_sock.o ntp_adjust.o
  
  DIST= README Makefile man ${SRCS} ${HDRS} ntp.conf test.c extract.pl stat.pl
  PROGS=	ntp ntpd ntpdc ntest

Index: README
*** README.old	Wed May  3 15:17:55 1989
--- README	Wed May  3 15:17:58 1989
***************
*** 1,4 ****
! README for UNIX NTP release $Date: 89/04/08 10:35:44 $ $Revision: 3.4.1.4 $
  
  
  
--- 1,4 ----
! README for UNIX NTP release $Date: 89/05/03 15:08:58 $ $Revision: 3.4.1.5 $
  
  
  
***************
*** 48,53 ****
--- 48,68 ----
  	7) Fire up ntpd in /etc/rc.local
  
  History:
+ 5/3/89
+ 	The changes to the ntp_proto.c module for clockhopper suppression have
+ 	been tweaked once more, ever so slightly to conform with the 21 April
+ 	1989 draft of the NTP spec.  We won't switch peers if the current 
+ 	peer makes it into the final selection list, unless the first peer on
+ 	the selection list is of a higher stratum than the current peer.
+ 
+ 	The ntpd.c/hourly() function now saves the value of the drift
+ 	compensation register to a file (/etc/ntp.drift by default).  In fact,
+ 	the last 5 hourly samples are written to the file, as well as how
+ 	many hours the ntpd process has been running.  Ntpd will also attempt
+ 	to intialize the value of the drift compensation register from this
+ 	file when it is started up.  The hourly stats: log message has been
+ 	augmented to log additional information.
+ 
  4/8/89
  	Changes to the ntp_proto.c module to supress peer switching when the
  	dispersion between the newly selected peer and the currently selected

Index: ntp.c
*** ntp.c.old	Wed May  3 15:18:09 1989
--- ntp.c	Wed May  3 15:18:11 1989
***************
*** 1,9 ****
  #ifndef	lint
! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp.c,v $ $Revision: 3.4.1.4 $ $Date: 89/04/07 18:04:49 $";
  #endif	lint
  
  /*
   *  $Log:	ntp.c,v $
   * Revision 3.4.1.4  89/04/07  18:04:49  louie
   * Removed unused variables from ntp.c program.
   * 
--- 1,12 ----
  #ifndef	lint
! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp.c,v $ $Revision: 3.4.1.5 $ $Date: 89/05/03 15:09:53 $";
  #endif	lint
  
  /*
   *  $Log:	ntp.c,v $
+  * Revision 3.4.1.5  89/05/03  15:09:53  louie
+  * Fix minor problem in ntp.c to get sin_family set in the proper place.
+  * 
   * Revision 3.4.1.4  89/04/07  18:04:49  louie
   * Removed unused variables from ntp.c program.
   * 
***************
*** 147,152 ****
--- 150,156 ----
  	} else
  		dst.sin_port = sp->s_port;
  
+ 	dst.sin_family = AF_INET;
  	while ((n = getopt(argc, argv, "vsf")) != EOF) {
  		switch (n) {
  		case 'v':
***************
*** 165,172 ****
  
  		if (argv[host] == NULL)
  			continue;
- 		dst.sin_family = AF_INET;
- 		dst.sin_port = sp->s_port;
  
  		hp = NULL;
  		HostAddr = inet_addr(argv[host]);
--- 169,174 ----

Index: ntp.h
*** ntp.h.old	Wed May  3 15:18:22 1989
--- ntp.h	Wed May  3 15:18:26 1989
***************
*** 1,7 ****
! /* $Source: /usr/users/louie/ntp/RCS/ntp.h,v $ $Revision: 3.4.1.5 $ $Date: 89/04/10 15:55:42 $ */
  
  /*
   *  $Log:	ntp.h,v $
   * Revision 3.4.1.5  89/04/10  15:55:42  louie
   * Provide default value for number of bits/byte if not defined.  Compute the
   * Window shift mask inside of conditional code on XTAL so we get the correct
--- 1,11 ----
! /* $Source: /usr/users/louie/ntp/RCS/ntp.h,v $ $Revision: 3.4.1.6 $ $Date: 89/05/03 15:11:06 $ */
  
  /*
   *  $Log:	ntp.h,v $
+  * Revision 3.4.1.6  89/05/03  15:11:06  louie
+  * Specify default file for drift value and more peer flag definitions to
+  * reflect various stages of clock selection critera.
+  * 
   * Revision 3.4.1.5  89/04/10  15:55:42  louie
   * Provide default value for number of bits/byte if not defined.  Compute the
   * Window shift mask inside of conditional code on XTAL so we get the correct
***************
*** 108,113 ****
--- 112,120 ----
  #ifndef	NTPINITFILE
  #define	NTPINITFILE	"/etc/ntp.conf"
  #endif
+ #ifndef	NTPDRIFTCOMP
+ #define	NTPDRIFTCOMP	"/etc/ntp.drift"
+ #endif
  
  struct list {
  	struct ntp_peer *head;
***************
*** 286,291 ****
--- 293,300 ----
  	int	flags;			/* local flags */
  #define	PEER_FL_CONFIG		1
  #define	PEER_FL_AUTHENABLE	2
+ #define	PEER_FL_SANE		0x0100	/* sane peer */
+ #define	PEER_FL_CANDIDATE	0x0200	/* candidate peer */
  #define	PEER_FL_SYNC		0x1000	/* peer can bet sync'd to */
  #define	PEER_FL_BCAST		0x2000	/* broadcast peer */
  #define	PEER_FL_SELECTED	0x8000	/* actually used by query routine */

Index: ntp_proto.c
*** ntp_proto.c.old	Wed May  3 15:18:48 1989
--- ntp_proto.c	Wed May  3 15:18:56 1989
***************
*** 1,5 ****
  #ifndef	lint
! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp_proto.c,v $ $Revision: 3.4.1.8 $ $Date: 89/04/10 15:57:59 $";
  #endif
  
  /*
--- 1,5 ----
  #ifndef	lint
! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntp_proto.c,v $ $Revision: 3.4.1.9 $ $Date: 89/05/03 15:13:25 $";
  #endif
  
  /*
***************
*** 11,16 ****
--- 11,20 ----
  
  /*
   * $Log:	ntp_proto.c,v $
+  * Revision 3.4.1.9  89/05/03  15:13:25  louie
+  * Add code to count number of peer switches and inhibited peer switches.  Clock
+  * selection code has been updated to reflect 21 April 1989 draft of NTP spec.
+  * 
   * Revision 3.4.1.8  89/04/10  15:57:59  louie
   * New -l option for ntpd to enable logging for clock adjust messages.  Changed
   * our idea of a bogus packet in the packet procedure to include a packet received
***************
*** 118,123 ****
--- 122,129 ----
  
  #include "ntp.h"
  
+ int peer_switches, peer_sw_inhibited;
+ 
  struct ntp_peer dummy_peer;
  extern double WayTooBig;
  extern unsigned long clock_watchdog;
***************
*** 822,827 ****
--- 828,834 ----
  	struct sel_lst {
  		struct ntp_peer *peer;
  		double distance;
+ 		double precision;
  	} sel_lst[X_NTP_CANDIDATES];
  	int i, j, stratums, candidates;
  	int sanity_check();
***************
*** 834,843 ****
--- 841,852 ----
  		/*
  		 * Check if this is a candidate for "sys.peer" 
  		 */
+ 		peer->flags &= ~(PEER_FL_SANE | PEER_FL_CANDIDATE);
  		if(sanity_check(peer)) {
  			sel_lst[candidates].peer = peer;
  			sel_lst[candidates].distance = peer->estdisp + 
  				s_fixed_to_double(&peer->dispersion);
+ 			peer->flags |= PEER_FL_SANE;
  			candidates++;
  		}
  		peer = peer->next;
***************
*** 944,949 ****
--- 953,959 ----
  	}
  	while (candidates > 1) {
  		double maxdispersion = 0.0, dispersion, weight;
+ 		double min_precision_thres = 10e20, precision_thres;
  		short worst = 0;	/* shut up GNU CC about unused var */
  #ifdef	DEBUG
  		if (debug > 3)
***************
*** 954,959 ****
--- 964,970 ----
  			   rest of the candidates */
  			dispersion = 0.0;
  			weight = 1.0;
+ 			sel_lst[i].peer->flags |= PEER_FL_CANDIDATE;
  			for (j = 0; j < candidates; j++) {
  				dtmp = sel_lst[j].peer->estoffset -
  					sel_lst[i].peer->estoffset;
***************
*** 965,983 ****
  			/* since we just happen to have this double floating
  			   around.. */
  			sel_lst[i].distance = dispersion;
  			if (dispersion >= maxdispersion) {
  				maxdispersion = dispersion;
  				worst = i;
  			}
  #ifdef	DEBUG
  			if (debug > 4) {
! 				printf(" peer %s => disp %f\n",
  				       ntoa(sel_lst[i].peer->src.sin_addr),
! 				       dispersion);
  			}
  #endif
  		}
  #ifdef	DEBUG
  		if (debug > 4)
  			printf(" peer %s => TOSS\n",
  			       ntoa(sel_lst[worst].peer->src.sin_addr));
--- 976,1018 ----
  			/* since we just happen to have this double floating
  			   around.. */
  			sel_lst[i].distance = dispersion;
+ 			
+ 			precision_thres = NTP_MAXSKW + 1.0/(1<<-sys.precision);
+ 			if (peer->precision < 0 &&
+ 			    -peer->precision < sizeof(long)*NBBY)
+ 				precision_thres += 1.0/(1<<-peer->precision);
+ 
+ 			sel_lst[i].precision = precision_thres;
+ 
  			if (dispersion >= maxdispersion) {
  				maxdispersion = dispersion;
  				worst = i;
  			}
+ 			if (precision_thres < min_precision_thres) {
+ 				min_precision_thres = precision_thres;
+ 			}
  #ifdef	DEBUG
  			if (debug > 4) {
! 				printf(" peer %s => disp %f prec_th %f\n",
  				       ntoa(sel_lst[i].peer->src.sin_addr),
! 				       dispersion, precision_thres);
  			}
  #endif
  		}
+ 		/*
+ 		 *  Now check to see if the max dispersion is greater than
+ 		 *  the min dispersion limit.  If so, crank again, otherwise
+ 		 *  bail out.
+ 		 */
+ 		if (! (maxdispersion > min_precision_thres)) {
  #ifdef	DEBUG
+ 			if (debug > 4)
+ 				printf(" %d left valid\n", candidates);
+ #endif
+ 			break;
+ 		}
+ 			
+ #ifdef	DEBUG
  		if (debug > 4)
  			printf(" peer %s => TOSS\n",
  			       ntoa(sel_lst[worst].peer->src.sin_addr));
***************
*** 987,992 ****
--- 1022,1028 ----
  		 *  and interate until there is only one candidate peer left.
  		 */
  		if (worst != candidates - 1) {
+ 			sel_lst[worst].peer->flags &= ~PEER_FL_CANDIDATE;
  			for (i = worst, j = worst + 1; j < candidates; )
  				sel_lst[i++].peer = sel_lst[j++].peer;
  		}
***************
*** 997,1038 ****
  	if (debug > 3)
  		printf("select_clock: step6 %d candidates\n", candidates);
  #endif
- 	if (sys.peer != NULL && sys.peer != sel_lst[0].peer) {
- 		/* 
- 		 * Potential peer is different that current one; don't switch
- 		 * to new peer unless the offset is suitably "large".
- 		 */
- 		if (sys.peer->stratum == sel_lst[0].peer->stratum) {
- 			double threshold ;
  
! 			threshold = NTP_MAXSKW +
! 				1.0/(unsigned long)(1L << -sys.precision);
! 
! 			/* make sure we don't try to divide by zero */
! 			if (-sel_lst[0].peer->precision < sizeof(long)*NBBY)
! 				threshold += 1.0/(unsigned long)
! 					(1L << -sel_lst[0].peer->precision);
! 
! 			if (sel_lst[0].peer->estoffset < threshold) {
! #ifdef	DEBUG
! 				if (debug > 2)
! 					printf("clock: inhibit peer switch\n");
! #endif
  				return;
  			}
! 		}	     
  	}
  
! #ifdef	DEBUG
! 	if ((debug > 2) || (sys.peer != sel_lst[0].peer))
! 		printf("clock: select peer %s stratum %d\n",
! 		       ntoa(sel_lst[0].peer->src.sin_addr),
! 		       sel_lst[0].peer->stratum);
! #endif
! 
! 	/* 
! 	 *  We've finally selected our best bet for a clock to synchronize to.
  	 */
  	if (sys.peer != sel_lst[0].peer) {
  		if (sys.peer != NULL)
  			syslog(LOG_INFO, "clock: select peer %s stratum %d was %s stratum %d",
--- 1033,1072 ----
  	if (debug > 3)
  		printf("select_clock: step6 %d candidates\n", candidates);
  #endif
  
! 	/*
! 	 *  Check to see if current peer is on the list of candidate peers.  If
! 	 *  don't change sys.peer.  Note that if the first selected clock is
! 	 *  at a higher stratum, don't even bother; we're going to want to
! 	 *  switch to it.
! 	 */
! 	if (sys.peer != NULL && 
! 	    (sys.peer->stratum > sel_lst[0].peer->stratum)) {
! 		for (i = 0; i < candidates; i++) {
! 			if (sys.peer == sel_lst[i].peer) {
! 				/*
! 				 * The clock we're currently synchronized to
! 				 * is among the candidate peers.  Don't switch.
! 				 */
! 				if (i != 0) {
! 					/*
! 					 *  Count instances where the best 
! 					 *  candidate is different from the
! 					 *  current clock, thus inhibiting
! 					 *  clockhopping.
! 					 */
! 					peer_sw_inhibited++;
! 				}
  				return;
  			}
! 		}
  	}
  
! 	/*
! 	 *  The currently selected peer (if any) isn't on the candidate list.
! 	 *  Grab the first one and let it be.
  	 */
+ 
  	if (sys.peer != sel_lst[0].peer) {
  		if (sys.peer != NULL)
  			syslog(LOG_INFO, "clock: select peer %s stratum %d was %s stratum %d",
***************
*** 1043,1053 ****
  			syslog(LOG_INFO, "clock: select peer %s stratum %d was UNSYNCED",
  			       ntoa(sel_lst[0].peer->src.sin_addr),
  			       sel_lst[0].peer->stratum);
  	}
- 
- 
- 	/* finally, set new peer */
- 	sys.peer = sel_lst[0].peer;
  }
  
  int
--- 1077,1092 ----
  			syslog(LOG_INFO, "clock: select peer %s stratum %d was UNSYNCED",
  			       ntoa(sel_lst[0].peer->src.sin_addr),
  			       sel_lst[0].peer->stratum);
+ 		
+ #ifdef	DEBUG
+ 		if (debug > 2)
+ 			printf("clock: select peer %s stratum %d of %d cand\n",
+ 			       ntoa(sel_lst[0].peer->src.sin_addr),
+ 			       sel_lst[0].peer->stratum, candidates);
+ #endif
+ 		sys.peer = sel_lst[0].peer;
+ 		peer_switches++;
  	}
  }
  
  int

Index: ntpd.c
*** ntpd.c.old	Wed May  3 15:19:23 1989
--- ntpd.c	Wed May  3 15:19:31 1989
***************
*** 1,9 ****
  #ifndef	lint
! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntpd.c,v $ $Revision: 3.4.1.7 $ $Date: 89/04/10 15:58:45 $";
  #endif	lint
  
  /*
   *  $Log:	ntpd.c,v $
   * Revision 3.4.1.7  89/04/10  15:58:45  louie
   * Add -l option to enable logging of clock adjust messages.
   * 
--- 1,14 ----
  #ifndef	lint
! static char *rcsid = "$Source: /usr/users/louie/ntp/RCS/ntpd.c,v $ $Revision: 3.4.1.8 $ $Date: 89/05/03 15:16:17 $";
  #endif	lint
  
  /*
   *  $Log:	ntpd.c,v $
+  * Revision 3.4.1.8  89/05/03  15:16:17  louie
+  * Add code to save the value of the drift compensation register to a file every
+  * hour.  Add additional configuration file directives which can specify the same
+  * information as on the command line.
+  * 
   * Revision 3.4.1.7  89/04/10  15:58:45  louie
   * Add -l option to enable logging of clock adjust messages.
   * 
***************
*** 115,120 ****
--- 120,127 ----
  char *prog_name;
  
  char *conf = NTPINITFILE;
+ char *driftcomp_file = NTPDRIFTCOMP;
+ static int drift_fd = -1;
  
  #ifdef	DEBUG
  int debug = 0;
***************
*** 275,286 ****
  		setlogmask(LOG_UPTO(LOG_INFO));
  #endif	/* LOG_DAEMON */
  
! 	syslog(LOG_NOTICE, "%s version $Revision: 3.4.1.7 $", prog_name);
  	syslog(LOG_NOTICE, "patchlevel %d", PATCHLEVEL);
  
  #ifdef	DEBUG
  	if (debug)
! 		printf("%s version $Revision: 3.4.1.7 $ patchlevel %d\n",
  		       prog_name, PATCHLEVEL);
  #endif
  	(void) setpriority(PRIO_PROCESS, 0, -10);
--- 282,293 ----
  		setlogmask(LOG_UPTO(LOG_INFO));
  #endif	/* LOG_DAEMON */
  
! 	syslog(LOG_NOTICE, "%s version $Revision: 3.4.1.8 $", prog_name);
  	syslog(LOG_NOTICE, "patchlevel %d", PATCHLEVEL);
  
  #ifdef	DEBUG
  	if (debug)
! 		printf("%s version $Revision: 3.4.1.8 $ patchlevel %d\n",
  		       prog_name, PATCHLEVEL);
  #endif
  	(void) setpriority(PRIO_PROCESS, 0, -10);
***************
*** 312,317 ****
--- 319,331 ----
  	init_kern_vars();
  	init_logical_clock();
  
+ 	/*
+ 	 * Attempt to open for writing the file for storing the drift comp
+ 	 * register.  File must already exist for snapshots to be taken.
+ 	 */
+ 	if ((i = open(driftcomp_file, O_WRONLY|O_CREAT, 0644)) >= 0) {
+ 		drift_fd = i;
+ 	}
  	(void) gettimeofday(&tv, (struct timezone *) 0);
  	srand(tv.tv_sec);
  
***************
*** 627,646 ****
  	register struct ntp_peer *peer = peer_list.head, *next;
  #ifndef	XADJTIME2
  	extern void adj_host_clock();
- #endif
  
! #ifdef	REFCLOCK
! 	/*
! 	 *  I think that this is being done wrong.  The reference clock 
! 	 *  attached to this host should look like another peer.  Then the
! 	 *  normal clock selection stuff will select the "right" one.
! 	 */
! 	if (sys.stratum == 1)
! 		adj_from_source();
! 	else
! #endif	/* REFCLOCK */
! #ifndef	XADJTIME2
! 		adj_host_clock();
  #endif
  	/*
  	 * Count down sys.hold if necessary.
--- 641,648 ----
  	register struct ntp_peer *peer = peer_list.head, *next;
  #ifndef	XADJTIME2
  	extern void adj_host_clock();
  
! 	adj_host_clock();
  #endif
  	/*
  	 * Count down sys.hold if necessary.
***************
*** 720,725 ****
--- 722,729 ----
  	int i;
  	int debuglevel;
  	int stagger = 0;
+ 	double j;
+ 	extern double drift_comp;
  
  	bzero((char *) &sin, sizeof(sin));
  	fp = fopen(config, "r");
***************
*** 747,753 ****
  				} else
  					trusting = atoi(name);
  			}
! 		} else if (strcmp(name, "debuglevel") == 0) {
  			if (fscanf(fp, "%d", &debuglevel) != 1)
  				error = TRUE;
  #ifdef	DEBUG
--- 751,785 ----
  				} else
  					trusting = atoi(name);
  			}
! 		} else if (strcmp(name, "logclock") == 0) {
! 			if (fscanf(fp, "%s", name) != 1)
! 				error = TRUE;
! 			else {
! 				if (*name == 'Y' || *name == 'y') {
! 					logstats = 1;
! 				} else if (*name == 'N' || *name == 'n') {
! 					logstats = 0;
! 				} else
! 					logstats = atoi(name);
! 			}
! 		} else if (strcmp(name, "driftfile") == 0) {
! 			if (fscanf(fp, "%s", name) != 1)
! 				error = TRUE;
! 			else {
! 				if (driftcomp_file = malloc(strlen(name)+1))
! 					strcpy(driftcomp_file, name);
! 			}
! 		} else if (strcmp(name, "waytoobig") == 0 ||
! 			   strcmp(name, "setthreshold") == 0) {
! 			if (fscanf(fp, "%s", name) != 1)
! 				error = TRUE;
! 			else {
! 				if (strcmp(name, "any") == 0)
! 					WayTooBig = 10e15;
! 				else
! 					WayTooBig = atof(name);
! 			}
! 		} else if (strncmp(name, "debuglevel", 5) == 0) {
  			if (fscanf(fp, "%d", &debuglevel) != 1)
  				error = TRUE;
  #ifdef	DEBUG
***************
*** 754,771 ****
  			else debug += debuglevel;
  #endif
  		} else if (strcmp(name, "stratum") == 0) {
! 			if (fscanf(fp, "%d", &stratum) != 1)
! 				error = TRUE;
! 			else sys.stratum = (u_char) stratum;
! 			if (sys.stratum == 1) {
! 				if (fscanf(fp, "%4s", ref_clock) != 1)
! 					error = TRUE;
! 				else {
! 					ref_clock[4] = 0;
! 					(void) strncpy((char *) &sys.refid,
! 						       ref_clock, 4);
! 				}
! 			}
  		} else if (strcmp(name, "precision") == 0) {
  			if (fscanf(fp, "%d", &precision) != 1)
  				error = TRUE;
--- 786,793 ----
  			else debug += debuglevel;
  #endif
  		} else if (strcmp(name, "stratum") == 0) {
! 			fprintf(stderr, "Obsolete command 'stratum'\n");
! 			error = TRUE;
  		} else if (strcmp(name, "precision") == 0) {
  			if (fscanf(fp, "%d", &precision) != 1)
  				error = TRUE;
***************
*** 775,780 ****
--- 797,813 ----
  			if (fscanf(fp, "%d", &i) != 1)
  				error = TRUE;
  			else tickadj = i;
+ 		} else if (strcmp(name, "settickadj") == 0) {
+ 			if (fscanf(fp, "%s", name) != 1)
+ 				error = TRUE;
+ 			else {
+ 				if (*name == 'Y' || *name == 'y') {
+ 					dotickadj = 1;
+ 				} else if (*name == 'N' || *name == 'n') {
+ 					dotickadj = 0;
+ 				} else
+ 					dotickadj = atoi(name);
+ 			}
  #endif
  #ifdef	NOSWAP
  		} else if (strcmp(name, "noswap") == 0) {
***************
*** 915,920 ****
--- 948,969 ----
  
  		exit(1);
  	}
+ 	/*
+ 	 *  Read saved drift compensation register value.
+ 	 */
+ 	if ((fp = fopen(driftcomp_file, "r")) != NULL) {
+ 		if (fscanf(fp, "%f", &j) == 1 && j > -1.0 && j < 1.0) {
+ 			drift_comp = j;
+ 			syslog(LOG_INFO,
+ 			       "Drift compensation value initialized to %f", j);
+ 		} else {
+ 			fprintf(stderr,
+ 				"init_ntp: bad drift compensation value\n");
+ 			syslog(LOG_ERR,
+ 			       "init_ntp: bad drift compensation value\n");
+ 		}
+ 		fclose(fp);
+ 	}
  }
  
  int kern_tickadj, kern_hz, kern_tick;
***************
*** 1168,1183 ****
  hourly() {
  	char buf[200];
  	register int p = 0;
  	extern double drift_comp, compliance;
  
! 	(void) sprintf(buf, "stats: dc %f comp %f", drift_comp, compliance);
  
  	if (sys.peer == NULL)
  		strcat(buf, " UNSYNC");
  	else {
  		p = strlen(buf);
! 		(void) sprintf(buf + p, " SYNC %s %d",
! 			ntoa(sys.peer->src.sin_addr), sys.peer->stratum);
  	}
  	syslog(LOG_INFO, buf);
  #ifdef	DEBUG
--- 1217,1239 ----
  hourly() {
  	char buf[200];
  	register int p = 0;
+ 	static double drifts[5] = { 0.0, 0.0, 0.0, 0.0, 0.0 };
+ 	static int drift_count = 0;
  	extern double drift_comp, compliance;
+ 	extern int peer_switches, peer_sw_inhibited;
  
! 	(void) sprintf(buf, "stats: dc %f comp %f peersw %d inh %d",
! 		       drift_comp, compliance, peer_switches,
! 		       peer_sw_inhibited);
  
  	if (sys.peer == NULL)
  		strcat(buf, " UNSYNC");
  	else {
  		p = strlen(buf);
! 		(void) sprintf(buf + p, " off %f SYNC %s %d",
! 			       sys.peer->estoffset,
! 			       ntoa(sys.peer->src.sin_addr),
! 			       sys.peer->stratum);
  	}
  	syslog(LOG_INFO, buf);
  #ifdef	DEBUG
***************
*** 1184,1189 ****
--- 1240,1269 ----
  	if (debug)
  		puts(buf);
  #endif
+ 	/*
+ 	 *  If the drift compensation snapshot file is open, then write
+ 	 *  the current value to it.  Since there's only one block in the
+ 	 *  file, and no one else is reading it, we'll just keep the file
+ 	 *  open and write to it.
+ 	 */
+ 	if (drift_fd >= 0) {
+ 		drifts[drift_count % 5] = drift_comp;
+ 		/* works out to be 70 bytes */
+ 		(void) sprintf(buf,
+ 		     "%+12.10f %+12.10f %+12.10f %+12.10f %+12.10f %4d\n",
+ 			       drifts[drift_count % 5],
+ 			       drifts[(drift_count+4) % 5],
+ 			       drifts[(drift_count+3) % 5],
+ 			       drifts[(drift_count+2) % 5],
+ 			       drifts[(drift_count+1) % 5],
+ 			       drift_count + 1);
+ 
+ 		(void) lseek(drift_fd, 0L, L_SET);
+ 		if (write(drift_fd, buf, strlen(buf)) < 0) {
+ 			syslog(LOG_ERR, "Error writing drift comp file: %m");
+ 		}
+ 		drift_count++;
+ 	}
  }
  
  #if	defined(DEBUG) && defined(SIGUSR1) && defined(SIGUSR2)

Index: ntpdc.c
*** ntpdc.c.old	Wed May  3 15:19:48 1989
--- ntpdc.c	Wed May  3 15:19:51 1989
***************
*** 1,9 ****
  #ifndef	lint
! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntpdc.c,v $ $Revision: 3.4.1.5 $ $Date: 89/04/08 10:38:06 $";
  #endif
  
  /*
   * $Log:	ntpdc.c,v $
   * Revision 3.4.1.5  89/04/08  10:38:06  louie
   * Minor cosmetic changes and removed dead debug code from ntpd.c
   * 
--- 1,13 ----
  #ifndef	lint
! static char *RCSid = "$Source: /usr/users/louie/ntp/RCS/ntpdc.c,v $ $Revision: 3.4.1.6 $ $Date: 89/05/03 15:17:27 $";
  #endif
  
  /*
   * $Log:	ntpdc.c,v $
+  * Revision 3.4.1.6  89/05/03  15:17:27  louie
+  * ntpdc now will display addional peer flags which indicate how far through
+  * the clock selection process a peer was considered.
+  * 
   * Revision 3.4.1.5  89/04/08  10:38:06  louie
   * Minor cosmetic changes and removed dead debug code from ntpd.c
   * 
***************
*** 287,292 ****
--- 291,297 ----
  	double offset[PEER_SHIFT], delay[PEER_SHIFT], dsp,del,off;
  	char c;
  	char *cvthname();
+ 	int flags;
  
  	sin.sin_addr.s_addr = n->net_address;
  	for (i = 0; i < PEER_SHIFT; i++) {
***************
*** 297,305 ****
  	del = (long) ntohl(n->estdelay);	/* leave in milliseconds */
  	off = (long) ntohl(n->estoffset);	/* leave in milliseconds */
  	c = ' ';
! 	if (ntohs(n->flags) & PEER_FL_CONFIG)
  		c = '-';		/* mark pre-configured */
! 	if (ntohs(n->flags) & PEER_FL_SELECTED)
  		c = '*';		/* mark peer selection */
  	sin.sin_addr.s_addr = n->net_address;
  	printf("%c%-15.15s ", c, cvthname(&sin));
--- 302,315 ----
  	del = (long) ntohl(n->estdelay);	/* leave in milliseconds */
  	off = (long) ntohl(n->estoffset);	/* leave in milliseconds */
  	c = ' ';
! 	flags = ntohs(n->flags);
! 	if (flags & PEER_FL_CONFIG)
  		c = '-';		/* mark pre-configured */
! 	if (flags & PEER_FL_SANE)
! 		c = '.';		/* passed sanity check */
! 	if (flags & PEER_FL_CANDIDATE)
! 		c = '+';		/* made candidate list */
! 	if (flags & PEER_FL_SELECTED)
  		c = '*';		/* mark peer selection */
  	sin.sin_addr.s_addr = n->net_address;
  	printf("%c%-15.15s ", c, cvthname(&sin));
