Tools for people using software clocks only with xntp.

George Baily billd at fps.com
Sat Jun 22 12:03:35 AEST 1991


This is an updated version of my tools for people using software only
clocks with xntp.  Against my better judgement, I'm cross-posting to
alt.sources thinking that maybe some people who might like these might
not read comp.protocols.time.ntp.  Probably not but who knows?

If the next paragraph makes no sense to you, go on to the README below.

In any case, I've made a few improvements on these fairly trivial
programs.  tclock is quite a lot more efficient in terms of the use of
system resources.  I got rid of a lot of unneccessary system calls.
The default output format is different but 4 formats are now available
via command line switches.  adjtime can now optionally wait for the
adjustment to finish and it prints out the pending adjustment once
per second while it waits.  doadj makes use of this and also now
puts the old value of tickadj back rather than wimping out and doing
a tickadj -A.

I made these things for myself and didn't really intend them for
distribution so they are fairly hacked looking.  I did try to clean
them up a little more this time but they are still fairly rough.
Fortunately, they are trivial enough that it doesn't really matter
that much.

Enjoy.

** README ********************************************************

These programs are crude hacks but they make working with a software
reference clock with no good hardware reference clock available a
little easier.

I try to synchronize my time with the phone company time recording.  To
do this, I first run "tclock" which stands for "text clock" which
prints out the current time constantly in one of the following forms:
-h: "\rHH:MM:SS.FF", -m "\rMM:SS.FF", -s "\rSS.FF", or -d (default)
"\rSS.F".  I currently have it set to print out every 0.1 seconds.  I
figure I can see the difference between times that are about .1 or .2
off from each other so this is about as good as it gets when doing this
stuff by hand.  Anyway, I call the "time" number and watch the running
tclock and try to guess how far off it is from the phone company time.

After making a guess I then want to adjust it.  "date(1)" is a pain.
There is a variable delay between the time you hit return and the time
that the clock is actually set.  So I've written a program called
"adjtime" which is simply a shell level access program to the
adjtime(2) system call.  It takes as it's parameter a single floating
point number of the amount of seconds to adjust by.  If you have your
tickadj variable set to a small value (as ntp documentation always
recomends), it will take a hell of a long time to make up differences
large enough for humans to distinguish.  For that reason, I've made a
script called "doadj" which does a tickadj to make tickadj 10% of tick
(normal default) while it runs adjtime.  It then waits an appropriate
amount of time for the tickadj to finish and runs "tickadj -a" to set
things back to normal.  You may not want to have (x)ntpd running when
you do this since it might do it's own adjtime and wipe you out.  If
you leave it running and the time doesn't get adjusted, that's probably
what happened.  Just do it again.  Adjtime can optionally take a "-w"
flag which causes it to wait for the comepensation to finish before it
exits and print out how much compensation is left once per second.
This is a pacifier that I find I need.

READ AND UNDERSTAND THE doadj SCRIPT BEFORE YOU RUN IT!
It may need modification for your system.

Now you can run tclock again and call the "time" number again to see
how close you are.  You may need to adjust again.

If you keep track of how much you have to adjust over given time
periods you can guess a good value for the drift compensation
register.  If you are using the software pseudo-clock from xntp, you
can use this value for your fudge time1 value.  You can refine it
over longer and longer test periods as you keep using it.

This stuff was written on and is used on BSD systems.  I don't know if
tclock will run on System V since I don't know if System V has
setitimer(2) or some of the signal stuff.  I don't care to port it and
I won't support it.  You're on your own.

Usual disclaimers: Run this stuff at your own risk.  Neither I nor my
company are willing to take repsonsibility for this and in fact this
whole posting could be a forgery made it look like it came from
billd at fps.com so you'll have a hell of a time proving that I posted
it.  So there.

