[comp.sources.misc] v20i069: remtime - Remote Time Synchronization without ntp, Part01/01

dold@mitisft.convergent.com (Clarence Dold) (06/26/91)

Submitted-by: Clarence Dold <dold@mitisft.convergent.com>
Posting-number: Volume 20, Issue 69
Archive-name: remtime/part01
Environment: SYSVR3, SYSVr4, INET

This is a utility that I use on a network of SysV machines.
I don't have ntp, and I don't need incredible accuracy.  This keeps the
systems within a couple of seconds of each other.
I have one system that is slaved to NBS via modem once a week.
The others all run 'remtime' to it at boot time, and periodically.

#!/bin/sh -f
# This is a shell archive, meaning:
# 1. Remove everything above the "#!/bin/sh -f" line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# Wrapped by dold@tsdold.Convergent.COM - Sat Jun 22 09:19:01 PDT 1991 
# size    5063 bytes -- remtime.c
# This archive created: Sat Jun 22 09:19:01 PDT 1991
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'remtime.c'" '(5063 characters)'
if test -f 'remtime.c'
then
  echo shar: "will not over-write existing file 'remtime.c'"
else
sed 's/^X//' << \SHAR_EOF > 'remtime.c'
X#ifdef COMMENT 
X
Xset tabstop=4 
XThis works on the S/Series, as well as the SPC and U6000.
XYou need a host that is running the timeservice.  Any sysVr4 machine should.
X'tsdold' does.  tsdold is synched to WWV on Sunday morning.
X
XFor sysVr3 SPC and S/Series:
Xcc -#Oo remtime remtime.c -lsocket -lc_s
Xor
Xcc -#go remtime -DDEBUG remtime.c -lsocket -lc_s
X
XFor sysVr4 SPC and S/8400:
Xcc -#Oo remtime remtime.c  -lsocket -lnsl 
X
XFor IBM RS6000:
Xcc -Oo remtime remtime.c
X
X#endif /* COMMENT */
X
Xstatic char *Author = " dold@Convergent.COM ";
X#include <stdio.h>
X#include <sys/types.h>
X#include <netinet/in.h>
X#include <sys/socket.h>
X#include <netdb.h>
X#include <time.h>
X
X#define EPOCH 0x83aa7e80	/* The start of UNIX time */
X#define TOOMUCH 100 * 3600
X#define TOOLIT 3	/* granularity of one, desired of two */
Xextern int errno;
X
Xint
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X	struct sockaddr_in sin;
X	struct hostent *host;
X	struct servent *serv;
X	time_t intime, mytime, oldtime;
X	unsigned long delta;
X	int sock, con, rd;
X	
X	
X	if (2 > argc){
X		fprintf(stderr, "Usage: %s hostname\n", argv[0]);
X		exit(-1);
X	}
X	
X	if (serv = getservbyname ( "time", "tcp" )) /* assignment non-NULL */
X		sin.sin_port = serv->s_port;
X	else {
X		perror("Cannot locate time service");
X		exit(errno);
X	}
X	
X	if (host = gethostbyname(argv[1])) {
X		sin.sin_family = host->h_addrtype;
X		memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
X	} else {
X		fprintf(stderr, "Cannot resolve host name\n");
X		exit(errno);
X	}
X	
X	if ( (-1) != (sock = socket(AF_INET, SOCK_STREAM, 0))) {
X		con = connect(sock, (struct sockaddr *) &sin, sizeof(sin));
X	} else {
X		perror("socket");
X		exit(errno);
X	}
X
X	if ( sizeof(intime) != (rd = read(sock, &mytime, sizeof(intime)))){
X		fprintf(stderr, "Remote time service not available\n");
X		exit(-1);
X	}
X	
X	intime = ntohl(mytime);	/* Handle Byte-order for Intel */
X	mytime = intime - EPOCH;
X
X	
X	oldtime = time(0);
X
X	delta = mytime - oldtime;
X#ifdef DEBUG
X	fprintf(stderr, "Received %x, (less epoch) = %x, %s", 
X		intime, mytime, ctime(&mytime));
X	fprintf(stderr, "Delta: %d\n", delta);
X#endif
X
X	if ( !delta  || delta < TOOLIT || delta > (unsigned)(-TOOLIT) ){
X	printf("Time is in agreement with %s\n", argv[1]);
X	exit(0);
X	}
X
X	if ( delta > TOOMUCH && delta < (unsigned)(-TOOMUCH) ){
X	printf("This program won't adjust more than %d hours,\n\
X	Remote time is %s", TOOMUCH/3600, ctime(&mytime));
X	printf("\t Local time is %s", ctime(&oldtime));
X	exit(-1);
X	}
X	
X	printf("Current system clock is %s", ctime(&oldtime));
X
X	setrtc(mytime);
X
X
X	mytime = time(0);
X	printf("Time is now %s", ctime(&mytime));
X	
X	return(0);
X}
X/* +++++++++++++++ end of main() ++++++++++++++++ */
X
X#if mc68k || i386	/* Routine common to Convergent Systems */
X#include <sys/syslocal.h>
X#include <utmp.h>
X#include <fcntl.h>
X	int fd_wtmp;
X	struct utmp utmp[2] = {
X		{"", "", OTIME_MSG, 0, OLD_TIME, 0, 0, 0}, 
X		{"", "", NTIME_MSG, 0, NEW_TIME, 0, 0, 0} 
X	};
X#else	/* Not a recognized box */
Xunsigned long delta;
Xchar dateline[30];
X#endif
X
Xint
Xsetrtc(clock)
Xtime_t clock;
X{
Xstruct tm *tm;
X
X
X#if mc68k	/* Convergent SysVr3 S/Series family */
X#include <sys/rtc.h>
Xstruct rtc rtc;
X	tm = gmtime(&clock);
X	rtc.sec10 = tm->tm_sec / 10;
X	rtc.sec1 = tm->tm_sec % 10;
X	rtc.min10 = tm->tm_min / 10;
X	rtc.min1 = tm->tm_min % 10;
X	rtc.hr10 = tm->tm_hour / 10;
X	rtc.hr1 =  tm->tm_hour % 10;
X	rtc.day10 = tm->tm_mday / 10;
X	rtc.day1 = tm->tm_mday % 10;
X	tm->tm_mon++;	/* tm struct numbers from 0 RTC wants 1-12 */
X	rtc.mon10 = tm->tm_mon / 10;
X	rtc.mon1 = tm->tm_mon % 10;
X	rtc.yr10 = tm->tm_year / 10;
X	rtc.yr1 = tm->tm_year % 10;
X	rtc.wkday = tm->tm_wday;
X
X#elif i386	/* Convergent / Unisys SPC / U6000 family */
X#include <sys/todc.h>
X	struct todc rtc;
X	tm = localtime(&clock);
X	rtc.todc_year   = tm->tm_year;
X	rtc.todc_month  = tm->tm_mon;	/*SPC RTC wants 0-11 */
X	rtc.todc_day    = tm->tm_mday;
X	rtc.todc_hour   = tm->tm_hour;
X	rtc.todc_minute = tm->tm_min;
X	rtc.todc_second = tm->tm_sec;
X	rtc.todc_dow    = tm->tm_wday;
X	rtc.todc_millisec = 0;
X
X#else	/* undefined system */
X	printf("Setting system clock to %s\twaiting for next even minute to set RTC\n", ctime(&clock));
X	
X	tm = localtime(&clock);
X	delta = 60 - tm->tm_sec;
X	sleep(delta);	/* wait for nearest minute to stab RTC */
X	
X	clock += delta;
X	tm = localtime(&clock);	/* catch any date changes, TZ, etc. */
X	
X	sprintf(dateline, "date %.02d%.02d%.02d%.02d%.02d >/dev/null",
X		tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_year);
X	
X	system(dateline);
X#endif	/* unknown hardware */
X
X
X#if mc68k || i386	/* Routine common to Convergent Systems */
X
X		printf("Setting system clock to %s", ctime(&clock));
X	if (syslocal(SYSL_WTRTC, &rtc))	perror("Write Real Time Clock");
X
X	utmp[0].ut_time = time(0);
X	if (stime(&clock)) {
X		perror("Set system time");
X	} else {
X		utmp[1].ut_time = clock;
X		utmp[0].ut_pid = utmp[1].ut_pid = getpid();
X		pututline(&utmp[0]);
X		pututline(&utmp[1]);
X		if ((fd_wtmp = open(WTMP_FILE, O_WRONLY|O_APPEND)) >0){
X			(void) write(fd_wtmp, (char *)utmp, sizeof(utmp));
X		}
X	}
X
X#endif	/* either of the Convergent Systems */
X
X}
SHAR_EOF
if test 5063 -ne "`wc -c < 'remtime.c'`"
then
  echo shar: "error transmitting 'remtime.c'" '(should have been 5063 characters)'
fi
fi
exit 0
# End of shell archive
-- 
---
Clarence A Dold - dold@tsmiti.Convergent.COM
               ...pyramid!ctnews!tsmiti!dold

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.