Time Services from the U.S. Naval Observatory
Stephen Friedl and Ed Schaefer
As a system administrator one of your many tasks is
setting the system
time. To automate this task, a client machine could
call a remote
(or server) system, obtain the time from the server,
and arbitrarily
set the time on the client. This article addresses a
C utility, utc
(Listing 1), which calls the U.S. Naval Observatory
(USNO), in Washington
D.C. (1-202-653-0351), to obtain as accurate a time
as is available
anywhere.
The USNO Time Format
The USNO provides time data once per second in the format
shown in
Figure 1. The Julian Date measures the number of days
since Greenwich
mean noon 1 January 4713 B.C. on the Julian proleptic
calendar. This
corresponds to the period of the earliest known astronomical
observations
and forms a common starting point for numerous time
and date systems.
The Modified Julian Date (MJD) provided by the Observatory
is the
JD minus 240000.5 (the ".5" shifts the start
of a measured
day from noon to midnight). Since both UNIX and USNO
keep time using
Greenwich Mean Time (GMT), time zones are eliminated.
The Systems File
Since this utility uses the ubiquitous Call UNIX utility,
cu,
you first set up the UNIX Systems file for the USNO
site name
and a speed of 1200 bits per second:
usno Nvr ACU 1200 1-202-653-0351
This entry attaches a phone number and speed to a system
name -- the typical login information is not required
since uucp
won't be using this. Speeds above 1200 bits per second
are not supported;
they would be counterproductive in any case because
of the increased
delays inherent in the way commonly used error control
protocols are
packed.
The utc Utility Options
The options for utc are:
-s-- specify to set system time via stime()
(root only)
-c sysn -- specify system name to dial via
Systems file (usno in our definition)
-D nn -- specify debug level
-d -- don't route cu's stderr
to /dev/null (for debug)
If no options are specified, no cu is spawned and the
time
is printed internally in the USNO minute format.
Executing the cu Command
The heart of the utc utility is creating a pipe between
the
cu command and the shell, using the popen() function
call. (For more information on programming the pipe,
see "Using
the UNIX Pipe in C," Sys Admin, July/August 1993).
The
cu command is actually piped in the cu_open() function
and a FILE pointer is returned to the calling set_time()
function. After cu connects, the routine reads output
from
USNO using the normal stream reading function, fgets().
cu_open() also makes the utc utility a process group
leader via the setpgrp() function call. Since cu typically
spawns an extra process (one for reading, one for writing),
having
a self-contained process group makes it easier to terminate
all processes
involved in setting the time should this be necessary.
(Check the
implementation of setpgrp() on your system -- some UNIX
variants use setsid().)
Parsing the USNO Output String
After the connection is made to USNO, the convert_to_time()
function parses the line from USNO format and returns
the UNIX time,
defined as the number of seconds since midnight 01/01/1970.
convert_to_time()
returns 0 for the marker and an error if the five expected
fields can not be parsed. utc assumes the UNIX time
is correct
when five valid times are received sequentially, each
being one second
greater than the prior time. The marker line is ignored
in the count
and is not considered an error condition.
Terminating utc
The alarm() function is set so that utc will terminate
within 60 seconds if no valid input is received. If
USNO delivered
a valid UNIX time, utc kills the cu child processes
with the kill() function, and closes the USNO pipe using
pclose().
Finally, if the set-system-time option is on, the system
time
is set to the time received from USNO. Before calling
setime(),
however, utc compares the old system time to the new
time.
The most obvious error condition is a user other than
root attempting
to set the system time.
Future Enhancements
The utc utility obtains the GMT time from the USNO
and optionally sets system time, but the error checking
is limited.
A time-range-check-in-hours option could prove useful
(e.g., don't
change the time if the proposed change from USNO is
more than a certain
number of minutes or hours).
Also, a clever system administrator could set the utc
utility
up as part of a timeserver account for others to use,
thus eliminating
the need for a long-distance telephone call to Washington,
D.C.
References
Curry, David A. Using C on the UNIX System.
Sebastopol, CA: O'Reilly & Associates, 1989.
About the Authors
Stephen Friedl is an independent software and network
consultant
in Tustin, California, and has been working with C and
UNIX since
his first exposure on a Z8000 machine in 1981. He develops
UNIX facsimile
software, does training and system administration, and
is a volunteer
tutor of English as a second language to a cool group
of students.
He can be reached via email at friedl@mtndew.com.
Ed Schaefer is a frequent contributer to Sys Admin.
He is an Informix software developer and UNIX system
administrator at jeTECH Data Systems of Moorpark, CA,
where he develops
Time and Attendance Software. He can be reached at olded@ix.netcom.com.
|