Index: Build
===================================================================
RCS file: Build
diff -N Build
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ Build	22 Mar 2004 01:16:32 -0000	1.3
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+source ../../Config.sh
+
+pp_do "$@"
Index: Makefile
===================================================================
RCS file: /srv/CVS/pp_shared/ntpclient/Makefile,v
retrieving revision 1.1.128.1
retrieving revision 1.2
diff -u -r1.1.128.1 -r1.2
--- Makefile	16 Oct 2003 14:22:11 -0000	1.1.128.1
+++ Makefile	6 Nov 2003 11:55:37 -0000	1.2
@@ -7,20 +7,27 @@
 #    CC = arm-linux-gcc
 # To check for lint
 # -Wundef not recognized by gcc-2.7.2.3
-CFLAGS += -Wall -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow \
+
+include ../../Config.mk
+
+#CFLAGS += -Wall -Wpointer-arith -Wcast-align -Wcast-qual -Wshadow \
  -Waggregate-return -Wnested-externs -Winline -Wwrite-strings \
  -Wstrict-prototypes
 
-CFLAGS += -O
+CFLAGS += $(FW_CFLAGS_3RDPARTY)
 
 all: ntpclient
 
 test: ntpclient
 	./ntpclient -d -r <test.dat
 
-ntpclient: ntpclient.o phaselock.o
+ntpclient: ntpclient.o phaselock.o hwclock.o
 
 adjtimex: adjtimex.o
 
 clean:
 	rm -f ntpclient adjtimex *.o
+
+install: all
+	install -d $(DESTDIR)/bin
+	install -m 755 ntpclient $(DESTDIR)/bin/
Index: hwclock.c
===================================================================
RCS file: hwclock.c
diff -N hwclock.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ hwclock.c	6 Nov 2003 11:55:37 -0000	1.2
@@ -0,0 +1,105 @@
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <linux/rtc.h>
+
+#ifdef PP_FW_TYPE_PEMX
+# define RTC_DEV "/dev/misc/rtc"
+#else
+# define RTC_DEV "/dev/rtc"
+#endif
+
+static int
+set_hardware_clock_rtc(const struct tm *new_broken_time) {
+    /* ---------------------------------------------------------------------
+     * Set the Hardware Clock to the broken down time <new_broken_time>.
+     * Use ioctls to "rtc" device /dev/rtc.
+     * --------------------------------------------------------------------- */
+    int rc = -1;
+    int rtc_fd;
+
+    if ((rtc_fd = open(RTC_DEV, O_RDONLY)) == -1) {
+	fprintf(stderr, "Unable to open %s", RTC_DEV);
+	exit(1);
+    }
+
+    rc = ioctl(rtc_fd, RTC_SET_TIME, new_broken_time);
+
+    if (rc == -1) {
+	fprintf(stderr, "ioctl(RTC_SET_TIME) to %s failed (%s).\n", RTC_DEV,
+		strerror(errno));
+	exit(1);
+    }
+
+    close(rtc_fd);
+
+    return 0;
+}
+
+static float 
+time_diff(struct timeval subtrahend, struct timeval subtractor)
+{
+    /* ---------------------------------------------------------------------
+     * The difference in seconds between two times in "timeval" format.
+     * --------------------------------------------------------------------- */
+    return( (subtrahend.tv_sec - subtractor.tv_sec) +
+	    (subtrahend.tv_usec - subtractor.tv_usec) / 1E6 );
+}
+
+static void
+set_hardware_clock(const time_t newtime)
+{
+    /* ---------------------------------------------------------------------
+     * Set the Hardware Clock to the time <newtime>, in local time zone.
+     * --------------------------------------------------------------------- */
+    struct tm new_broken_time;  
+
+    /*
+     * Time to which we will set Hardware Clock, in broken down format, in
+     * the time zone of caller's choice
+     */
+
+    new_broken_time = *localtime(&newtime);
+    set_hardware_clock_rtc(&new_broken_time);
+}
+
+void
+set_hardware_clock_exact(const time_t settime, const struct timeval ref_time)
+{
+    /* ----------------------------------------------------------------------
+     * Set the Hardware Clock to the time "settime", in local time zone or
+     * UTC, according to "universal".
+     *
+     * But correct "settime" and wait for a fraction of a second so that
+     * "settime" is the value of the Hardware Clock as of system time
+     * "ref_time", which is in the past.  For example, if "settime" is
+     * 14:03:05 and "ref_time" is 12:10:04.5 and the current system
+     * time is 12:10:06.0: Wait .5 seconds (to make exactly 2 seconds since
+     * "ref_time") and then set the Hardware Clock to 14:03:07, thus
+     * getting a precise and retroactive setting of the clock.
+     *
+     * (Don't be confused by the fact that the system clock and the Hardware
+     * Clock differ by two hours in the above example.  That's just to
+     * remind  you that there are two independent time scales here).
+     *
+     * This function ought to be able to accept set times as fractional
+     * times. Idea for future enhancement.
+     *
+     * --------------------------------------------------------------------- */
+    time_t newtime;  /* Time to which we will set Hardware Clock */
+    struct timeval now_time;  /* locally used time */
+
+    gettimeofday(&now_time, NULL);
+    newtime = settime + (int) time_diff(now_time, ref_time) + 1;
+  
+    /* Now delay some more until Hardware Clock time newtime arrives */
+    do gettimeofday(&now_time, NULL);
+    while (time_diff(now_time, ref_time) < newtime - settime);
+  
+    set_hardware_clock(newtime);
+}
Index: ntpclient.c
===================================================================
RCS file: /srv/CVS/pp_shared/ntpclient/ntpclient.c,v
retrieving revision 1.1.128.1
retrieving revision 1.2
diff -u -r1.1.128.1 -r1.2
--- ntpclient.c	16 Oct 2003 14:22:11 -0000	1.1.128.1
+++ ntpclient.c	6 Nov 2003 11:55:37 -0000	1.2
@@ -51,6 +51,8 @@
 
 #define ENABLE_DEBUG
 
