[mod.computers.masscomp] setting network time

masscomp-request@soma.UUCP (02/10/87)

If you have a network of machine, you may want to keep all their
clocks in sync. Masscomp provides the "rtime" utility to
do this. It uses the ARPA-Internet TIMESERVER standard method
of setting the time. This is fine, if you have a couple of
machines.

John Quarterman wrote a utility that can be run on a large
network (or the Internet) to allow a machine to set its time
by polling a large number of machine and taking the "best"
time offered. I took that program and modified it for the
Masscomp.

The newer Masscomp (MC5400,MC5500-20,MC5500-PEP,MC5600,
MC5700) provided internal time-of-day clocks. Unfortunately,
if these clocks get our of sync, the only current mechanism
documented is using the "date" command to reset those clocks.
As a result, this program does not know how to reset those clocks
and only reset the kernel clock. Perhaps someone at Westford
can clue us in.

Here is a shar archive of the program. Enjoy.
Stan Barber
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	netdate.8
#	netdate.c
#	makefile
#	rfc868
# This archive created: Tue Feb 10 14:38:01 1987
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'netdate.8'" '(5229 characters)'
if test -f 'netdate.8'
then
	echo shar: "will not over-write existing file 'netdate.8'"
else
sed 's/^	X//' << \SHAR_EOF > 'netdate.8'
	X.TH NETDATE 8L 85/08/21
	X.UC 4
	X.SH NAME
	Xnetdate \- set date and time by ARPA Internet RFC 868
	X.SH SYNOPSIS
	X.B
	X/etc/netdate
	X[ \-v ] [ \-l limit ] [ protocol ] hostname...
	X.SH DESCRIPTION
	X\fINetdate\fP takes a list of names of Internet hosts as arguments,
	Xselects the one which supplies the best time, and sets
	Xthe system time accordingly.
	XThe invoker must be the super-user for the time to be set.
	XProtocol names (either \fBudp\fP or \fBtcp\fP) may be
	Xinterspersed with the host names, and determine the
	Xprotocol which will be used to connect to the hosts
	Xwhose names follow, up to the next protocol name or
	Xthe end of the arguments.
	XThe default protocol is \fBudp\fP.
	X.PP
	XThe ``best'' time is chosen by polling the named hosts
	Xonce each to find their times and taking their differences
	Xfrom the local host's time.
	XThese differences are used to find the largest group of hosts
	Xwhose times agree with each other within a certain limit.
	XThe first host in the largest group is picked as the best host.
	X(The assumption is that the hosts which are usually most accurate
	Xwill be named first.)
	XThat host is polled again and the local host's time is set to the result.
	XThe chosen host's time is checked on this second poll to insure that
	Xits difference from the local host's time has not varied more than the limit
	Xfrom its difference at the first poll.
	X.PP
	XThe default limit is five seconds.  It may be set with the \fB\-l\fP option.
	XThe \fB\-v\fP option causes the groups to be shown.
	XThe host name \fBlocalhost\fP is recognized as a synonym for the name
	Xof the local host, no network connection is made for it, and its
	Xtime difference is always zero.
	XIf \fBlocalhost\fP is chosen as having the best time,
	Xthe system time will not be set.
	XHosts which do not respond are not counted in the groups.
	XIf the limit is set to zero, the time is set to that of the
	Xfirst host to respond and no other checking is done.
	XSupplying only one host name argument also sets the limit to zero.
	X.PP
	XWhile the RFC868 protocol only returns 32\ bits of data, containing
	Xthe time in seconds, \fInetdate\fP will accept an extra 32\ bits,
	Xcontaining microseconds (expected to be accurate to no more than milliseconds).
	XDelays on long haul networks may make this extra precision useless,
	Xbut it is useful on local area networks.
	XThe extra precision is not used on the first poll of a host,
	Xbut it is used on the second poll of the chosen host,
	Xif that host supplies it.
	X.SH EXAMPLE
	XThe most accurate hosts are named first in each example.
	XSome such call on \fInetdate\fP should be put at the end of \fB/etc/rc.local\fP,
	Xso that the time will be set properly on system startup.
	XIt is also useful to have a shell script, e.g., \fB/etc/timehosts\fP,
	Xwhich contains a call on \fInetdate\fP with arguments appropriate
	Xto the local system, so that it is easy to set the time manually.
	X.SH "/etc/netdate -l 30 udp dcn\-gateway tcp neighbor"
	X\fIDcn\-gateway\fP is a hypothetical host which usually keeps time
	Xaccurate to within milliseconds of Coordinated Universal Time,
	Xbut may occasionally be eight hours off.
	X\fINeighbor\fP is a neighbor of the local host which keeps time
	Xwith moderate accuracy.
	XThe time will be set to that of \fIdcn\-gateway\fP if that and \fIneighbor\fP
	Xagree to within thirty seconds, else it will not be set at all.
	XThis is almost good enough for most circumstances, but won't do
	Xwhen the local host's time is known to be wrong (e.g., after
	Xa long downtime or a bad crash) and must be set to something.
	XIf one of the hosts named is inaccurate or not responding, there is a problem.
	X.SH "/etc/netdate -l 30 udp dcn\-gateway tcp neighbor neighbor2"
	XOnly two of the three hosts named must agree on the time.
	XThe time will still be set (to that of the first neighbor),
	Xeven if \fIdcn\-gateway\fP is far off as long as the two neighbors agree.
	XThis is probably good enough for most cases.
	XOne can arbitrarily gerrymander the vote for more insurance
	X(and less clarity), as in the following example.
	X.SH "/etc/netdate\ udp\ dcn\-gateway\ dcn1\ tcp\ bbn\-unix\ localhost\ neighbor"
	XHere \fIdcn1\fP and \fIbbn\-unix\fP are more hypothetical very accurate
	Xtimekeepers, at least one of which keeps time independently from
	X\fIdcn\-gateway\fP, one hopes.
	XIt is very likely that the time will be set to that one of those three
	Xvery accurate hosts, as long as at least two of them agree, or at least
	Xone of them agrees with the neighbor or the local host's time.
	XIf all the foreign hosts disagree, the time will not be set,
	Xsince \fBlocalhost\fP will be chosen as best.
	X.SH "/etc/netdate\ \-l\ 3\ localhost\ localhost\ udp\ dcn\-gateway\ dcn1\ tcp\ bbn\-unix"
	XThis example gives \fBlocalhost\fP two votes and declares it to usually
	Xhave the most accurate time.
	XAll three foreign hosts must agree within three seconds
	Xand also differ from \fBlocalhosts\fP by more than three seconds
	Xfor the time to be set.
	XThus the time will be set only if it really needs to be.
	X.SH FILES
	X.nf
	X/etc/services	for the time service port number
	X/etc/protocols	for the protocol numbers
	X/usr/adm/wtmp	to record time-setting
	X.SH SEE ALSO
	XARPANET Request for Comments 868, gettimeofday(2), date(1),
	XWWV (USA):
	X2.5,5,10,15 MHz AM for Coordinated Universal Time (UCT).
	X.SH DIAGNOSTICS
