turner@ksr.com (James M. Turner) (11/06/90)
Here's a program I wrote to call the Naval Observatory and set the time. It seems to be accurate to about 50 milliseconds on a Sun 3. I know it works on SunOS 4.0.3, if people get it working on other systems, please send me the changes and I'll merge them into the sources for future releases. Instructions on compiling and using the software can be found in the source. ------------------------------ Cut Here ------------------------------ /* UTCCLOCK.C - Set time from US naval Observatory via modem Copyright (C) 1990, James M. Turner *** This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *** utcclock allows us mortals without cessium clocks and WWV radio receivers to keep our time reasonable close to UTC. Experiments on a Sun 3/60 had local time within 50 milliseconds of UTC as provided by the US Naval Observatory. Not perfect, but better than trying to set it by hand. Usage: utcclock [-S] [-s speed] [-l device] [-n number] Where speed is the baud rate to use, device is the device to call on, and number is the phone number to dial. If the -S option is used, the time will be set, otherwise only the delta difference is reported. You must be root to set the time. Because it uses the UUCP locking mechanism, it needs write permission to /usr/spool/uucp. I installed it setuid with owner = uucp on my system. If you install it setuid to root, anyone will be able to set the time. On SunOS 4.0.3, compile with: cc -O -o utcclock utcclock.c I suggest installing it in /usr/local/etc Have fun, and happy ticking. James Turner (turner@ksr.com) 617-895-9480 $Log: utcclock.c,v $ * Revision 1.4 90/11/05 16:27:56 turner * Added GPL notice * * Revision 1.3 90/11/05 16:06:06 turner * Added exclusive locking of device, better leap-year computation. * */ #include <sys/types.h> #include <sys/time.h> #include <sys/timeb.h> #include <stdio.h> #include <fcntl.h> #include <stdio.h> #include <signal.h> #include <termio.h> char version[] = "$Id: utcclock.c,v 1.4 90/11/05 16:27:56 turner Exp $"; /* PLEASE CHECK AND SET THE VALUES BELOW THIS LINE !!! */ /* Default device to use. Should be exclusive-locking if possible */ #define TTYPORT "cua0" /* Phone number to dial. Please verify that you receive tone on this number (we wouldnt want to harrass little old ladies with modem tones, now would we?) */ #define NUMBER "12026530351" /* US Naval Observatory */ /* Format of string to send to modem with number in %s */ #define DIALSTRING "ATDT%s\r" /* Default baud rate to use on line */ #define BAUDRATE B1200 /* Number of seconds of data to read */ #define NCOUNT 5 /* Locking file for UUCP. %s will be replaced by "ntp" and the device name */ #define LOCKFILE "/usr/spool/uucp/LCK..%s" /* END OF USER CONFIGURABLE SECTION */ #define FIRST_YEAR 1988 #define FIRST_VALUE 47160 /* The day value of Dec 31, FIRST_YEAR-1 */ int months[] = { 31, 28,31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; int modem; /* Device Descriptor for Modem Line */ char *timeout_reason=NULL; /* If we timeout, where are we in the code? */ char lck1[80], lck2[80]; /* This code handles the cleanup (shutting down the modem) if you abort for some reason */ void exit_handler(sig, code, scp, addr) int sig, code; struct sigcontext *scp; char *addr; { int flags = (TIOCM_DTR | TIOCM_LE); ioctl(modem, TIOCMBIC, &flags); if (sig == SIGALRM) printf("utcclock: timeout while %s\n", timeout_reason); if (timeout_reason != NULL) { unlink(lck1); unlink(lck2); } exit(0); } struct sigvec vec = { exit_handler, 0, 0}; /* Returns number of days in the given year. * Remember, a leap year is a year which is evenly divisible by 4, * but not a century, unless it is a century divisible by 400 */ static daysinyear(thisyear) int thisyear; { if ((thisyear % 4) == 0 && (((thisyear % 100) != 0) || ((thisyear % 400) == 0))) return(366); return(365); } main(argc, argv) int argc; char **argv; { extern char *optarg; extern int optind; int fd1, flags; struct sigvec ovec; struct termio tty; char c, *OptLine, *OptNumber, option, device[50]; struct tm tm; struct timeval del, del1; struct timezone tzp; struct timeb tp; time_t i; long utc_time; int hh, mm, ss, dd, yy, dummy, milli[3], m, n = 0, r, k=0, des, yydd, year, month, OptSetme = 0, OptSpeed = BAUDRATE; char buffer[80]; /* Make sure that timeouts and terminations clean up after themselves */ if (sigvec(SIGTERM, &vec, &ovec) != 0) { perror("Sigvec:"); exit(-1); } if (sigvec(SIGINT, &vec, &ovec) != 0) { perror("Sigvec:"); exit(-1); } if (sigvec(SIGALRM, &vec, &ovec) != 0) { perror("Sigvec:"); exit(-1); } OptLine = TTYPORT; OptNumber = NUMBER; /* Read in the options */ while ((option = getopt(argc, argv, "Sl:s:n:")) != -1) { switch (option) { case 'S': OptSetme = 1; break; case 'l': OptLine = optarg; break; case 'n': OptNumber = optarg; break; case 's': OptSpeed = atoi(optarg); switch (OptSpeed) { case 300: OptSpeed = B300; break; case 1200: OptSpeed = B1200; break; case 2400: OptSpeed = B2400; break; case 4800: OptSpeed = B4800; break; case 9600: OptSpeed = B9600; break; case 19200: OptSpeed = B19200; break; otherwise: fprintf(stderr, "utcclock: Illegal baud rate\n"); exit(2); } break; case '?': fprintf(stderr, "Usage: utcclock [-S] [-s speed] [-l line] [n number]\n"); exit(2); break; } } sprintf(device, "/dev/%s", OptLine); /* 60 Seconds to get the mess worked out */ alarm(60); sprintf(lck1, LOCKFILE, "ntp"); sprintf(lck2, LOCKFILE, OptLine); if ((n = open(lck1, O_CREAT|O_EXCL)) == -1) { fprintf(stderr, "utcclock: utcclock already running\n"); exit(2); } close(n); if ((m = open(lck2, O_CREAT|O_EXCL)) == -1) { fprintf(stderr, "utcclock: port in use\n"); unlink(lck1); exit(2); } close(m); timeout_reason = "opening device"; if ((modem = open(device, O_RDWR|O_NDELAY|O_EXCL)) == -1) { perror("utcclock"); exit(2); } timeout_reason = "setting line parameters"; if (ioctl(des, TCGETA, &tty) == 0) { tty.c_cflag &= ~CBAUD; tty.c_cflag |= (CLOCAL | OptSpeed); } ioctl(des, TCSETA, &tty); fcntl(modem,F_SETFL,0); /* Turn off NDELAY. */ /* Mom says we have to reopen for effect */ fd1 = open(device, O_RDWR|O_EXCL); close(modem); /* Close old line */ modem = fd1; /* dial utc */ timeout_reason = "dialing"; ioctl(modem, TCFLSH, 0); /* Flush any old characters */ sprintf(buffer, DIALSTRING, OptNumber); /* Change for non-hayes */ write(modem, buffer, strlen(buffer)); /* Now we read characters until we see the first * from the remote side. I hope your modem doesn't report messages with a * */ timeout_reason = "Looking for *"; for (n = 0, buffer[0] = ' '; (n > -1), (buffer[0] != '*'); n = read(modem, buffer, 1)); if (n == -1) exit(2); yy = 0; /* Set year = 0 */ n = 0; /* Set character counter = 0 */ while (k < NCOUNT) { /* Until we get NCOUNT seconds of data */ i = read(modem, buffer+n, 1); /* Read a character */ if (i <= 0) exit(-1); /* On EOF, punt */ if (buffer[n] == '*') { /* If second-marker */ if (yy != 0) { /* Have we got legal data? */ if (k == (NCOUNT-1)) { /* And have we seen NCOUNT seconds? */ ftime(&tp); /* Get our local time for delta */ if (OptSetme) { /* If we set time */ r = settimeofday(&del1, &tzp); /* Set to calculated value */ if (r < 0) /* Did we get an error? */ perror("settimeofday"); } if (del1.tv_sec > tp.time) { /* If value is negative */ if (tp.millitm != 0) { /* And some part of it is millitm */ tp.time++; /* Then delta is one second less */ tp.millitm = 1000 - tp.millitm; /* Plus 1.0 - millitm */ } printf("Our clock slow by %d.%03d seconds\n", del1.tv_sec - tp.time, tp.millitm); } else { printf("Our clock fast by %d.%03d seconds\n", tp.time - del1.tv_sec, tp.millitm); } printf("Universal Coordinated Time exactly %d/%d/%d %d:%02d:%02d\n", month, dd, yy, hh, mm, ss); } /* If we aren't ready to set the time yet, add one to the timestamp and one to the good marker count */ del1.tv_sec++; k++; } } else { /* If we got a CR, we figure out the time sent */ if (buffer[n] == '\n' || buffer[n] == 'r') { buffer[n] = 0; /* Terminate buffer */ /* If we haven't read a good value, and there are characters in the buffer, and the string parses correctly, then calculate time */ if ((yy == 0) && (n != 0) && (sscanf(buffer, "%d %d %2d%2d%2d UTC", &yydd, &dd, &hh, &mm, &ss) == 5)) { yydd -= FIRST_VALUE; /* Subtract day value of Dec 31st */ for (year = FIRST_YEAR; (yydd > daysinyear(year)); year++) /* Decrement until under 1 year left */ yydd -= daysinyear(year); yy = year - 1900; /* Set year number */ if (daysinyear(year) == 366) months[1] = 29; /* Handle leap year */ for (month = 0; (dd > months[month]); month++) dd -= months[month]; tm.tm_sec = ss; /* Stuff seconds in second field */ tm.tm_min = mm; /* Stuff minutes in minute field */ tm.tm_hour = hh; /* Stuff hours in hour field */ tm.tm_year = yy; /* Stuff year in year field */ tm.tm_mday = dd; /* Stuff day of month */ tm.tm_mon = month; /* Stuff month */ utc_time = ((long)timegm(&tm)); /* Get gmtime version of time */ gettimeofday(&del1, &tzp); /* Get time zone information */ del1.tv_usec = 0; /* Always exactly on second */ del1.tv_sec = utc_time; /* * is for *NEXT* second */ } n = 0; /* Reset character counter */ } else { n++; /* Store character */ buffer[n] = 0; /* Terminate */ } } } flags = TIOCM_DTR; /* Clean up after success */ ioctl(modem, TIOCMBIC, &flags); unlink(lck1); unlink(lck2); exit(0); } -- Name: James M. Turner * Great Moments in Aviation #21: While on a Company: Kendall Square Research * NDB approach into Hanscom, pilot Ted Hertz Email: turner@ksr.com, ksr!turner * accidently tunes WEEI on his NAV instead Phone: (617) 895-9400 * of the LOM, and lands on top of the Pru.
mackey@scs.fiu.edu (11/08/90)
In article <885@ksr.com> turner@ksr.com (James M. Turner) writes: >Here's a program I wrote to call the Naval Observatory and set the time >------------------------------ Cut Here ------------------------------ >/* UTCCLOCK.C - Set time from US naval Observatory via modem > Copyright (C) 1990, James M. Turner The program referenced here uses a modem to dial into the USNO. Does anyone know of a way of doing the same thing via an internet connection? Presumably ``rdate'' would work reasonably well if the connection is fast. But what is the Naval Obs.'s internet address? Is there a better way than rdate?
Jim.Thompson@Central.Sun.COM (Jim Thompson) (11/08/90)
From ntp-relay@trantor.umd.edu Wed Nov 7 13:53:25 1990 Return-Path: <ntp-relay@trantor.umd.edu> Received: from Central.Sun.COM (texsun) by hosaka (4.1/SMI-4.1) id AA03860; Wed, 7 Nov 90 13:53:24 CST Received: from Sun.COM (sun-barr.EBay.Sun.COM) by Central.Sun.COM (4.1/SMI-4.1-900117) id AA10482; Wed, 7 Nov 90 13:53:22 CST Received: from trantor.umd.edu by Sun.COM (4.1/SMI-4.1) id AA08434; Wed, 7 Nov 90 11:53:18 PST Received: by trantor.umd.edu (5.64/1.34) id AA14738; Wed, 7 Nov 90 14:24:06 -0500 Received: from ucbvax.Berkeley.EDU by trantor.umd.edu (5.64/1.34) id AA14734; Wed, 7 Nov 90 14:24:02 -0500 Received: by ucbvax.Berkeley.EDU (5.63/1.42) id AA22380; Wed, 7 Nov 90 11:18:35 -0800 Received: from USENET by ucbvax.Berkeley.EDU with netnews for ntp@trantor.umd.edu (ntp@trantor.umd.edu) (contact usenet@ucbvax.Berkeley.EDU if you have questions) Date: 7 Nov 90 18:53:33 GMT From: swrinde!zaphod.mps.ohio-state.edu!uakari.primate.wisc.edu!uflorida!kluge!scs!mackey@ucsd.edu Organization: %BS-F-QXCD, Bullshit quota exceeded, core dumped. Subject: Re: A poor man's WWV receiver (via modem) Message-Id: <1632@kluge.fiu.edu> Sender: ntp-relay@trantor.umd.edu To: ntp@trantor.umd.edu Status: R In article <885@ksr.com> turner@ksr.com (James M. Turner) writes: >Here's a program I wrote to call the Naval Observatory and set the time >------------------------------ Cut Here ------------------------------ >/* UTCCLOCK.C - Set time from US naval Observatory via modem > Copyright (C) 1990, James M. Turner The program referenced here uses a modem to dial into the USNO. Does anyone know of a way of doing the same thing via an internet connection? Presumably ``rdate'' would work reasonably well if the connection is fast. But what is the Naval Obs.'s internet address? Is there a better way than rdate? (x)ntpdate? Jim
gavron@vesta.sunquest.com (Ehud Gavron) (11/08/90)
In article <1632@kluge.fiu.edu>, mackey@scs.fiu.edu writes... #In article <885@ksr.com> turner@ksr.com (James M. Turner) writes: #>Here's a program I wrote to call the Naval Observatory and set the time #>------------------------------ Cut Here ------------------------------ #>/* UTCCLOCK.C - Set time from US naval Observatory via modem #> Copyright (C) 1990, James M. Turner # #The program referenced here uses a modem to dial into the USNO. #Does anyone know of a way of doing the same thing via an #internet connection? Presumably ``rdate'' would work reasonably #well if the connection is fast. But what is the Naval Obs.'s #internet address? Is there a better way than rdate? How about running ntp? ;-) :-) ;-) :-) Ehud /----------------------------------------------------------------------------\ | Ehud Gavron, Systems analyst | gavron@vesta.sunquest.com (Internet) | | Sunquest Information Systems | uunet!sunquest!gavron (UUCP) | | 930 N. Finance Center Drive | gavron@lampf (BITNET) | | Tucson, Arizona, 85710 | (602)722-7546/885-7700 x.2546 (AT&Tnet) | |----------------------------------------------------------------------------| | your cute quote here | \----------------------------------------------------------------------------/
Mills@udel.edu (11/11/90)
[?? no sender full name ??] So far as I have been able to determine, there is no IP connectivity for USNO. I have it on personal communication that they have plans to do this, but no bucks. Dave
medin@NSIPO.NASA.GOV ("Milo S. Medin", NASA ARC NSI Project Office) (11/11/90)
Not true! The USNO is connected to the Internet via the NASA Science Net. We have a 56 Kbps link from there to GSFC, whre it hits the NSN backbone, and then via FIX's to the NSFNET and other US Government backbones. U.S. Naval Observatory (NET-USNO) Observatory Circle NW Washington, DC 20390 NetName: USNO NetNumber: 192.5.41.0 Coordinator: Withington, F. Neville (NW33) FNW@USNO01.UNSO.NAVY.MIL (202) 653-0588 Record last updated on 23-Oct-90. It's also reachable: traceroute to usno01.usno.navy.mil (192.5.41.10), 30 hops max, 40 byte packets 1 arc-nas-gw (128.102.16.5) 10 ms 10 ms 0 ms 2 ARC1.NSN.NASA.GOV (192.52.195.2) 10 ms 0 ms 10 ms 3 GSFC1.NSN.NASA.GOV (128.161.2.3) 90 ms 90 ms 100 ms 4 GSFC3.NSN.NASA.GOV (128.161.16.33) 90 ms 90 ms 100 ms 5 USNO.NSN.NASA.GOV (128.161.38.35) 110 ms 120 ms 130 ms 6 * * * Perhaps you should tell your friends there to connect up to this network... Thanks, Milo
Mills@udel.edu (11/11/90)
Milo, My statemet nt stands. Lauro a Charron tells me USNO doe s s not provide a USNO te imestamp. Regardless of your NS a ASA prov be, I am told thter jere here is no USNO timestamp worthy of international chime. I wqou ould be most gald lad of a proof ff t f to the contrary. Dave
medin@NSIPO.NASA.GOV ("Milo S. Medin", NASA ARC NSI Project Office) (11/11/90)
Well, I don't think any of the clocks are wired up to anything that speaks IP, but there is Internet connectivity at the site... Thanks, Milo