earle@jplopto.uucp (Gregory Earle (40876)) (05/11/87)
An easy workaround for not having `timed' on Suns, that has worked quite well for me for some time: For each machine in your network, call the UTC number, (303) 499-7111 I believe, and set its clock by it. Do this on a Friday. Then, on Monday, call it again and see which machine is still closest to the correct time. Assume that is your best clock machine. Call this machine `goodclock'. Then, write a little script, which does simply for i in [names of your hosts here] (If you use YP, you can replace a static list by `ypcat hosts.byname | awk '{ print $1}'` or something equivalent) do rsh $i rdate goodclock done I toss this into /usr/adm, and run it every 6 hours out of crontab. Obviously it loses if one of the machines happens to be down (`goodclock' will be left with a few processes hanging around, like `sh' and `rsh'), but in general this is a minor nuisance. This way, you get pretty reasonable clock sync across your network, and then you merely need call UTC every week or two to keep `goodclock' in sync. It may not be as clean as `timed' but *I* certainly never worried about clock sync problems using this method ...
chris@mimsy.UUCP (Chris Torek) (05/11/87)
In article <3734@elroy.Jpl.Nasa.Gov> earle@jplopto.uucp (Gregory Earle (40876)) writes: >... call the UTC number, (303) 499-7111 I believe, and set its clock >by it. There must be several UTC clocks. There is a machine readable UTC clock at the U.S. Naval Observatory in Washington, D.C.; the number is (correct this time!) 202 653 0351. (The voice number is 202 653 1800.) Below is a program that reads the values printed by this clock. I did not write this code and am not responsible for all the obvious bugs in it. #ifndef lint static char sccsid[] = "@(#)navclock.c (U of Maryland) FLB 15-May-1986"; static char RCSid[] = "$Header: navclock.c,v 1.1 86/05/15 23:23:25 bin Exp $"; #endif lint /* * navclock - read Naval Observatory clock to set system clock * % cc -s -O navclock.c -o navclock * * $Log: navclock.c,v $ * Revision 1.1 86/05/15 23:23:25 bin * Initial revision * */ #include <stdio.h> #include <signal.h> #include <sys/time.h> #include <ctype.h> #include <sysexits.h> #define PHONE_DELAY 1700 #define SECONDS 1 #define MINUTES 60 #define HOURS (60*MINUTES) #define DAYS (24*HOURS) #define N_SAMP_DFL 3 #define ADJTIME 1 #define CLOCK_LOG "/usr/adm/clock_log" int silent_flag = 0; struct timeval correction, min_correction = { 259200, 0}, corr_threshhold = { 0, 50000}, threshhold = { 600, 0}, timeout = { 8, 500 }; /****************************************************************************/ struct timeval get_correction() { struct timeval system_time, naval_time, correction; struct timezone time_zone; long julian_date, day_of_year, hour, minute, second, days, year; char buff[BUFSIZ], c; register char *cp; nice(-40); nice(20); nice(0); nice(-10); alarm(40); do { if (fgets(buff, sizeof(buff), stdin) == NULL) { if (!silent_flag) fprintf(stderr, "unexpected EOF on input\n\r"); exit(EX_NOINPUT); } for (cp = buff; cp < &buff[sizeof(buff)] && *cp; cp++) *cp &= 0177; *--cp = (char)0; } while (sscanf(buff, "%d %d %2d%2d%2d", &julian_date, &day_of_year, &hour, &minute, &second) < 5); do { if (read(0, &c, 1) < 1) { if (!silent_flag) perror("Read error"); exit(EX_NOINPUT); } c &= 0177; if (!silent_flag) fputc(c, stderr); } while (c != '*'); if (!silent_flag) fputc('\n', stderr); fflush(stderr); if (gettimeofday(&system_time, &time_zone) < 0) { if (!silent_flag) perror("gettimeofday"); exit(EX_OSERR); } alarm(0); nice(-40); nice(20); nice(0); { long t; struct tm *localtime(); register struct tm *tp; time(&t); tp = localtime(&t); year = tp->tm_year; if (year < 100) year += 1900; } { register int i; for (days = 0, i = 1970; i < year; i++) days += dysize(i); } naval_time.tv_sec = (days+day_of_year-1)*DAYS + hour*HOURS + minute*MINUTES + second*SECONDS; naval_time.tv_usec = 0; correction.tv_sec = naval_time.tv_sec - system_time.tv_sec; correction.tv_usec = naval_time.tv_usec - system_time.tv_usec; correction.tv_usec += PHONE_DELAY; normalize(&correction); return correction; } /****************************************************************************/ struct timeval * abs_val(tp) struct timeval *tp; { register struct timeval *abs; if (tp->tv_sec < 0) { abs = (struct timeval *)malloc(sizeof(struct timeval)); abs->tv_sec = -tp->tv_sec; abs->tv_usec = -tp->tv_usec; } else *abs = *tp; return abs; } /****************************************************************************/ main(argc, argv) int argc; char *argv[]; { int n_samp = N_SAMP_DFL; signal(SIGALRM, SIG_DFL); for (argc--, argv++; argc > 0; argc--, argv++) { register char *cp; for (cp = *argv; *cp;) switch (*cp) { case 'm': threshhold.tv_sec = atoi(++cp); while (*cp && isascii(*cp) && isdigit(*cp)) cp++; break; case 's': silent_flag++; cp++; break; case 'n': n_samp = atoi(++cp); while (*cp && isascii(*cp) && isdigit(*cp)) cp++; default: fprintf(stderr, "navclock: bad flag: %c\n\r", *cp); case '-': cp++; } } while (n_samp-- > 0) { correction = get_correction(); if (timercmp(abs_val(&correction), abs_val(&min_correction), <)) min_correction = correction; } if (timercmp(abs_val(&correction), &corr_threshhold, <)) { if (!silent_flag) fprintf(stderr, "no correction\r\n"); correction.tv_sec = correction.tv_usec = 0; } if (!silent_flag) fprintf(stderr, "correction %f seconds\r\n", (double)correction.tv_sec + ((double)correction.tv_usec/1000000.0)); if (timercmp(abs_val(&correction), &threshhold, >)) { if (!silent_flag) fprintf(stderr, "navclock: correction greater than %d seconds.\n", threshhold); exit(EX_DATAERR); } #ifdef CLOCK_LOG log_it(&correction); #endif CLOCK_LOG if (correction.tv_sec == 0 && correction.tv_usec == 0) exit(EX_OK); #ifdef ADJTIME if (adjtime(&correction, (struct timeval *)0) < 0) { if (!silent_flag) perror("adjtime"); exit(EX_NOPERM); } #else ADJTIME if (gettimeofday(&system_time, &time_zone) < 0) { if (!silent_flag) perror("gettimeofday"); exit(EX_OSERR); } system_time.tv_sec += correction.tv_sec; system_time.tv_usec += correction.tv_usec; normalize(&system_time); if (settimeofday(&system_time, &time_zone) < 0) { if (!silent_flag) perror("settimeofday"); exit(EX_NOPERM); } #endif ADJTIME exit (EX_OK); } /****************************************************************************/ normalize(timestruct) register struct timeval *timestruct; { if (timestruct->tv_sec >= 0) { if (timestruct->tv_usec >= 1000000) { timestruct->tv_sec++; timestruct->tv_usec -= 1000000; } if (timestruct->tv_usec < 0) { timestruct->tv_sec--; timestruct->tv_usec += 1000000; } } else { if (timestruct->tv_usec <= -1000000) { timestruct->tv_sec--; timestruct->tv_usec += 1000000; } if (timestruct->tv_usec > 0) { timestruct->tv_sec++; timestruct->tv_usec -= 1000000; } } } /****************************************************************************/ #ifdef CLOCK_LOG log_it(corr) struct timeval *corr; { register FILE *log; char *ctime(); long time(), tim; if ((log = fopen(CLOCK_LOG, "a")) == NULL) { perror(CLOCK_LOG); return; } time(&tim); fprintf(log, "%24.24s %f\n", ctime(&tim), (double)corr->tv_sec + ((double)corr->tv_usec/1000000.0)); fclose(log); } #endif CLOCK_LOG /****************************************************************************/ -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) Domain: chris@mimsy.umd.edu Path: seismo!mimsy!chris