+#define MAX_SERVERS 4
+
 extern char *optarg;
 
 /* XXXX fixme - non-automatic build configuration */
@@ -95,22 +97,30 @@
 	unsigned int fine;
 };
 
+struct ntpserver {
+	char * name;
+	struct sockaddr_in sa;
+	int valid;
+};
+
 /* prototype for function defined in phaselock.c */
 int contemplate_data(unsigned int absolute, double skew, double errorbar, int freq);
 
 /* prototypes for some local routines */
-void send_packet(int usd);
+void send_packet(int usd, struct sockaddr * sa_dest, socklen_t sa_dest_len);
 int rfc1305print(uint32_t *data, struct ntptime *arrival);
-void udp_handle(int usd, char *data, int data_len, struct sockaddr *sa_source, int sa_len);
+extern void set_hardware_clock_exact(const time_t settime,
+				     const struct timeval ref_time);
 
 /* variables with file scope
  * (I know, bad form, but this is a short program) */
 static uint32_t incoming_word[325];
 #define incoming ((char *) incoming_word)
 #define sizeof_incoming (sizeof(incoming_word)*sizeof(uint32_t))
-static struct timeval time_of_send;
 static int live=0;
 static int set_clock=0;   /* non-zero presumably needs root privs */
+struct ntpserver ntpservers[MAX_SERVERS];
+size_t n_servers = 0;
 
 /* when present, debug is a true global, shared with phaselock.c */
 #ifdef ENABLE_DEBUG
@@ -154,7 +164,7 @@
 #endif
 }
 
-void send_packet(int usd)
+void send_packet(int usd, struct sockaddr * sa_dest, socklen_t sa_dest_len)
 {
 	__u32 data[12];
 	struct timeval now;
@@ -179,8 +189,7 @@
 	gettimeofday(&now,NULL);
 	data[10] = htonl(now.tv_sec + JAN_1970); /* Transmit Timestamp coarse */
 	data[11] = htonl(NTPFRAC(now.tv_usec));  /* Transmit Timestamp fine   */
-	send(usd,data,48,0);
-	time_of_send=now;
+	sendto(usd, data, 48, 0, sa_dest, sa_dest_len);
 }
 
 void get_packet_timestamp(int usd, struct ntptime *udp_arrival_ntp)
