home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.sources.misc
- X-UNIX-From: mrapple@quack.sac.ca.us
- organization: The Duck Pond, Stockton, CA
- subject: v15i009: Heathkit GC-1000 reader for unix, v1.4
- from: mrapple@quack.sac.ca.us (Nick Sayer)
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 15, Issue 9
- Submitted-by: mrapple@quack.sac.ca.us (Nick Sayer)
- Archive-name: gc1000/part01
-
- #! /bin/sh
- # This file was wrapped with "dummyshar". "sh" this file to extract.
- # Contents: gc1000.c
- echo extracting 'gc1000.c'
- if test -f 'gc1000.c' -a -z "$1"; then echo Not overwriting 'gc1000.c'; else
- sed 's/^X//' << \EOF > 'gc1000.c'
- X/*
- X
- Xsetclock.c - get time from the Heathkit GC-1000
- X
- XCopyright 1990, Nick Sayer
- XPermission to distribute granted as long as no fee is charged and
- Xthose to whom you distribute are also free to do so. All other
- Xrights reserved. No warrantees are extended regarding this software's
- Xcorrectness or applicability to any specific purpose.
- X
- Xrevision history:
- X
- Xv1.4 10/01/90 - minor bug fixes. -d flag now ignores -l. -l 0 disables -l.
- Xv1.3 09/22/90 - added limitation on time "displacement" -l option
- Xv1.2 03/31/90 - added command line option -d (debug)
- Xv1.1 02/01/90 - added configuration section & changed to settimeofday()
- Xv1.0 the epoch - created
- X
- XBUGS - adjtime() would be preferable to settimeofday().
- X
- X USAGE
- X
- X% setclock [-d] [-l minutes]
- X
- XHave cron run this program as often as necessary to maintain system
- Xclock accuracy. If the clock is not set, or if the tenth-of-a-second digit
- Xis dimmed, the system time will not be changed.
- X
- XIf -d is specified, the system will print out what time it is according
- Xto the clock. It will not try to set the system time. Use this to debug
- Xthe switch and/or options settings (see below).
- X
- XIf the time is off by more than a certain number of minutes (specified
- Xby -l, default 5), the time will not be changed and an error message
- Xgenerated instead. The WWV signal has no check-bits and some computers
- Xdon't have the best shielding in the world. The result is that despite
- Xthe clock's heuristics it can occasionally get the wrong idea of what
- Xtime it is. Having the system time suddenly change by a large amount
- Xcan cause great confusion, and that confusion is complicated when the
- Xtime has to be changed back again. For small numbers of minutes though
- Xthis isn't such a big problem. If you know the clock is right and the
- Xsystem is wrong, you can use "-l 0" to turn this checking off.
- X
- X CONFIGURATION
- X
- XYour clock should be set to constantly give the time every second or
- Xso. I.e. the handshaking option should be off, and the continuous
- Xoption should be on. On my clock, using this configuration, the
- Xtime reported is exactly one second slow, so this second is added back
- Xlater. To remove this, simply find the line that says
- X"convert.tm_sec=....." and remove the "+1".
- X
- XThe time sent to the RS-232 reads exactly the same way as it does on
- Xthe display, so if your clock displays UT1, so will your unix box.
- XIf the section below is not right, all hell will break loose. :-)
- X
- XSet DEVICE to the full path of the entry in /dev (or a link to it)
- Xthat talks to the clock
- X*/
- X#define DEVICE "/dev/clock" /* file for clock device */
- X
- X/*
- XSet baud rate for clock (like in sgtty.h)
- X*/
- X#define BAUD B2400 /* baud rate for clock */
- X
- X/*
- XSet the default minute limit here
- X*/
- X#define DEFAULT_MINUS_L 5
- X
- X/*
- XIf your clock displays AM/PM, define this.
- X*/
- X#define AMPM /* define if clock shows AM/PM */
- X
- X/*
- XIf you've set the clock up to display local time rather than GMT, then
- Xthe clock must also be set properly for your local interpretation of
- Xdaylight savings time. If your area has DST, it is NOT a good idea to
- Xrun this program less than 24 hours before DST kicks in or turns off.
- XYou may find your clock changing DST status early. Unix will figure out
- XDST by itself. For no-hassle results, use GMT and undef LOCAL. For
- Xhuman-readibility of the clock, grin and bear it. :-)
- X*/
- X#define LOCAL /* undef this if your clock displays GMT */
- X
- X/*
- XSince the BCD time code doesn't include any indication of what year it
- Xis, heath used internal dipswitches to set the year. Since it's a pain
- Xto get in there on December 31 every year, two options have been
- Xincluded to get around this. If you define CLOCKYEAR, the clock's idea
- Xof what year it is will be used. If you define YEARFILE, and set it
- Xto a filename, that file is assumed to have two digits and a newline
- Xin it, and those two digits will be used as the year. If you don't
- Xdefine either, the system's current notion of what year it is will
- Xbe retained. If you do it this way, it is NOT a good idea to run
- Xthis program close to 23:59:59 on December 31.
- X*/
- X/* #define CLOCKYEAR /* define this to use the clock's year */
- X/* #define YEARFILE "/usr/local/lib/year" /* define this for file */
- X
- X/*
- XFor best results, define NICE and set to the priority level desired. -20
- Xis highly recommended. This program doesn't load the CPU much, but
- Xaccuracy will suffer if it gets swapped.
- X*/
- X#define NICE -20
- X
- X/*
- X END OF CONFIGURATION
- X*/
- X
- X/* spoof 'em for gmtime if necessary */
- X
- X#ifdef LOCAL
- X#define LOCALTIME localtime
- X#define TIMELOCAL timelocal
- X#else
- X#define LOCALTIME gmtime
- X#define TIMELOCAL timegm
- X#endif
- X
- X#include <stdio.h>
- X#include <sgtty.h>
- X#include <signal.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- Xextern int errno; /* perror(3) */
- Xextern char *sys_errlist[];
- Xextern int optind,opterr; /* getopt(3) */
- Xextern char *optarg;
- X
- X/* We'll set a timer later. If it goes off, something's messed up. */
- Xbomb()
- X{
- X
- X printf("Timeout. Check clock.\n");
- X exit(1);
- X
- X}
- X
- X/* A hack. getc() didn't work for some reason. */
- Xchar get_c(fildes)
- Xint fildes;
- X{
- X char c;
- X read(fildes,&c,1);
- X return c;
- X}
- X
- Xmain(argc,argv)
- Xint argc;
- Xchar **argv;
- X{
- X
- X int clkfil,dbg_flag=0,usec,hr,timedif=DEFAULT_MINUS_L,errflag=0;
- X char a[255],*b,optchar;
- X time_t hydrant;
- X
- X struct timeval tv;
- X struct timezone tz;
- X struct tm convert;
- X
- X struct sgttyb ttystuff;
- X
- X#ifdef YEARFILE
- X FILE *yf;
- X int yf_yr;
- X#endif
- X
- X opterr=0;
- X
- X while((optchar=getopt(argc,argv,"dl:"))!=-1)
- X {
- X switch(optchar)
- X {
- X case 'd':dbg_flag++; break;
- X case 'l':timedif=atoi(optarg); break;
- X default:errflag++;
- X }
- X }
- X if (errflag)
- X {
- X printf("Usage: %s [-d] [-l min]\n",*argv);
- X exit(1);
- X }
- X
- X/* if YEARFILE, we'd better read it now so it won't interfere with the
- Xtight timing section later */
- X#ifdef YEARFILE
- X yf=fopen(YEARFILE,"r");
- X scanf("%d\n",&yf_yr);
- X fclose(yf);
- X#endif
- X
- X#ifdef NICE
- X nice(NICE);
- X#endif
- X
- X alarm(15);
- X signal(SIGALRM,bomb);
- X
- X if ((clkfil=open(DEVICE,2))==NULL)
- X {
- X printf("Error opening %s.\n",DEVICE);
- X exit(1);
- X }
- X
- X/* set for baud rate and RAW */
- X ttystuff.sg_ispeed=BAUD;
- X ttystuff.sg_ospeed=BAUD;
- X ttystuff.sg_kill=' ';
- X ttystuff.sg_erase=' ';
- X ttystuff.sg_flags=RAW;
- X if (ioctl(clkfil,TIOCSETP,&ttystuff)==-1)
- X {
- X printf("Error setting up %s.\n",DEVICE);
- X exit(1);
- X }
- X/*
- XWait for end of line, then read until another. If seconds>50,
- Xwait for it to go to 0. We have to add 1 to the seconds, and if it's
- X:59..... Also, if the line's too short, read it again.
- X*/
- X while((get_c(clkfil) & '')!='\r');
- X do {
- X b=a;
- X while((*b=get_c(clkfil) & '')!='\r') b++;
- X *b='\0';
- X } while (a[6]=='5' || strlen(a)!=23);
- X/*
- X
- X START OF TIME CRITICAL SECTION
- X
- XFrom here to end of critical section must be executed as quickly as
- Xpossible to (try to) insure accuracy
- X
- Xa[9] is the tenth of a second digit. The clock outputs a ? here if
- Xeither the clock is not set, or if it hasn't been updated in 24
- Xhours and therefore isn't sure of itself.
- X*/
- X if (a[9]=='?')
- X {
- X printf("Clock not set.\n");
- X exit(1);
- X }
- X
- X usec=atoi(a+9)*100;
- X hr=atoi(a);
- X
- X#ifdef AMPM
- X if (a[11]=='P')
- X {
- X if (hr!=12) hr+=12;
- X }
- X if (a[11]=='A')
- X {
- X if (hr==12) hr=0;
- X }
- X#endif
- X
- X time(&hydrant);
- X convert=*LOCALTIME(&hydrant);
- X convert.tm_min=atoi(a+3);
- X convert.tm_sec=atoi(a+6)+1;
- X convert.tm_hour=hr;
- X convert.tm_mon=atoi(a+15)-1;
- X convert.tm_mday=atoi(a+18);
- X
- X#ifdef CLOCKYEAR
- X convert.tm_year=atoi(a+21);
- X#endif
- X
- X#ifdef YEARFILE
- X convert.tm_year=yf_yr;
- X#endif
- X
- X hydrant=TIMELOCAL(&convert);
- X
- X if (dbg_flag)
- X {
- X printf("%s",ctime(&hydrant));
- X exit(0);
- X }
- X
- X if ( (abs(time(0L)-hydrant)>(timedif*60)) && (timedif) )
- X {
- X printf("Clock shows substantially different time. Check clock.\n");
- X exit(1);
- X }
- X
- X/*
- XNow hydrant is the current ctime (num of secs since epoch)
- X*/
- X
- X gettimeofday(&tv,&tz);
- X tv.tv_sec=hydrant;
- X tv.tv_usec=usec;
- X if (!dbg_flag)
- X if (settimeofday(&tv,&tz)!=0)
- X {
- X printf("settimeofday(): %s\n",sys_errlist[errno]);
- X exit(1);
- X }
- X
- X/*
- X
- XEND OF TIME CRITICAL SECTION
- X
- X*/
- X
- Xexit(0);
- X
- X}
- EOF
- chars=`wc -c < 'gc1000.c'`
- if test $chars != 8123; then echo 'gc1000.c' is $chars characters, should be 8123 characters!; fi
- fi
- exit 0
- --
- Nick Sayer | Disclaimer:
- N6QQQ [44.2.1.17 soon] | "Just because you're reading my post doesn't
- mrapple@quack.sac.ca.us | mean we're gonna take long showers together."
- 209-952-5347 (Telebit) | -- Gunnery Sgt. Thomas Highway
-
-