Cover V04, I04
Figure 1
Listing 1
Sidebar 1


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.


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

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