@@ -264,15 +273,24 @@
 #undef Data
 
 	if (set_clock) {   /* you'd better be root, or ntpclient will crash! */
-		struct timeval tv_set;
+		struct timeval tv_set, myreftime;
 		/* it would be even better to subtract half the slop */
 		tv_set.tv_sec  = xmttime.coarse - JAN_1970;
 		/* divide xmttime.fine by 4294.967296 */
 		tv_set.tv_usec = USEC(xmttime.fine);
+		/*
+		 * We can only set_hardware_clock_exact to a whole seconds
+		 * time, so we set it with reference to the most recent whole
+		 * seconds time.
+		 */
+		myreftime.tv_sec = tv_set.tv_sec;
+		myreftime.tv_usec = 0;
 		if (settimeofday(&tv_set,NULL)<0) {
 			perror("settimeofday");
 			exit(1);
 		}
+		/* set the hardware clock */
+		set_hardware_clock_exact((time_t)myreftime.tv_sec, myreftime);
 		if (debug) {
 			printf("set time to %lu.%.6lu\n", tv_set.tv_sec, tv_set.tv_usec);
 		}
@@ -324,19 +342,20 @@
 	return(el_time-st_time);
 }
 
-void stuff_net_addr(struct in_addr *p, char *hostname)
+int stuff_net_addr(struct in_addr *p, char *hostname)
 {
 	struct hostent *ntpserver;
 	ntpserver=gethostbyname(hostname);
 	if (ntpserver == NULL) {
 		herror(hostname);
-		exit(1);
+		return 0;
 	}
 	if (ntpserver->h_length != 4) {
 		fprintf(stderr,"oops %d\n",ntpserver->h_length);
-		exit(1);
+		return 0;
 	}
 	memcpy(&(p->s_addr),ntpserver->h_addr_list[0],4);
+	return 1;
 }
 
 void setup_receive(int usd, unsigned int interface, short port)
@@ -354,15 +373,19 @@
 	listen(usd,3);
 }
 
-void setup_transmit(int usd, char *host, short port)
+void setup_transmit(short port)
 {
-	struct sockaddr_in sa_dest;
-	bzero((char *) &sa_dest, sizeof(sa_dest));
-	sa_dest.sin_family=AF_INET;
-	stuff_net_addr(&(sa_dest.sin_addr),host);
-	sa_dest.sin_port=htons(port);
-	if (connect(usd,(struct sockaddr *)&sa_dest,sizeof(sa_dest))==-1)
-		{perror("connect");exit(1);}
+	size_t i;
+	for (i = 0; i < n_servers; i++) {
+		bzero((char *)&ntpservers[i].sa, sizeof(ntpservers[i].sa));
+		ntpservers[i].sa.sin_family = AF_INET;
+		if (stuff_net_addr(&ntpservers[i].sa.sin_addr, ntpservers[i].name)) {
+			ntpservers[i].sa.sin_port = htons(port);
+			ntpservers[i].valid = 1;
+		} else {
+			ntpservers[i].valid = 0;
+		}
+	}
 }
 
 void primary_loop(int usd, int num_probes, int interval, int goodness)
@@ -372,6 +395,8 @@
 	int i, pack_len, sa_xmit_len, probes_sent, error;
 	struct timeval to;
 	struct ntptime udp_arrival_ntp;
+	size_t j;
+	int accept_packet = 0;
 
 	if (debug) printf("Listening...\n");
 
@@ -389,29 +414,38 @@
 			if (to.tv_sec == 0) {
 				if (probes_sent >= num_probes &&
 					num_probes != 0) break;
-				send_packet(usd);
+				for (j = 0; j < n_servers; j++) {
+					if (ntpservers[j].valid) {
+						send_packet(usd, (struct sockaddr*)&ntpservers[j].sa,
+							    sizeof(ntpservers[j].sa));
+					}
+				}
 				++probes_sent;
 				to.tv_sec=interval;
 				to.tv_usec=0;
+				accept_packet = 1;
 			}	
 			continue;
 		}
 		pack_len=recvfrom(usd,incoming,sizeof_incoming,0,
 		                  &sa_xmit,&sa_xmit_len);
 		error = goodness+1;