SHAR_EOF
if test 5229 -ne "`wc -c < 'netdate.8'`"
then
	echo shar: "error transmitting 'netdate.8'" '(should have been 5229 characters)'
fi
fi
echo shar: "extracting 'netdate.c'" '(11728 characters)'
if test -f 'netdate.c'
then
	echo shar: "will not over-write existing file 'netdate.c'"
else
sed 's/^	X//' << \SHAR_EOF > 'netdate.c'
	X#ifndef lint
	Xchar sccsid[]="@(#)$Header: netdate.c,v 1.17 87/02/09 18:25:03 sob Exp $";
	X/*
	X * by John Quarterman (jsq@im4u.UTEXAS.EDU)
	X * Modified by Stan Barber (sob@soma.bcm.tmc.edu)
	X */
	X#endif
	X#if defined(mc300) || defined(mc500) || defined(mc700)
	X#define MASSCOMP
	X#endif
	X#include <sys/param.h>
	X#include <sys/stat.h>
	X#include <sys/ioctl.h>
	X#include <sys/socket.h>
	X
	X#include <netinet/in.h>
	X
	X#include <stdio.h>
	X#include <netdb.h>
	X#include <sys/time.h>
	X#include <setjmp.h>
	X#include <signal.h>
	X#include <utmp.h>
	X
	X#ifndef WTMP
	X#define WTMP "/usr/adm/wtmp"
	X#endif
	X
	Xstruct utmp wtmp[2]
	X#ifndef MASSCOMP	
	X/* this is ugly!! -- but I did it.-- sob*/
	X= {
	X	{ "|", "", "", 0 },
	X	{ "{", "", "", 0 }
	X};
	Xchar *defaultproto = "udp";
	X#else
	X;
	Xchar *defaultproto = "tcp";	/* timeserver in sp-70 is tcp protocol */
	X#endif
	Xchar *service = "time";
	X/* difference between 1900 (RFC868) and 1970 (UNIX) base times */
	X#define NETBASE	2208988800
	X
	Xlong limit = 5;
	X#define MAXHOSTS 20
	X
	X#define LOCALHOST "localhost"
	Xchar *whoami;
	Xchar hostname[65];
	Xstruct timeval now;
	Xstruct timehost {
	X	char *hostname;
	X	short local;
	X	short bad;
	X	char *protoname;
	X	long protonumber;
	X	int socktype;
	X	struct timeval asked;
	X	struct timeval then;
	X	struct timeval acked;
	X	long difference;
	X	long count;
	X} timehosts[MAXHOSTS];
	Xstruct timehost *tophost = &timehosts[MAXHOSTS];
	X
	Xusage ()
	X{
	Xfprintf (stderr,
	X	"%s [ -l limit ] host ...\n", whoami);
	Xfprintf (stderr,
	X	"%s tries to find a group of at least two hosts\n", whoami);
	Xfprintf (stderr,
	X	"whose times agree within %d seconds,\n", hostname, limit);
	Xfprintf (stderr,
	X	"and sets the time to that of the first host in the group.\n");
	Xfprintf (stderr,
	X	"The limit may be set with the -l option.  Setting it\n");
	Xfprintf (stderr,
	X	"to zero (or supplying only one host name argument)\n");
	Xfprintf (stderr,
	X	"will set the time to that of the first host to respond.\n");
	Xfprintf (stderr,
	X	"The caller must be super-user for the system time to be set.\n");
	X
	X	exit (1);
	X}
	X
	Xint rdate = 0;
	Xint verbose = 0;
	Xint debug = 0;
	X
	Xmain (argc, argv)
	Xint argc;
	Xchar **argv;
	X{
	X	extern char *rindex();
	X	struct timehost *mungediffs();
	X	register struct timehost *thishost;
	X	int hostargs = 0;
	X
	X	if ((whoami = rindex(*argv, '/')) != NULL)
	X		whoami++;
	X	else
	X		whoami = *argv;
	X	if (strcmp (whoami, "rdate") == 0) {	/* emulate SMI rdate command */
	X		rdate = 1;
	X		defaultproto = "tcp";
	X		limit = 0;
	X	}
	X	if (gethostname(hostname, (int)sizeof (hostname)) == -1) {
	X		perror ("gethostname");
	X		exit (1);
	X	}
	X	while (*++argv != NULL && **argv == '-') {
	X		switch (argv[0][1]) {
	X		case 'd':
	X			debug++;
	X			break;
	X		case 'v':
	X			verbose++;
	X			break;
	X		case 'l':
	X			if (*++argv == NULL)
	X				usage();
	X			limit = atoi(*argv);
	X			break;
	X		default:
	X			fprintf (stderr, "Unknown option:  %s\n", *argv);
	X			usage();
	X			break;
	X		}
	X	}
	X	if (*argv == NULL)
	X		usage();
	X	if (debug)
	X		fprintf (stderr, "%s: rdate %d; verbose %d; limit %d.\n", 
	X			whoami, rdate, verbose, limit);
	X	for (thishost = &timehosts[0]; *argv != NULL; argv++) {
	X		if (thishost >= tophost) {
	X			fprintf(stderr, "Too many hosts: ignoring");
	X			do {
	X				fprintf (stderr, " %s", *argv);
	X			} while (*++argv != NULL);
	X			fprintf (stderr, "\n");
	X			break;
	X		}
	X		if (setproto(*argv, thishost))
	X			continue;
	X		thishost -> hostname = *argv;
	X		thishost -> bad = 0;
	X		if (strcmp (thishost -> hostname, LOCALHOST) == 0)
	X			thishost -> local = 1;
	X		if (++hostargs == 1 && argv[1] == NULL)	/* Only one host arg, */
	X			limit = 0;			/* so just set to it. */
	X		if (limit == 0) {
	X			if (!getdate(thishost))
	X				continue;
	X			exit(0);
	X		}
	X		if (!getdiff (thishost))
	X			continue;
	X		thishost++;
	X	}
	X	if (limit == 0)
	X		exit(1);
	X	if (thishost == &timehosts[0])
	X		exit(1);
	X	if ((thishost = mungediffs(thishost)) == NULL) {
	X		fprintf (stderr,
	X			"No two hosts agree on the time within %d seconds\n",
	X			limit);
	X		exit(1);
	X	}
	X	if (!getdate (thishost))
	X		exit (1);
	X	exit(0);
	X}
	X
	Xsetproto(what, thishost)
	Xchar *what;
	Xstruct timehost *thishost;
	X{
	X	static	char *protoname;
	X	static	long protonumber;
	X	static	int socktype;
	X	register struct protoent *pp;
	X
	X	setprotoent(1);
	X	if ((pp = getprotobyname (what)) == NULL) {
	X		if (protoname == NULL)
	X			if (!setproto(defaultproto, thishost)) {
	X				fprintf(stderr,
	X#ifdef MASSCOMP
	X		"Default protocol %s was not found in /etc/net/protocols.\n",
	X#else
	X		"Default protocol %s was not found in /etc/protocols.\n",
	X#endif
	X						defaultproto);
	X				exit(1);
	X			}
	X		thishost -> protoname = protoname;
	X		thishost -> protonumber = protonumber;
	X		thishost -> socktype = socktype;
	X		return(0);
	X	}
	X	protoname = what;	/*pp -> p_name;	this is static:  don't use it.*/
	X	protonumber = pp -> p_proto;
	X	switch (protonumber) {
	X		case IPPROTO_TCP:
	X			socktype = SOCK_STREAM;
	X			if (debug)
	X				fprintf(stderr, "%s SOCK_STREAM\n", protoname);
	X			break;
	X		case IPPROTO_UDP:
	X			socktype = SOCK_DGRAM;
	X			if (debug)
	X				fprintf(stderr, "%s SOCK_DGRAM\n", protoname);
	X			break;
	X		default:
	X			fprintf(stderr, "Unknown protocol:  %s\n", protoname);
	X			exit(1);
	X			break;
	X	}
	X	return(1);
	X}
	X
	Xgetdiff(thishost)
	Xstruct timehost *thishost;
	X{
	X	if (!internettime (thishost))
	X		return(0);
	X	thishost -> difference = thishost -> then.tv_sec - now.tv_sec;
	X	if (!rdate)
	X		printit(thishost);
	X	return(1);
	X}
	X
	X
	X/*
	X	Find the largest group of hosts which agree within the limit
	X	and return the first of that group.  If no two hosts agree,
	X	give up.
	X */
	Xstruct timehost *
	Xmungediffs(tophost)
	Xstruct timehost *tophost;
	X{
	X	register struct timehost *thishost, *ahost, *goodhost;
	X	long diff;
	X
	X	tophost--;	/* simplifies the comparisons */
	X	goodhost = &timehosts[0];
	X	for (thishost = &timehosts[0]; thishost < tophost; thishost++) {
	X		if (thishost -> bad)
	X			continue;
	X		thishost -> count = 1;
	X		if (verbose)
	X			printf ("%s", thishost -> hostname);
	X		for (ahost = thishost + 1; ahost <= tophost; ahost++) {
	X			if (thishost -> bad)
	X				continue;
	X			diff = ahost -> difference - thishost -> difference;
	X			if (abs(diff) < limit) {
	X				thishost -> count++;
	X				if (verbose)
	X					printf (" %s", ahost -> hostname);
	X			}
	X		}
	X		if (verbose) {
	X			printf (" %d\n", thishost -> count);
	X			(void)fflush(stdout);
	X		}
	X		if (thishost -> count > goodhost -> count)
	X			goodhost = thishost;
	X	}
	X	if (goodhost -> count > 1)
	X		return(goodhost);
	X	return(NULL);
	X}
	X
	Xgetdate (thishost)
	Xregister struct timehost *thishost;
	X{
	X	int set = 0;
	X
	X	if (!internettime (thishost))
	X		return (0);
	X	if (thishost -> local) {
	X		printf ("Local host %s has best time, so not setting date\n",
	X			hostname);
	X		printit(thishost);
	X		exit(0);
	X	}
	X	if (limit != 0
	X	&& abs((thishost -> then.tv_sec - now.tv_sec) - thishost -> difference)
	X	    > limit) {
	X		fprintf (stderr,
	X		"Time from %s has varied more than the limit of %d seconds\n",
	X			thishost -> hostname, limit);
	X		printit(thishost);
	X		exit(1);
	X	}
	X	if (settimeofday (&thishost -> then, (struct timezone *)0) == -1)
	X		perror ("netdate; settimeofday");
	X	else {
	X		/* this is not needed on Masscomp, I think. -- sob*/
	X
	X		int wf;
	X		if ((wf = open(WTMP, 1)) >= 0) {
	X#ifndef MASSCOMP
	X			wtmp[0].ut_time = now.tv_sec;
	X			wtmp[1].ut_time = thishost -> then.tv_sec;
	X#else
	X			bzero((char*) wtmp,sizeof(wtmp));
	X			/* is this the right order? */	
	X			wtmp[0].ut_type = OLD_TIME;
	X			wtmp[0].ut_time = thishost -> then.tv_sec;
	X			wtmp[1].ut_type = NEW_TIME;
	X			wtmp[1].ut_time = now.tv_sec;
	X			strcpy(wtmp[0].ut_line,OTIME_MSG);
	X			strcpy(wtmp[1].ut_line,NTIME_MSG);
	X#endif
	X			(void)lseek(wf, 0L, 2);
	X			(void)write(wf, (char *)wtmp, sizeof(wtmp));
	X			(void)close(wf);
	X		}
	X
	X		set = 1;
	X	}
	X	printit(thishost);
	X	return(set);
	X}
	X
	Xprintit(thishost)
	Xstruct timehost *thishost;
	X{
	X	extern char *ctime();
	X	struct tm *tp, *localtime();
	X	struct timeval diff;
	X	char newstring[128];
	X
	X	if (rdate)
	X		printf ("%s", ctime((unsigned long *)&thishost -> then.tv_sec));
	X	else {
	X		(void)sprintf(newstring, "%s ", thishost -> hostname);
	X		tvsub(&diff, &thishost -> then, &now);
	X		printdiff(&newstring[strlen(newstring)], &diff);
	X		printf ("%-24s %.19s.%03d", newstring,
	X			ctime((unsigned long *)&thishost -> then.tv_sec),
	X				thishost -> then.tv_usec / 1000);
	X		if (verbose) {
	X			tp = localtime((unsigned long *)&thishost -> acked);
	X			printf(" at %02d:%02d:%02d.%03d",
	X				tp -> tm_hour, tp -> tm_min, tp -> tm_sec,
	X				thishost -> acked.tv_usec / 1000);
	X			tvsub(&diff, &thishost -> acked, &thishost -> asked);
	X			printdiff(newstring, &diff);
	X			printf(" delay %s", newstring);
	X		}
	X		printf("\n");
	X	}
	X	(void)fflush (stdout);
	X}
	X
	Xtvsub(tdiff, t1, t0)
	X	struct timeval *tdiff, *t1, *t0;
	X{
	X	tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
	X	tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
	X	if (tdiff->tv_sec < 0 && tdiff->tv_usec > 0)
	X		tdiff->tv_sec++, tdiff->tv_usec -= 1000000;
	X	if (tdiff->tv_sec > 0 && tdiff->tv_usec < 0)
	X		tdiff->tv_sec--, tdiff->tv_usec += 1000000;
	X}
	X
	Xprintdiff(where, diff)
	Xchar *where;
	Xstruct timeval *diff;
	X{
	X	(void) sprintf (where, "%c%d.%.03d",
	X		(diff->tv_sec < 0 || diff->tv_usec < 0) ? '-' : '+',
	X		abs(diff->tv_sec), abs(diff->tv_usec) / 1000);
	X}
	X
	Xstatic	jmp_buf jb;
	Xstatic int
	Xtimeout()
	X{
	X	longjmp(jb, 1);
	X}
	X
	Xstatic
	Xinternettime (thishost)
	Xstruct timehost *thishost;
	X{
	X	register struct hostent *hp;
	X	struct sockaddr_in sin;
	X	long port;
	X	int nread;
	X	static int s = -1;
	X
	X	if (thishost -> local) {
	X		if (gettimeofday (&now, (struct timezone *)0) == -1) {
	X			perror ("netdate: gettimeofday");
	X			exit (1);
	X		}
	X		thishost -> asked = now;
	X		thishost -> then = now;
	X		thishost -> acked = now;
	X		return(1);
	X	}
	X	timerclear(&thishost -> then);
	X	if (setjmp(jb))
	X		goto bad;
	X	(void)signal(SIGALRM, timeout);
	X	if (s != -1)
	X		(void) close (s), s = -1;
	X	port = getport(thishost -> protoname);
	X	bzero((char *)&sin, sizeof (sin));
	X	sethostent(1);
	X	if ((hp = gethostbyname(thishost -> hostname)) == NULL) {
	X		fprintf(stderr, "%s: %s: unknown host\n",
	X			whoami, thishost -> hostname);
	X		goto out;
	X	}
	X	sin.sin_family = hp->h_addrtype;
	X	(void)alarm(20);
	X	s = socket(hp->h_addrtype, thishost -> socktype, 0 /*protonumber*/);
	X	if (s < 0) {
	X		perror("netdate: socket");
	X		(void)alarm(0);
	X		goto out;
	X	}
	X	if (thishost -> socktype == SOCK_STREAM) {
	X		if (bind(s, (char *)&sin, sizeof (sin)) < 0) {
	X			perror("netdate: bind");
	X			goto bad;
	X		}
	X	}
	X	bcopy(hp->h_addr, (char *)&sin.sin_addr, hp->h_length);
	X	sin.sin_port = port;
	X	(void)gettimeofday (&thishost -> asked, (struct timezone *)0);
	X	if (connect(s, (char *)&sin, sizeof (sin)) < 0) {
	X		perror("netdate: connect");
	X		goto bad;
	X	}
	X	if (thishost -> socktype == SOCK_DGRAM) {
	X		if (write (s, "\n", 1) < 0) {
	X			perror ("netdate: send");
	X			goto bad;
	X		}
	X	}
	X	nread = read (s, (char *)&thishost -> then, sizeof (thishost -> then));
	X	(void)gettimeofday (&thishost -> acked, (struct timezone *)0);
	X	(void)alarm(0);
	X	now = thishost -> acked;
	X	if (nread < sizeof(thishost -> then.tv_sec)) {
	X		perror ("netdate: read");
	X		goto bad;
	X	}
	X	/* RFC 868 only allows seconds, but what the hell */
	X	if (nread == sizeof(thishost -> then))
	X		thishost -> then.tv_usec = ntohl(thishost -> then.tv_usec);
	X	else
	X		thishost -> then.tv_usec = 0L;
	X	thishost -> then.tv_sec = ntohl (thishost -> then.tv_sec) - NETBASE;
	X	return (1);	/* don't close before returning to avoid delays */
	Xbad:
	X	(void)alarm(0);
	X	(void) close (s), s = -1;
	Xout:
	X	if (gettimeofday (&now, (struct timezone *)0) == -1) {
	X		perror ("netdate: gettimeofday");
	X		exit (1);
	X	}
	X	thishost -> asked = now;
	X	thishost -> then = now;
	X	thishost -> acked = now;
	X	thishost -> bad = 1;
	X	fprintf (stderr, "Connection with %s to %s failed.\n",
	X		thishost -> protoname, thishost -> hostname);
	X	return(0);
	X}
	X
	Xgetport(protoname)
	Xchar *protoname;
	X{
	X	register struct servent *sp;
	X	static long port;
	X
	X	if (port != 0)
	X		return(port);
	X	if ((sp = getservbyname(service, protoname)) == 0) {
	X		fprintf(stderr, "%s: %s/%s: unknown service\n",
	X			whoami, service, protoname);
	X		exit(1);
	X	}
	X	return (port = sp->s_port);
	X}