--Bill Davidson billd at fps.com 6/21/91

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  README Makefile adjtime.c tclock.c doadj.sh
# Wrapped by billd at celit on Mon May 20 20:26:18 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(2559 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
XThese programs are crude hacks but they make working with a software
Xreference clock with no good hardware reference clock available a
Xlittle easier.
X
XI try to synchronize my time with the phone company time recording.  To
Xdo this, I first run "tclock" which stands for "text clock" which
Xprints out the current time constantly in the form "\rHH:MM:SS.FF".  I
Xcurrently have it set to print out every 0.1 seconds.  I figure I can
Xsee the difference between times that are about .2 off from each other
Xso this is about as good as it gets when doing this stuff by hand.
XAnyway, I call the "time" number and watch the running tclock and try
Xto guess how far off it is from the phone company time.
X
XAfter making a guess I then want to adjust it.  "date(1)" is a pain.
XThere is a variable delay between the time you hit return and the time
Xthat the clock is actually set.  So I've written a program called
X"adjtime" which is simply a shell level access program to the
Xadjtime(2) system call.  It takes as it's parameter a single floating
Xpoint number of the amount of seconds to adjust by.  If you have your
Xtickadj variable set to a small value (as ntp documentation always
Xrecomends), it will take a hell of a long time to make up differences
Xlarge enough for humans to distinguish.  For that reason, I've made a
Xscript called "doadj" which does a tickadj to make tickadj 10% of tick
X(normal default) while it runs adjtime.  It then waits an appropriate
Xamount of time for the tickadj to finish and runs "tickadj -A" to set
Xthings back to normal.  You may not want to have (x)ntpd running when
Xyou do this since it might do it's own adjtime and wipe you out.  If
Xyou leave it running and the time doesn't get adjusted, that's probably
Xwhat happened.  Just do it again.
X
XREAD AND UNDERSTAND THE doadj SCRIPT BEFORE YOU RUN IT!
XIt may need modification for your system.
X
XNow you can run tclock again and call the "time" number again to see
Xhow close you are.  You may need to adjust again.
X
XThis stuff was written on and is used on BSD systems.  I don't know if
Xtclock will run on System V since I don't know if System V has
Xsetitimer(2) or some of the signal stuff.  I don't care to port it and
XI won't support it.  You're on your own.
X
XUsual disclaimers: Run this stuff at your own risk.  Neither I nor my
Xcompany are willing to take repsonsibility for this and in fact this
Xwhole posting could be a forgery made it look like it came from
Xbilld at fps.com so you'll have a hell of a time proving that I posted
Xit.  So there.
X
X--Bill Davidson billd at fps.com 5/20/91
END_OF_FILE
if test 2559 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(368 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X# quick hack Makefile
X#
X
XCFLAGS=		-O
XPROGRAMS=	adjtime tclock doadj
XFILES=		README Makefile adjtime.c tclock.c doadj.sh
X
Xall: $(PROGRAMS)
X
Xadjtime: adjtime.o
X	$(CC) $(CFLAGS) -o $@ $@.o
X
Xtclock: tclock.o
X	$(CC) $(CFLAGS) -o $@ $@.o
X
Xdoadj: doadj.sh
X	cp $@.sh $@
X	chmod +x $@
X
Xclean:
X	rm -f $(PROGRAMS) *.o
X
Xsoftclock.shar: $(FILES)
X	shar -o softclock.shar $(FILES)
X
END_OF_FILE
if test 368 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'adjtime.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'adjtime.c'\"
else
echo shar: Extracting \"'adjtime.c'\" \(1799 characters\)
sed "s/^X//" >'adjtime.c' <<'END_OF_FILE'
X/******************************************************************************
X*
X*	ADJTIME - Apply the adjtime call with the value on the command
X*	line.  Reports value of pending adjtime which you just wiped
X*	out (see adjtime(2)).  Takes only one parameter: a floating
X*	point number which is the number of seconds to adjust by.
X*	Positive numbers speed up the clock, negative numbers slow
X*	it down.
X*
X*	This program must be run by root to have any effect.
X*
X*	You probably want to have tickadj set to a large value, say
X*	tick/10 (normal value).  If you have a small value for ntp,
X*	you may want to temporarily run "tickadj -a 1000" before
X*	running adjtime and "tickadj -A" after running adjtime and
X*	after the clock has come into the value you want.
X*
X*	This program makes it a little easier to get the system clock
X*	set to the proper time in the face of delays running date(1).
X*
X******************************************************************************/
X
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/time.h>
X
Xdouble atof();
Xvoid doadjtime();
X
X#define issign(x)	(((x)=='-')||((x)=='+'))
X
Xvoid main( argc, argv )
Xint	argc;
Xchar	*argv[];
X{
X    double diff;
X    char *val;
X
X    if ( argc < 2 )
X	usage();
X    val = argv[1];
X    if ( isdigit(val[0]) || ( isdigit(val[1]) && issign(val[0]) ) ){
X	diff = atof(argv[1]);
X	doadjtime(diff);
X    }else
X	usage();
X}
X
Xint usage()
X{
X    fprintf(stderr,"usage: adjtime seconds\n");
X    exit(-1);
X}
X
Xvoid doadjtime(diff)
Xdouble	diff;
X{
X    struct timeval tp, otp;
X
X    tp.tv_sec = (long)diff;
X    tp.tv_usec = (long)(1000000 * (diff - tp.tv_sec));
X    printf("adjusting %ld seconds, %ld useconds\n",tp.tv_sec,tp.tv_usec);
X    if ( adjtime( &tp, &otp ) ){
X	perror("adjtime");
X	exit(-1);
X    }else
X	printf("%ld %ld\n",otp.tv_sec,otp.tv_usec);
X}
X
END_OF_FILE
if test 1799 -ne `wc -c <'adjtime.c'`; then
    echo shar: \"'adjtime.c'\" unpacked with wrong size!
fi
# end of 'adjtime.c'
fi
if test -f 'tclock.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tclock.c'\"
else
echo shar: Extracting \"'tclock.c'\" \(2924 characters\)
sed "s/^X//" >'tclock.c' <<'END_OF_FILE'
X/******************************************************************************
X*
X*	TCLOCK - This program prints a text clock.  It tries to do it
X*	ten times per second.  It prints out accurate to 1/100th of
X*	a second.  Quit with SIGINT (usually control-C).
X*
X*	Needed Library Routines:
X*
X*		gettimeofday(2)
X*		setitimer(2)
X*		sigpause(2)
X*		sigsetmask(2)
X*
X*		exit(3)
X*		fflush(3)
X*		localtime(3)
X*		printf(3)
X*		signal(3)
X*
X******************************************************************************/
X
X#include <stdio.h>
X#include <sys/time.h>
X#include <sys/signal.h>
X
X/* set FREQ to the number of microseconds to sleep between printouts
X   I try to get it so that it prints out every 0.1 seconds.  Due to
X   program overhead and resource sharing, this is usually a bit less
X   than 100000 microseconds (=0.1 seconds).  If you get it right, the
X   hundredths place will stay constant. */
X
X#define	FREQ	99990
X
Xvoid fsleep();
X
X/* cheap signal handler */
Xint
Xhandler()
X{
X    printf("\n");
X    exit(0);
X}
X
X/******************************************************************************
X*
X*	Main program.
X*		Just an infinite loop getting and printing out the time.
X*		Sets up a signal handler to abort on SIGINT or SIGTERM.
X*
X*	Library routines:
X*		gettimeofday(2)
X*		fflush(3)
X*		localtime(3)
X*		printf(3)
X*		signal(3)
X*
X******************************************************************************/
Xvoid
Xmain()
X{
X    struct tm *tp;
X    struct timeval tv;
X    struct timezone tz;
X
X    signal( SIGINT, handler );
X    signal( SIGTERM, handler );
X    while ( 1 ){
X	gettimeofday( &tv, &tz );
X	tp = localtime(&tv.tv_sec);
X	printf("\r%02d:%02d:%02d.%02d", tp->tm_hour, tp->tm_min, tp->tm_sec,
X							tv.tv_usec/10000 );
X	fflush(stdout);
X	fsleep( (unsigned long)0, (unsigned long)FREQ );
X    }
X}
X
Xstatic void
Xfsleeptrap()
X{
X	/* Zen function */
X}
X
X/******************************************************************************
X*
X*	FSLEEP - Fine sleep function; sleeps at resolution of the
X*	interval timer (see setitimer(2)) or microseconds; whichever
X*	is worse.
X*
X*	Library routines:
X*		setitimer(2)
X*		sigpause(2)
X*		sigsetmask(2)
X*		signal(3)
X*
X******************************************************************************/
Xvoid
Xfsleep( secs, usecs )
Xunsigned long secs, usecs;
X{
X    int  omask, (*osig)();
X    struct itimerval tval[2];
X
X	/* setup */
X    osig = signal( SIGALRM, fsleeptrap );
X
X    if ( usecs >= 1000000L ){
X	secs += usecs / 1000000L;
X	usecs %= 1000000L;
X    }
X    tval[1].it_interval.tv_sec = 0L;
X    tval[1].it_interval.tv_usec = 0L;
X    tval[1].it_value.tv_sec = secs;
X    tval[1].it_value.tv_usec = usecs;
X
X	/* more setup */
X    omask = sigsetmask( ( 1 << (SIGALRM-1) ) );
X    setitimer( ITIMER_REAL, &tval[1], &tval[0] );
X
X	/* wait for interrupt */
X    sigpause( 0 );
X
X	/* cleanup */
X    signal( SIGALRM, osig );
X    setitimer( ITIMER_REAL, &tval[0], &tval[1] );
X    sigsetmask( omask );
X
X    return;
X}
END_OF_FILE
if test 2924 -ne `wc -c <'tclock.c'`; then
    echo shar: \"'tclock.c'\" unpacked with wrong size!
fi
# end of 'tclock.c'
fi
if test -f 'doadj.sh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'doadj.sh'\"
else
echo shar: Extracting \"'doadj.sh'\" \(698 characters\)
sed "s/^X//" >'doadj.sh' <<'END_OF_FILE'
X#!/bin/sh -x
X#
X# This script temporarily changes tickadj and runs adjtime to fix your
X# system time.  It's only parameter is the amount of time to adjust by
X# which is passed to adjtime.
X#
X# set path so that you can find tickadj and adjtime
X#
XPATH="$PATH:/usr/local/etc"
X#
X# find tick/10 so you can make large adjustments with adjtime.
X#
Xticka=`echo tick/D |adb -k /vmunix /dev/mem |grep tick |awk '{printf("%d\n",$2/10)}'`
X#
X# set tickadj to a large value and do the adjtime.
X#
Xtickadj -a $ticka
Xadjtime $1
X#
X# sleep long enough for the adjtime to finish.
X#
Xtim=`echo $1 | awk '{s=$1;if(s<0){s=-1*s};printf("%d\n",((10*s)+0.5))}'`
Xsleep $tim
X#
X# Restore tickadj to it's proper value.
X#
Xtickadj -A
END_OF_FILE
if test 698 -ne `wc -c <'doadj.sh'`; then
    echo shar: \"'doadj.sh'\" unpacked with wrong size!
fi
# end of 'doadj.sh'
fi
echo shar: End of shell archive.
exit 0



More information about the Alt.sources mailing list