-		if (pack_len<0) {
-			perror("recvfrom");
-		} else if (pack_len>0 && (unsigned)pack_len<sizeof_incoming){
-			get_packet_timestamp(usd, &udp_arrival_ntp);
-			check_source(pack_len, &sa_xmit, sa_xmit_len);
-			error = rfc1305print(incoming_word, &udp_arrival_ntp);
-			/* udp_handle(usd,incoming,pack_len,&sa_xmit,sa_xmit_len); */
-		} else {
-			printf("Ooops.  pack_len=%d\n",pack_len);
-			fflush(stdout);
+		if (accept_packet) {
+			if (pack_len<0) {
+				perror("recvfrom");
+			} else if (pack_len>0 && (unsigned)pack_len<sizeof_incoming){
+				get_packet_timestamp(usd, &udp_arrival_ntp);
+				check_source(pack_len, &sa_xmit, sa_xmit_len);
+				error = rfc1305print(incoming_word, &udp_arrival_ntp);
+			} else {
+				printf("Ooops.  pack_len=%d\n",pack_len);
+				fflush(stdout);
+			}
+
+			if ( error < goodness && goodness != 0) break;
+			if (probes_sent >= num_probes && num_probes != 0) break;
 		}
-		if ( error < goodness && goodness != 0) break;
-		if (probes_sent >= num_probes && num_probes != 0) break;
+		accept_packet = 0;
 	}
 }
 
@@ -466,7 +500,6 @@
 	int probe_count=0;            /* default of 0 means loop forever */
 	/* int debug=0; is a global above */
 	int goodness=0;
-	char *hostname=NULL;          /* must be set */
 	int replay=0;                 /* replay mode overrides everything */
 
 	for (;;) {
@@ -485,7 +518,12 @@
 				goodness = atoi(optarg);
 				break;
 			case 'h':
-				hostname = optarg;
+				if (n_servers < MAX_SERVERS) {
+					ntpservers[n_servers++].name = optarg;
+				} else {
+					fprintf(stderr, "Too many hosts specified.\n");
+					exit(1);
+				}
 				break;
 			case 'i':
 				cycle_time = atoi(optarg);
@@ -501,32 +539,45 @@
 				break;
 			case 's':
 				set_clock++;
-				probe_count = 1;
+				//probe_count = 1;
 				break;
 			default:
 				usage(argv[0]);
 				exit(1);
 		}
 	}
+	if (n_servers == 0) {
+#define CONFIG_FILE "/etc/ntpclient.conf"
+		FILE * fp;
+		if ((fp = fopen(CONFIG_FILE, "r+")) != NULL) {
+			char line[256];
+			char server[256];
+			while (fgets(line, sizeof(line), fp) != NULL) {
+				if (sscanf(line, "server %255s", server) == 1) {
+					ntpservers[n_servers++].name = strdup(server);
+				}
+			}
+			fclose(fp);
+		}
+	}
 	if (replay) {
 		do_replay();
 		exit(0);
 	}
-	if (hostname == NULL) {
-		usage(argv[0]);
-		exit(1);
+	if (n_servers == 0) {
+		fprintf(stderr, "No NTP servers configured. Waiting for the killer ...\n");
+		while(pause());
 	}
 	if (debug) {
 		printf("Configuration:\n"
 		"  -c probe_count %d\n"
 		"  -d (debug)     %d\n"
 		"  -g goodness    %d\n"
-		"  -h hostname    %s\n"
 		"  -i interval    %d\n"
 		"  -l live        %d\n"
 		"  -p local_port  %d\n"
 		"  -s set_clock   %d\n",
-		probe_count, debug, goodness, hostname, cycle_time,
+		probe_count, debug, goodness, cycle_time,
 		live, udp_local_port, set_clock );
 	}
 
@@ -536,7 +587,7 @@
 
 	setup_receive(usd, INADDR_ANY, udp_local_port);
 
-	setup_transmit(usd, hostname, NTP_PORT);
+	setup_transmit(NTP_PORT);
 
 	primary_loop(usd, probe_count, cycle_time, goodness);
 