SHAR_EOF
if test 11728 -ne "`wc -c < 'netdate.c'`"
then
	echo shar: "error transmitting 'netdate.c'" '(should have been 11728 characters)'
fi
fi
echo shar: "extracting 'makefile'" '(127 characters)'
if test -f 'makefile'
then
	echo shar: "will not over-write existing file 'makefile'"
else
sed 's/^	X//' << \SHAR_EOF > 'makefile'
	Xall: netdate timed
	X
	Xnetdate: netdate.c
	X	$(CC) $(CFLAGS) -o netdate netdate.c
	X
	Xtimed: timed.c
	X	$(CC) $(CFLAGS) -o timed timed.c
SHAR_EOF
if test 127 -ne "`wc -c < 'makefile'`"
then
	echo shar: "error transmitting 'makefile'" '(should have been 127 characters)'
fi
fi
echo shar: "extracting 'rfc868'" '(3024 characters)'
if test -f 'rfc868'
then
	echo shar: "will not over-write existing file 'rfc868'"
else
sed 's/^	X//' << \SHAR_EOF > 'rfc868'
	X
	XNetwork Working Group                                    J. Postel - ISI
	XRequest for Comments: 868                           K. Harrenstien - SRI
	X                                                                May 1983
	X
	X
	X
	X                             Time Protocol
	X
	X
	X
	X
	XThis RFC specifies a standard for the ARPA Internet community.  Hosts on
	Xthe ARPA Internet that choose to implement a Time Protocol are expected
	Xto adopt and implement this standard.
	X
	XThis protocol provides a site-independent, machine readable date and
	Xtime.  The Time service sends back to the originating source the time in
	Xseconds since midnight on January first 1900.
	X
	XOne motivation arises from the fact that not all systems have a
	Xdate/time clock, and all are subject to occasional human or machine
	Xerror.  The use of time-servers makes it possible to quickly confirm or
	Xcorrect a system's idea of the time, by making a brief poll of several
	Xindependent sites on the network.
	X
	XThis protocol may be used either above the Transmission Control Protocol
	X(TCP) or above the User Datagram Protocol (UDP).
	X
	XWhen used via TCP the time service works as follows:
	X
	X   S: Listen on port 37 (45 octal).
	X
	X   U: Connect to port 37.
	X
	X   S: Send the time as a 32 bit binary number.
	X
	X   U: Receive the time.
	X
	X   U: Close the connection.
	X
	X   S: Close the connection.
	X
	X   The server listens for a connection on port 37.  When the connection
	X   is established, the server returns a 32-bit time value and closes the
	X   connection.  If the server is unable to determine the time at its
	X   site, it should either refuse the connection or close it without
	X   sending anything.
	X
	X
	X
	X
	X
	X
	X
	XPostel                                                          [Page 1]
	X
	X
	X
	XRFC 868                                                         May 1983
	XTime Protocol                                                           
	X
	X
	XWhen used via UDP the time service works as follows:
	X
	X   S: Listen on port 37 (45 octal).
	X
	X   U: Send an empty datagram to port 37.
	X
	X   S: Receive the empty datagram.
	X
	X   S: Send a datagram containing the time as a 32 bit binary number.
	X
	X   U: Receive the time datagram.
	X
	X   The server listens for a datagram on port 37.  When a datagram
	X   arrives, the server returns a datagram containing the 32-bit time
	X   value.  If the server is unable to determine the time at its site, it
	X   should discard the arriving datagram and make no reply.
	X
	XThe Time
	X
	XThe time is the number of seconds since 00:00 (midnight) 1 January 1900
	XGMT, such that the time 1 is 12:00:01 am on 1 January 1900 GMT; this
	Xbase will serve until the year 2036.
	X
	XFor example:
	X
	X   the time  2,208,988,800 corresponds to 00:00  1 Jan 1970 GMT,
	X
	X             2,398,291,200 corresponds to 00:00  1 Jan 1976 GMT,
	X
	X             2,524,521,600 corresponds to 00:00  1 Jan 1980 GMT,
	X
	X             2,629,584,000 corresponds to 00:00  1 May 1983 GMT,
	X
	X        and -1,297,728,000 corresponds to 00:00 17 Nov 1858 GMT.
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	X
	XPostel                                                          [Page 2]
	X
	X
SHAR_EOF
if test 3024 -ne "`wc -c < 'rfc868'`"
then
	echo shar: "error transmitting 'rfc868'" '(should have been 3024 characters)'
fi
fi
exit 0
#	End of shell archive