Thread View: aus.sources
7 messages
7 total messages
Started by Michael Henning
Tue, 22 Dec 1992 04:11
AOTC atomic clock
Author: Michael Henning
Date: Tue, 22 Dec 1992 04:11
Date: Tue, 22 Dec 1992 04:11
509 lines
14097 bytes
14097 bytes
I've just written a hack to automatically set the system time on our
machine from AOTC's atomic clock. For those who don't know, AOTC offer
a time service at 1200 Baud. The number for Brisbane is (07) 221-7033.
I don't know about other cities, but I guess directory assistance
may be able to help.
I am using the MHSnet VCcall program to invoke the code that
sets the system time (details below).
If you don't have MHSnet, ACSnet will work if you write yourself
a call script that invokes the setclock program.
If you can get your UUCP to invoke a program from a chat script,
you should be able to use that too.
Anyway, below is some code that can set the time for you. I've included
some explanations for how to configure it into MHSnet. You should be
able to get going with that. The usual disclaimers apply. If my code
sets your machine on fire - tough luck.
The whole process from matching the date string (at 1200 Baud) to finally
setting the system clock takes less than 0.75 seconds on our machine.
For our purposes, that is accurate enough.
Cheers,
Michi.
To get MHSnet to make the call for you, you need a link for which to
establish a call. The easiest way to do this is to add a pseudo host
and create a link to it. The following entries in _state/commandsfile
do just that.
#
# Pseudo host to use the MHSnet modem dialer to set the time of day.
#
add N=setclock.O=ptcbu.P=oz.C=au
link N=ptcburp.O=ptcbu.P=oz.C=au,
N=setclock.O=ptcbu.P=oz.C=au
+foreign,+nochange,+dead
linkname N=setclock.O=ptcbu.P=oz.C=au
setclock
The host is called "setclock" and placed into the local domain. The
+foreign,+nochange,+dead flags prevent any messages from being sent
to that host. Please use your machine and domain to do this, not
ptcburp.ptcbu.oz.au :-)
Do a "netstate -wrsxC" after changing your commandsfile.
Next, add an entry to _lib/initfile:
call-setclock.ptcbu.oz.au "49 8 * * 1" setclock/call
This tries to establish a connection to the setclock host once a week.
In $SPOOLDIR, create a directory "setclock", owned by daemon, group daemon,
with permissions 750.
Create a file called "call", owned by daemon, group daemon, with
permissions 750. It contains the following script:
#!/bin/sh
DEVICE=/dev/term/0
TRACE=0
if [ "$TRACE" -gt 0 ]
then
mdmtrace='M1S61=255' # Switch speaker on
else
mdmtrace='M0' # Be silent
fi
/usr/spool/MHSnet/_lib/VCcall \
-T${TRACE} \
-v \
-D "dialstr=AT${mdmtrace}S50=3DT0,07,2217033" \
-D "linespeed=19200" \
-D "modemdev=$DEVICE" \
-D "timecmd=/usr/local/bin/setclock" \
-S setclock.cs \
-X /usr/spool/MHSnet/setclock/call.log \
setclock.ptcbu.oz.au
exit $?
This simply invokes VCcall with the appropriate arguments.
The dial string here is for a Trailblazer, so you need to adjust it if
you have a different modem.
The call script that calls the clock server and picks out the date
string goes into _call/setclock.cs. I modified one of the generic
call scripts which come with MHSnet to invoke a program to set the date.
/*
** Call script to set the system time.
**
** Imports:
** dialstr string to cause modem to dial remote site
** linespeed speed for modemdev
** modemdev device attached to modem
** timecmd command to set time
*/
set dialcount 6; /* dial attempts */
set timecount 10; /* number of tries at reading time */
/*
** Check imported strings.
*/
chkargs:
match dialstr UNDEFINED paramerr;
match linespeed UNDEFINED paramerr;
match modemdev UNDEFINED paramerr;
start1:
timeout 60; /* Wait 1 minute between/for open attempts */
retry 60; /* Allow 60 attempts at open => 1 hour max */
open "dial" modemdev "uucplock" "ondelay" "local"; /* Open with O_NDELAY */
match RESULT DEVOK openok;
set reason "Could not open \"" modemdev "\" reason: " RESULT;
openfail:
fail reason;
paramerr:
fail "missing some of:\n"
"\t-D \"dialstr=<ATD command for modem>\"\n"
"\t-D \"linespeed=<bits/second>\"\n"
"\t-D \"modemdev=<device pathname for modem>\""
;
openok:
device "offdelay"; /* Otherwise reads will return 0 */
device "speed" linespeed;
monitor 0; /* Turn on I/O tracing */
sleep 1; /* Because some terminal i/o is slow! */
write "AT\r"; /* Make sure modem latches on */
sleep 1;
write "AT\r";
sleep 1;
write "AT\r";
sleep 1;
device "flush";
write "ATZ\r";
timeout 10;
expect
"OK" try_initstr,
EOF eof,
TERMINATE terminate,
TIMEOUT rstmodem;
rstmodem:
sleep 2;
write "+++";
clrmodem:
sleep 2;
write "ATZ\r";
timeout 10;
expect
"OK" try_initstr,
EOF eof,
TERMINATE terminate,
TIMEOUT nomodem;
try_initstr:
match initstr UNDEFINED dialing;
timeout 0;
sleep 1;
write initstr "\r";
timeout 10;
expect
"OK" dialing,
EOF eof,
TERMINATE terminate,
TIMEOUT dialing;
nomodem:
set reason "modem \"" modemdev "\" not responding";
next nextmodem;
dialing:
test dialcount dfail;
timeout 0;
sleep 1;
write dialstr "\r";
timeout 60;
expect
"BUSY" busy,
"NO ANSWER" busy,
"NO CARRIER" clrmodem,
"NO DIALTONE" nodial,
"CONNECT 2400" gettime,
"CONNECT 1200" gettime,
"CONNECT" gettime,
EOF eof,
TERMINATE terminate,
TIMEOUT rstmodem;
busy:
trace "number \"" dialstr "\" busy";
sleep 30; /* Give them time to get off the phone */
next clrmodem;
gettime:
set DELIMCHARS "\n\r";
timeout 4;
try_again:
test timecount no_time;
device "flush";
expect
"[12][0-9][0-9][0-9]-[01][0-9]-[0-3][0-9][ ][0-2][0-9]:[0-5][0-9]:[0-5][0-9]\*" settime,
TIMEOUT try_again,
TERMINATE terminate,
EOF endmodem2;
settime:
shell timecmd " '"INPUT"'";
match RESULT "0" endmodem;
match RESULT "1" bad_format;
match RESULT "2" bad_date;
match RESULT "3" too_large;
match RESULT "4" stime_failed;
set reason timecmd " '"INPUT"' returned weird exit status: " RESULT;
endmodem:
device "local"; /* Ignore modem signals */
sleep 2;
device "flush";
write "+++";
timeout 3;
expect
"NO CARRIER" endmodem1,
"OK" endmodem1,
EOF endmodem2,
TERMINATE endmodem0,
TIMEOUT endmodem1;
endmodem0:
sleep 2;
endmodem1:
write "ATH0Z\r";
timeout 2;
expect
"OK" endmodem2,
EOF endmodem2,
TERMINATE endmodem2,
TIMEOUT endmodem2;
endmodem2:
match finishstr UNDEFINED endmodem3;
timeout 0;
write finishstr "\r";
sleep 1;
endmodem3:
match reason UNDEFINED out;
fail reason;
out:
return;
dfail:
set reason "too many dial attempts";
next endmodem;
eof:
set reason "remote disconnect";
next endmodem;
nodial:
set reason "modem \"" modemdev "\" has no dialtone";
match modemdev2 UNDEFINED endmodem;
next nextmodem;
terminate:
set reason "system termination";
next endmodem;
no_time:
set reason "cannot get time from connection";
next endmodem;
bad_format:
set reason timecmd " '"INPUT"': bad format";
next endmodem;
bad_date:
set reason timecmd " '"INPUT"': meaningless date";
next endmodem;
too_large:
set reason timecmd " '"INPUT"': time difference too large";
next endmodem;
stime_failed:
set reason timecmd " '"INPUT"': stime(2) call failed";
next endmodem;
Finally, you need to compile and install the code below (set-uid root).
It sets the new date after doing some sanity checks. I added a limit
to prevent the system time being changed by more than 300 seconds.
I figure if my clock is wrong by as much as that, I'd like to know why :-)
If you don't call the program /usr/local/bin/setclock, remember to
change the path passed to the call script from setclock/call.
/*
* setclock - set the system time using AOTC's atomic clock service.
*
* This program is meant to be invoked from a daemon which obtains
* the current date from AOTC's dial-up atomic clock. The clock produces
* lines of the form
*
* yyyy-mm-dd hh:mm:ss[*#]
*
* The output from the dial-up clock looks like
*
* 1992-12-10 10:01:40*
* 1992-12-10 10:01:41*
* 1992-12-10 10:01:42*
* 1992-12-10 10:01:43*
* 1992-12-10 10:01:44*
*
* Each line is printed up to the '*', followed by a brief pause,
* followed by the '*', CR and LF. The exact mark for the time is
* the stop-bit/start-bit transition between the CR and LF.
*
* For daylight saving time, the '*' is replaced by a '#'.
*
* The single argument must be one complete line. Any trailing characters
* (such as CR/LF) after the '*' or '#' are ignored.
*
* The argument is broken into its components, sanity checked and
* converted into seconds since The Epoch. If the resulting time does
* not differ from the current system time by more than MAX_ADJ seconds,
* the system clock is set to the new time.
*
* This program must be set-uid root, and should be installed with
* permissions 4710, owner root, group daemon.
*/
/*****************************************************************************/
#include <stdlib.h>
#include <unistd.h>
#include <libgen.h>
#include <string.h>
#include <time.h>
/*****************************************************************************/
#define FORMAT "yyyy-mm-dd hh:mm:ss" /* Format of input date */
#define USAGE "Usage: %s \"%s[*#]\"\n" /* Usage message */
#define MAX_ADJ 300 /* Max adjust in seconds */
#define OK 0 /* Exit status if OK */
#define BAD_FORM 1 /* Bad format of argument */
#define BAD_DATE 2 /* Meaningless date */
#define TOO_LARGE 3 /* MAX_ADJ exceeded */
#define BAD_STIME 4 /* stime(2) failed */
/*****************************************************************************/
static const char *progname; /* For error messages */
/*****************************************************************************/
/*
* Print usage message and exit. If the given date is non-NULL,
* also complain about an invalid date, showing the invalid string.
*/
static void
usage(int status, const char *date)
{
if (date != NULL) {
(void) fprintf(
stderr, "%s: invalid date: \"%s\"\n", progname, date
);
}
(void) fprintf(stderr, USAGE, progname, FORMAT);
exit(status);
}
/*****************************************************************************/
int
main(int argc, char *argv[])
{
char buf[sizeof(FORMAT) + 1]; /* +1 for '*' or '#' */
char *year;
char *month;
char *day;
char *hour;
char *minute;
char *second;
struct tm stm;
time_t new_time;
/*
* Set program name for error messages.
*/
progname = basename(argv[0]);
/*
* Check usage.
*/
if (argc != 2)
usage(BAD_FORM, NULL);
/*
* Get rid of any trailing garbage in argument (the AOTC atomic
* clock service terminates each line with CR/LF). We clean this
* up in argv[1] instead of a copy of it, so we can print nicer
* error messages (without any trailing newline).
*/
/* LINTED */
if (strlen(argv[1]) < strlen(FORMAT) + 1)
usage(BAD_FORM, argv[1]);
argv[1][strlen(FORMAT) + 1] = '\0';
/*
* Break up the date into components.
*/
(void) strncpy(buf, argv[1], strlen(FORMAT) + 1);
year = buf;
if ((month = strchr(year, '-')) == NULL)
usage(BAD_FORM, argv[1]);
*month++ = '\0';
if ((day = strchr(month, '-')) == NULL)
usage(BAD_FORM, argv[1]);
*day++ = '\0';
if ((hour = strchr(day, ' ')) == NULL)
usage(BAD_FORM, argv[1]);
*hour++ = '\0';
if ((minute = strchr(hour, ':')) == NULL)
usage(BAD_FORM, argv[1]);
*minute++ = '\0';
if ((second = strchr(minute, ':')) == NULL)
usage(BAD_FORM, argv[1]);
*second++ = '\0';
/*
* Check fields for validity and build struct tm.
*/
if (second[2] != '*' && second[2] != '#')
usage(BAD_FORM, argv[1]);
stm.tm_isdst = second[2] == '#';
second[2] = '\0';
stm.tm_year = atoi(year);
if (stm.tm_year < 1900)
usage(BAD_DATE, argv[1]);
stm.tm_year -= 1900; /* Origin is the year 1900 */
stm.tm_mon = atoi(month);
if (stm.tm_mon < 1 || stm.tm_mon > 12)
usage(BAD_DATE, argv[1]);
stm.tm_mon--; /* Origin is 0 (January) */
stm.tm_mday = atoi(day);
if (stm.tm_mday < 1 || stm.tm_mday > 31)
usage(BAD_DATE, argv[1]);
stm.tm_hour = atoi(hour);
if (stm.tm_hour < 0 || stm.tm_hour > 23)
usage(BAD_DATE, argv[1]);
stm.tm_min = atoi(minute);
if (stm.tm_min < 0 || stm.tm_min > 59)
usage(BAD_DATE, argv[1]);
stm.tm_sec = atoi(second);
if (stm.tm_sec < 0 || stm.tm_sec > 59)
usage(BAD_DATE, argv[1]);
/*
* Convert time to seconds since The Epoch.
*/
if ((new_time = mktime(&stm)) == -1)
usage(BAD_DATE, argv[1]);
/*
* Don't allow adjustment of time by more than MAX_ADJ seconds.
*/
if (abs(time(NULL) - new_time) > MAX_ADJ) {
(void) fprintf(
stderr,
"%s: will not adjust time by more than %d seconds\n",
progname, MAX_ADJ
);
exit(TOO_LARGE);
}
/*
* Set the system time.
*/
if (stime(&new_time) == -1) {
extern int errno;
(void) fprintf(
stderr, "%s: cannot set time: %s\n",
progname, strerror(errno)
);
exit(BAD_STIME);
}
/*
* Done.
*/
exit(OK);
/* NOTREACHED */
}
--
-m------- Michael Henning +61 75 950255
---mmm----- Pyramid Technology +61 75 722475 FAX
-----mmmmm--- Research Park, Bond University michi@ptcburp.ptcbu.oz.au
-------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA uunet!munnari!ptcburp.oz!michi
Re: AOTC atomic clock
Author: George Michaelson
Date: Tue, 22 Dec 1992 05:38
Date: Tue, 22 Dec 1992 05:38
19 lines
1516 bytes
1516 bytes
michi@ptcburp.ptcbu.oz.au (Michael Henning) writes:
>I've just written a hack to automatically set the system time on our
>machine from AOTC's atomic clock. For those who don't know, AOTC offer
>a time service at 1200 Baud. The number for Brisbane is (07) 221-7033.
>I don't know about other cities, but I guess directory assistance
>may be able to help.
I would be interested in knowing if anybody in AARNet already does
this who is in the global xntp framework. If so, how does it affect
clockdrift, and are you recognized as a stratum-1 time server?
-George
--
George Michaelson
G.Michaelson@cc.uq.oz.au The Prentice Centre | There's no market for
University of Queensland | hippos in Philadelphia
Phone: +61 7 365 4079 QLD Australia 4072 | -Bertold Brecht
Re: AOTC atomic clock
Author: David J. Hughes
Date: Wed, 23 Dec 1992 03:52
Date: Wed, 23 Dec 1992 03:52
16 lines
1144 bytes
1144 bytes
ggm@brolga.cc.uq.oz.au (George Michaelson) writes: >I would be interested in knowing if anybody in AARNet already does >this who is in the global xntp framework. If so, how does it affect >clockdrift, and are you recognized as a stratum-1 time server? I'm not up on the official requirements for designation as a stratum-1 host, but I'd assume that a lapse of approx 0.75 seconds (plus tran's time for the text data over the modem etc) wouldn't be seens as accurate enough. Any more reasonable prognosis (MarkP)? bambi ...
Re: AOTC atomic clock
Author: Michael Henning
Date: Wed, 23 Dec 1992 04:06
Date: Wed, 23 Dec 1992 04:06
19 lines
1578 bytes
1578 bytes
bambi@bu.oz.au (David J. Hughes) writes:
>I'm not up on the official requirements for designation as a stratum-1
>host, but I'd assume that a lapse of approx 0.75 seconds (plus tran's
>time for the text data over the modem etc) wouldn't be seens as accurate
>enough.
Just to clarify a bit. When I use my code to set the system clock,
the system time afterwards is within ~ 0.75 seconds of the real time.
This is a worst case. If the machine isn't heavily loaded at the time
the code runs, the system clock is set so close to the real time that I cannot
tell the difference (by eye).
Michi.
--
-m------- Michael Henning +61 75 950255
---mmm----- Pyramid Technology +61 75 722475 FAX
-----mmmmm--- Research Park, Bond University michi@ptcburp.ptcbu.oz.au
-------mmmmmmm- Gold Coast, Q 4229, AUSTRALIA uunet!munnari!ptcburp.oz!michi
Re: AOTC atomic clock
Author: Steve Balogh
Date: Wed, 23 Dec 1992 04:43
Date: Wed, 23 Dec 1992 04:43
23 lines
1432 bytes
1432 bytes
In article <1992Dec22.041148.24383@ptcburp.ptcbu.oz.au> michi@ptcburp.ptcbu.oz.au (Michael Henning) writes:
>
>I've just written a hack to automatically set the system time on our
>machine from AOTC's atomic clock. For those who don't know, AOTC offer
>a time service at 1200 Baud. The number for Brisbane is (07) 221-7033.
>I don't know about other cities, but I guess directory assistance
>may be able to help.
>
Melbourne 03 600 1641
Sydney 02 267 4648
Regards,
Steve
----_--_-_-_--_-__-_------_-__---_-___-_----_-____-_-_--__-_--_--___-_-_-_--__-_
Steve Balogh VK3YMY (Maths G.14) | steve@monu6.cc.monash.edu.au
Monash University, Clayton Campus | 37 54'38.8"S 145 07'47.1"E ...ICBM
Wellington Road, Clayton. | +61 3 565 4747 Voice (Office)
Melbourne, AUSTRALIA. 3168 | +61 3 565 4746 Fax
Re: AOTC atomic clock
Author: Gary Evesson
Date: Thu, 24 Dec 1992 01:25
Date: Thu, 24 Dec 1992 01:25
9 lines
1174 bytes
1174 bytes
(Ignore the From line, this message is from Andrew McNamara) >>For those who don't know, AOTC offer >>a time service at 1200 Baud. The number for Brisbane is (07) 221-7033. I'm curious. What _does_ AOTC use the clock for themselves? Do they have more than one (one in each city), or are they all derived from the one source? If so, why does it need to be theirs - couldn't CSIRO or someone provide it for them?
Re: AOTC atomic clock
Author: Brian Evans
Date: Sun, 27 Dec 1992 02:43
Date: Sun, 27 Dec 1992 02:43
16 lines
1301 bytes
1301 bytes
kcs@extro.ucc.su.OZ.AU (Gary Evesson) writes: >I'm curious. What _does_ AOTC use the clock for themselves? Do they have I believe that they use the clock to maintain time on their systems such as the keylink email service. I guess that they would also use it in DDN (Digital Data Network) for clocking the sync. links around the country. Also they sell the service to banks etc. >more than one (one in each city), or are they all derived from the one >source? The one source I think. I believe it is actually in TRL ( telecom research labs ) in Melbourne. Brian Evans
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads