Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Radio-Clock-Time (Part01/01)

4 views
Skip to first unread message

Jan-Piet Mens

unread,
Jul 29, 1991, 5:25:55 AM7/29/91
to
In comp.unix.questions I wrote:
> Does anybody know how to access the radio time sent out by
> the DCF77 transmitter near Frankfurt/M ?
> Has anyone ever done it in Unix ?

Here is a package to do it.

#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of archive 1 (of 1)."
# Contents: Copyright INSTALL MANIFEST Makefile README dcf.1 dcf.c
# defs.h log.c patchlevel.h
# Wrapped by jpm@logixwi on Mon Jul 29 11:24:49 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Copyright' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Copyright'\"
else
echo shar: Extracting \"'Copyright'\" \(361 characters\)
sed "s/^X//" >'Copyright' <<'END_OF_FILE'
X/*
X * Copyright 1991, Jan-Piet Mens
X * License to freely use and distribute this software is hereby granted
X * by the author, subject to the condition that this copyright notice
X * remains intact. The author retains the exclusive right to publish
X * derivative works based on this work, including, but not limited
X * to, revised versions of this work
X */
END_OF_FILE
if test 361 -ne `wc -c <'Copyright'`; then
echo shar: \"'Copyright'\" unpacked with wrong size!
fi
# end of 'Copyright'
fi
if test -f 'INSTALL' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'INSTALL'\"
else
echo shar: Extracting \"'INSTALL'\" \(565 characters\)
sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
X 1. See the Makefile, and set `BINDIR' to the name of the
X directory into which the `dcf' program will be copied
X upon "make install"
X
X 2. Set -DDEBUG in CFLAGS
X
X 3. Edit `defs.h' to adjust certain parameters to your liking.
X
X 4. type: "make" to produce a DEBUG version of `dcf'
X
X 5. test `dcf'. It should produce the debugging output described
X in the README-file.
X
X 6. If all works as planned, remove -DDEBUG from the Makefile.
X
X 7. type: "make install" to re-compile, and install into BINDIR
X
X 8. Watch the file /etc/dcf.log for correct entries.
X
X 9. Done!
X
END_OF_FILE
if test 565 -ne `wc -c <'INSTALL'`; then
echo shar: \"'INSTALL'\" unpacked with wrong size!
fi
# end of 'INSTALL'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(540 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X File Name Archive # Description
X-----------------------------------------------------------
X Copyright 1 Message
X INSTALL 1 Installation guide
X MANIFEST 1 This shipping list
X Makefile 1 Make
X README 1 Read this FIRST
X dcf.1 1 Manual page
X dcf.c 1 Main program
X defs.h 1 Configuration file
X log.c 1 Logging routines
X patchlevel.h 1 Release/Version
END_OF_FILE
if test 540 -ne `wc -c <'MANIFEST'`; then
echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(695 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# see defs.h before looking here.
X#
XCC= cc
X# set DEBUG only for experimental purposes
X#CFLAGS= -g -DDEBUG
XCFLAGS= -O -s
XBINDIR= /etc
X
XPROG= dcf
XOFILES= dcf.o log.o
XSFILES= dcf.c log.c
XHFILES= defs.h patchlevel.h
X
X$(PROG): $(OFILES)
X $(CC) $(CFLAGS) -o $(PROG) $(OFILES)
X
Xdcf.o: $(HFILES) Makefile
Xlog.o: $(HFILES) Makefile
X
Xinstall: $(BINDIR)/$(PROG)
X strip $(PROG)
X cp $(PROG) $(BINDIR)/$(PROG)
X chmod 555 $(BINDIR)/$(PROG)
X chown root $(BINDIR)/$(PROG)
X chgrp root $(BINDIR)/$(PROG)
X
Xdoc: dcf.1
X nroff -man dcf.1 > dcf.doc
X
X$(BINDIR)/$(PROG): $(PROG)
X
Xclean:
X rm -f *.o a.out core Part01 B-MANIFEST
Xclobber: clean
X rm -f $(PROG)
X
Xdist: $(SFILES) $(HFILES)
X makekit -oMANIFEST -h2 < Manifest
END_OF_FILE
if test 695 -ne `wc -c <'Makefile'`; then
echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(5227 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XThis is `dcf', a program to set UN*X system time from a DCF clock. Written
Xby Jan-Piet Mens. The clock was built by Jan Hentsch, who also supported and
Xsolved all technical problems.
X
XSee the file `INSTALL' for installation instructions.
X
XSee the file `dcf.1' for the manual.
X
X********************************************************************************
XDescription of the program
X==========================
X
XThe `dcf' program connects via a serial line (tty) to a clock which receives
Xa time signal sent out by the DCF transmitter near Mainflignen. The time signal
Xreceived from the clock, is used to set the time of a UN*X system.
X
X********************************************************************************
XThe clock
X=========
X
XThe clock is an electronic clock made by ELV and is called
X " ELV Funkuhren-Schaltsystem DCF 7000 "
X
X[ if you wish to know where and how to order the clock, please email to
X j...@logixwi.UUCP for details ]
X
XSome of the capabilities of the clock:
X - 16-digit display for displaying info
X time, date, weekday, week
X - 2 alarms
X - timer function
X - 8 additional channels for switching relays or 220V devices
X - 64 Wakeup/Channel times are programmable
X - Automatic switch to quarz due to loss of DCF signal
X - 8-bit parallel (Centronics) output
X - Serial (RS 232) output with 6 different baudrates.
X
XThe clock is available as a kit or ready-built. Unless you are *really* good
Xat soldering, and have quite some understanding of electronics, we would suggest
Xyou invest the couple-hundred marks extra, and buy the clock ready-made !!!
XIf only to avoid the 60-odd straps which must be soldered onto the main
XPCB.
X
X********************************************************************************
XTime Telegram received from DCF clock
X=====================================
X
XThe clock transmits a telegram over the serial (or parallel) line to the system
Xevery second. The format of the telegram (datagram) is
X
X yy-mm-dd-wd-hh-mm-ss-nn
X | | | | | | | |
X | | | | | | | +---- 00 = winter time, 01 = dst, etc.
X | | | | | | +------- Seconds
X | | | | | +---------- Minutes
X | | | | +------------- Hour
X | | | +---------------- Weekday
X | | +------------------- Day
X | +---------------------- Month
X +------------------------- Year
X
XEg: Mon Jul 29 10:20:41 1991 would come in as
X
X 91-07-29-01-10-20-41-nn
X
Xwhere `nn' is one of:
X
X 00 DST not in effect, DCF time, DCF sync
X 01 DST in effect, DCF Time, DCF sync
X 04 DST not in effect, DCF time, DCF out of sync
X 05 DST in effect, DCF time, DCF reception problem
X 06 DST not in effect, Manual time
X
XDST in effect: Daylight savings time applies
XDST not in effect: Daylight savings time does not apply
XDCF time: Timestamp set by clock via DCF
XManual time: Time was set manually on clock.
X
X
X
X********************************************************************************
XDCF info
X========
XTimecode transmitters, frequencies and geographic coordinates
XCall Location Frequencies Coordinates
X------------------------------------------------------------------------
XDCF77 Mainflingen, DE 77.5 kHz 50:01N 9:00E
X
X
X********************************************************************************
XCompilation with debug output
X=============================
X
XIf DCF is compiled with the -DDEBUG option, it will start up in non-daemon
Xmode, and display the time telegrams it receives from the clock.
X
X +--------------------------------------- DCF string
X | +----------------- No. chars read from DCF
X | | +--- Winter|Summer
X | | |
XGot: 91-07-25-04-08-39-06-01 [23 chrs] (01 Summer. DCF OK)
XUNIX = 680423946, DCF = 680423946
X | |
X | +---- time calculated by DCF program
X +--------------------- local system time(2)
XThu Jul 25 08:39:06 1991
X
XGot: 91-07-25-04-08-39-07-01 [23 chrs] (01 Summer. DCF OK)
XUNIX = 680423947, DCF = 680423947
XThu Jul 25 08:39:07 1991
X .../...
XGot: 91-07-25-04-08-39-15-01 [23 chrs] (01 Summer. DCF OK)
XUNIX = 680423955, DCF = 680423955
XThu Jul 25 08:39:15 1991
X10 timestamps received ok <================
XI would be setting the time here... <================
X
X
X********************************************************************************
XWiring
X======
X
XThe cable needed to connect your system to the DCF clock is rather simple.
XYou only need two pins; TRANSMIT DATA (DCF) is connected to RECEIVE DATA
X(system). The second wire is GROUND, that's all.
XYou may need the strap between pins 6 and 20. We have had some trouble with
Xan open DTR line.
X
X DTE (system) DCE (clock)
X
X RXD (3) ---------------------------(2) TXD
X GND (7) ---------------------------(7) GND
X DSR (6) ---+
X |
X DTR (20) --+
X
XThis setup works for us on a system that used the FAS 2.08 driver.
X
X********************************************************************************
XProblems
X========
X
X None known of at this moment ;-)
X
X Please mail any you find to
X
X j...@logixwi.uucp or
X ...!uunet!mcsun!unido!logixwi!jpm
X
X** End *************************************************************************
END_OF_FILE
if test 5227 -ne `wc -c <'README'`; then
echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'dcf.1' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dcf.1'\"
else
echo shar: Extracting \"'dcf.1'\" \(4014 characters\)
sed "s/^X//" >'dcf.1' <<'END_OF_FILE'
X.TH DCF 8 "Local Administrator Commands" "Release 1.00"
X.SH NAME
Xdcf - dcf clock daemon
X.SH SYNOPSIS
X.B dcf
X[
X.B -l
X.I device
X]
X[
X.B -s
X.I speed
X]
X[
X.B -v
X]
X.SH DESCRIPTION
X.B dcf
Xis a program that connects over a serial line specified as
X.I device
Xat the named
X.I speed
Xto a clock which receives the signal from the
X.I DCF77
Xtransmitter in
X.I Mainflignen
Xnear
X.I Frankfurt in West Germany.
X.PP
XThis time signal sent by the transmitter has a deviation of about one second in 300.000 years.
X.PP
XThe clock (ELV DCF 7000) receives and processed the signal as sent by the
Xtransmitter, and sends out a stream of bytes containing the official
XMiddle European time.
X.PP
XUpon startup, the
X.B dcf
Xprogram connects to the clock and starts reading the telegrams that are sent
Xby the clock.
X.B dcf
Xwaits until it has received ten correct telegrams and then sets the local time
Xvia the
X.I stime(2)
Xcall. A telegram is considered correct if it has an appropriate format, and
Xnot all values of the telegram are zero. The ten telegrams are considered
Xappropriate if they are in sequence, i.e.: the second is larger than the first, the third larger than the second, etc.
X.PP
XIn case of problems, the system's
X.I postmaster
Xis notified by mail.
X.SH OPTIONS
X.IP "\fB-l\fR \fIdevice\fR" 2i
Xread the clock on the specified device. The device name may be specified relative to the
X.I /dev
Xdirectory as in
X(
X.I tty1h
X), or as a full pathname (
X.I /dev/tty1h
X). If this options is not specified, a default device is used, which is set at
Xcompile-time.
X.IP "\fB-s\fR \fIspeed\fR" 2i
XUse the given speed. Here again, a default speed exists, which is supplied at compile-time.
XPossible speeds are between 300 and 9600 baud.
X.IP "\fB-v\fR" 2i
Xturn on verbose mode. The
X.B dcf
Xprogram does not become a daemon. Only for test purposes.
X.IP "\fB-V\fR" 2i
Xshow program version and exit.
X.SH DIAGNOSTICS
X.B dcf
Xsends most diagnostics via
X.I mail
Xto a
X.I postmaster.
X.PP
X.IP "Cannot open line [\fIdevice\fR]: [\fIreason\fR]. Dying..."
XThe specified
X.I device
Xcannot be opened. Probably just a permission problem. Why that could not be done is specified as
X.I reason.
X.IP "I tried 10 times to get a reading from the clock"
XTelegrams are not being received at all or correctly by the
X.B dcf
Xprogram. There is either no connection to the clock or, if the connection exists, some parameter such as baudrate is not correct.
X.IP "Cannot stime(): Not owner. Dying..."
XThe system call
X.I stime()
Xcannot be called. The program has probably been started by a non-superuser.
X.IP "Cannot ioctl [SET|GET]: [\fIreason\fR]. Dying..."
XAn
X.I ioctl
Xcould not be done on the
X.I device. The reason is indicated.
X.IP "Cannot re-open line"
XThe
X.B dcf
Xprogram can't convert the file descriptor of the already-open
X.I device
Xto a file pointer. Something is terribly wrong!
X.IP "Cannot set time. Wrong NOW"
XAlthough a telegram was thought to be correct, it isn't. No solution.
X.IP "Can't set %d as baudrate"
XThe specified baudrate is illegal.
X.IP "I have been asked to QUIT. Signal=%d Packing up!"
X.B dcf
Xhas caught a signal. The signal number is specified as
X.I %d.
X.IP "End of File"
XThe
X.B dcf
Xprogram has got an EOF from the
X.I device
X.IP "This program is not for you"
XThe program was not compiled with
X.I -DDEBUG,
Xand is being called by a non-superuser.
X.IP "DCF clock is booting ..."
XThe program was compiled with the
X.I -DDEBUG
Xoption, and the DCF clock was just powered up. The clock needs about 3 minutes
Xto adjust to the transmitter's signal. During this time, until the first
Xcorrect time telegram is received, this message is displayed on standard output.
X.SH FILES
X.IP /etc/dcf.log 1i
Xa circular log file, which records error messages and diagnostics.
XThe name of the file can be changed during compilation.
XThis file is created automatically if it does not exist, and it is always kept
Xat a reasonable size.
X.SH SEE ALSO
Xmail(1), stime(2), date(1), tzset(3)
X.SH RELEASE
XDCF clock daemon 1.00 J.P. Mens
X.SH AUTHOR
XJan-Piet Mens - j...@logixwi.UUCP
END_OF_FILE
if test 4014 -ne `wc -c <'dcf.1'`; then
echo shar: \"'dcf.1'\" unpacked with wrong size!
fi
# end of 'dcf.1'
fi
if test -f 'dcf.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dcf.c'\"
else
echo shar: Extracting \"'dcf.c'\" \(11342 characters\)
sed "s/^X//" >'dcf.c' <<'END_OF_FILE'
X/*
X * $Header: /u/tools/etc/dcf/RCS/dcf.c,v 1.1 1991/07/25 15:05:21 jpm Exp jpm $
X *
X * $Log: dcf.c,v $
X * Revision 1.1 1991/07/25 15:05:21 jpm
X * Initial revision
X *
X *
X */
X
X/*
X * Copyright 1991, Jan-Piet Mens
X * License to freely use and distribute this software is hereby granted
X * by the author, subject to the condition that this copyright notice
X * remains intact. The author retains the exclusive right to publish
X * derivative works based on this work, including, but not limited
X * to, revised versions of this work
X */
X
X#include "defs.h"
X#include "patchlevel.h"
X#include <signal.h>
X
X#define USAGE (void)fprintf(stderr,"Usage: %s [-l device] [-s speed] [-v] [-V]\n",\
X progname)
X#define ERR_BAUD (void)fprintf(stderr,"%s: Can't set %d as baudrate\n",\
X progname, baudrate)
Xchar progname[MAX]; /* Basename of my program */
Xextern char *sys_errlist[];
Xextern int errno;
Xint fd; /* Fd of device */
Xlong tz_adjust = 0; /* TZ adjustment in seconds */
Xchar verbose = FALSE; /* True if debugging output */
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X#ifndef lint
X static char rcs_id[] = "$Id: dcf.c,v 1.1 1991/07/25 15:05:21 jpm Exp jpm $";
X#endif
X char *strrchr(), *ptr;
X static char device[MAX] = "/dev/";
X static int baudrate = DEFAULT_BAUDRATE;
X extern char *optarg;
X extern long timezone, altzone;
X extern int daylight;
X int i, c, lflag = 0;
X
X /*
X * Get basename of program
X */
X
X ptr = (ptr = strrchr(*argv,'/')) ? ptr : *argv;
X (void)strcpy(progname, ptr);
X
X#ifndef DEBUG
X if (getuid())
X {
X fprintf(stderr,"%s: This program is not for you!\n", progname);
X exit(3);
X }
X#endif
X
X /*
X * Set up signal catching. Avoid "death of a child". This signal is
X * produced if mail() is used.
X * If DEBUG is defined, avoid DEL.
X * The clock gives a hangup signal sometimes. I don't know where it
X * comes from ... :-[
X */
X
X signal(SIGHUP,SIG_IGN);
X for (i = 2; i <= SIGPWR; i++)
X if ((i != SIGCLD) && (i != SIGALRM)
X#ifdef DEBUG
X && (i != SIGINT)
X#endif
X )
X (void)signal(i, quit);
X
X /*
X * Set up adjustment for local time zone
X */
X
X tzset(); /* Set up externals */
X if (daylight)
X tz_adjust = altzone; /* These are negative values! */
X else tz_adjust = timezone;
X
X
X while ((c = getopt(argc,argv,"l:s:vV")) != EOF)
X {
X switch (c)
X {
X case 'l': /* Device */
X if (*optarg == '/')
X (void)strcpy(device, optarg);
X else (void)strcat(device, optarg);
X ++lflag;
X break;
X case 's': /* Speed */
X baudrate = atoi(optarg);
X switch (baudrate)
X {
X /*
X * Don't bother catering for more...
X * The clock supports only these.
X */
X
X case 300: baudrate = B300; break;
X case 600: baudrate = B600; break;
X case 1200: baudrate = B1200; break;
X case 2400: baudrate = B2400; break;
X case 4800: baudrate = B4800; break;
X case 9600: baudrate = B9600; break;
X default:
X ERR_BAUD;
X (void)exit(1);
X }
X break;
X case 'v':
X verbose = TRUE;
X break;
X case 'V': /* Version */
X printf("DCF clock daemon %d.%02d J.P. Mens\n",
X RELEASE, PATCHLEVEL);
X exit(0);
X default:
X USAGE;
X (void)exit(1);
X }
X }
X
X if (!lflag) /* Device has not been specified */
X (void)strcpy(device, DEFAULT_DEVICE);
X
X /*
X * Make myself into a daemon ...
X */
X
X#ifndef DEBUG
X if (!verbose)
X {
X if (fork() == 0)
X {
X setpgrp();
X }
X else return (0); /* Parent returns */
X }
X#endif
X
X setup(device, baudrate);
X
X readtime();
X/*NOTREACHED*/
X}
X
X/*
X * Set up the device, to the appropriate baudrate.
X */
X
Xvoid setup(device, baudrate)
Xchar *device;
Xint baudrate;
X{
X static struct termio dl;
X char buf[BUFSIZ];
X
X if ((fd = open(device,O_RDONLY)) == -1)
X {
X (void)sprintf(buf,"%s: Cannot open line %s: %s. Dying...",
X progname, device, sys_errlist[errno]);
X mail(buf);
X }
X
X if ((ioctl(fd, TCGETA, &dl)) == -1)
X {
X (void)sprintf(buf,"%s: Cannot ioctl GET: %s. Dying...",
X progname, sys_errlist[errno]);
X mail(buf);
X }
X
X dl.c_cflag &= ~CBAUD;
X dl.c_cflag |= (CBAUD & baudrate);
X
X /*
X * When booting, the clock seems (?) to close the line. Avoid HUP.
X */
X
X dl.c_cflag &= ~HUPCL;
X dl.c_iflag |= ICRNL;
X dl.c_cflag |= PARENB;
X dl.c_cflag &= ~(PARODD);
X dl.c_lflag |= XCLUDE;
X
X if ((ioctl(fd, TCSETA, &dl)) == -1)
X {
X (void)sprintf(buf,"%s: Cannot ioctl SET: %s. Dying...",
X progname, sys_errlist[errno]);
X mail(buf);
X }
X}
X
X/*
X * Mail the content of `message' to the postmaster, and die.
X * Note, `message' may contain NO quotes!
X */
X
Xvoid mail(message)
Xchar *message;
X{
X char command[BUFSIZ];
X
X#ifndef NO_LOGGING
X log(message);
X#endif
X (void)sprintf(command, MAIL_COMMAND,message, POSTMASTER);
X (void)system(command);
X (void)exit(2);
X}
X
X/*
X * Endless. Read telegram from clock, and if correct, set time.
X */
X
Xvoid readtime()
X{
X long list[10];
X int listcount = 0;
X FILE *fp;
X long now, secs;
X long count = 0; /* No. of tries */
X static char telegram[100] = "91-07-23-04-20-15-00-00";
X char buf[BUFSIZ];
X
X if ((fp = fdopen(fd,"r")) == (FILE *)0)
X mail("Cannot re-open line");
X
X setbuf(fp,0);
X listcount = 0;
X while (1)
X {
X memset(telegram,EOS,100);
X if (fgets(telegram,100,fp) == (char *)0)
X mail("End of File");
X telegram[strlen(telegram) - 1] = EOS;
X
X /*
X printf("Telegram [%s]\n", telegram);
X fflush(stdout);
X */
X if (wrong_format(telegram))
X {
X if (!strncmp(telegram, "00-00-00-00-00-00-00", 20))
X {
X if (verbose) {
X printf("DCF clock is booting ...\n");
X fflush(stdout);
X }
X#ifndef NO_LOGGING
X time(&secs);
X log("Clock is booting ... (%-24.24s)",
X (char *)ctime(&secs));
X#ifndef DEBUG
X sleep(10);
X#endif
X#endif
X ioctl(fd,TCFLSH,0);
X continue;
X }
X ++count;
X if (count < MAX_TRIES)
X continue;
X toomanytries();
X }
X
X /*
X * Reset counter.
X */
X
X count = 0;
X if (verbose)
X show_string(telegram);
X
X /*
X * At this point we *should* have a perfect telegram,
X * containing a beautiful ;-) time stamp.
X * Now, how many seconds since 1.Jan.1970 00:00 GMT does
X * it contain ???
X */
X
X if ((now = mktm(telegram)) == -1)
X mail("Cannot set time. Wrong NOW");
X
X list[listcount] = now;
X if (++listcount < 10)
X continue;
X
X if (ok(list))
X {
X#ifndef DEBUG
X if (stime(&now) == -1)
X {
X sprintf(buf,"%s: Cannot stime(): %s. Dying...",
X progname, sys_errlist[errno]);
X mail(buf);
X }
X#endif
X#ifndef NO_LOGGING
X log("Time set. (%-24.24s)", (char *)ctime(&now));
X#endif /* NO_LOGGING */
X#ifdef DEBUG
X if (verbose) {
X printf("10 timestamps received ok\n");
X printf("I would be setting the time here...\n");
X }
X#endif
X }
X else
X {
X mail("Something happened to the clock!");
X }
X listcount = 0;
X
X /*
X * Rest a little ...
X */
X
X#ifndef DEBUG
X sleep(SLEEP_TIME);
X#endif
X ioctl(fd,TCFLSH,0);
X }
X}
X
X/*
X * Check 10 timestamps in list. The second should be greater than the first,
X * the third greater than the second, etc.
X */
X
Xint ok(list)
Xlong list[];
X{
X int i;
X
X for (i = 0; i < 9; i++)
X {
X if (list[i] > list[i + 1])
X return (0);
X }
X return (1);
X}
X
X/*
X * Check plausible format of string `s'. It must have an acceptable
X * telegram form if it contains a correct time.
X */
X
Xint wrong_format(telegram)
Xchar *telegram;
X{
X int i;
X
X /*
X * The string must at least be long enough!
X */
X
X if (strlen(telegram) != TELEGRAM_LENGTH)
X return (TRUE);
X
X /*
X * Every third character must be a dash. If it isn't, were
X * out of sync.
X */
X
X for (i = 2; i < TELEGRAM_LENGTH; i += 3)
X {
X if (telegram[i] != '-')
X return (TRUE);
X }
X
X /*
X * Not *all* elements of the telegram must be zero. Otherwise,
X * the DCF clock has just been turned on.
X * The last element, contains garbage upon startup of clock: don't
X * check that one!
X */
X
X if (!strncmp(telegram, "00-00-00-00-00-00-00", 20))
X return (TRUE);
X
X /*
X * We *should* now have a correct string, of sorts ;-)
X */
X
X return (FALSE);
X}
X
X/*
X * Show explanatory content of `buf', which is a time string as read
X * from the DCF clock.
X */
X
Xvoid show_string(telegram)
Xchar *telegram;
X{
X char *bp;
X
X (void)printf("Got: %s [%d chrs] ", telegram, strlen(telegram));
X bp = telegram + TIME_STATUS_POS;
X (void)printf(" (%s ", bp);
X switch (*(bp + 1))
X {
X case '0': (void)printf("Winter. DCF OK"); break;
X case '1': (void)printf("Summer. DCF OK"); break;
X case '4': (void)printf("Winter. DCF Offline"); break;
X case '5': (void)printf("Summer. DCF Offline"); break;
X case '6': (void)printf("Winter. Manual time"); break;
X default: (void)printf("Unkown ???"); break;
X }
X (void)putchar(')');
X (void)putchar('\n'); (void)fflush(stdout);
X}
X
X/*
X * Show time as we would set it...
X */
X
Xvoid showtime(secs)
Xlong *secs;
X{
X (void)printf((char *)ctime(secs));
X}
X
X
X/*
X * Convert the DCF telegram into a structure of type `tm'. Then
X * convert that into the number of seconds since 1.Jan.1970 00:00
X */
X
Xlong mktm(tgram)
Xchar *tgram;
X{
X static struct tm tm;
X static long now;
X char *bp;
X int j;
X
X (void)time(&now);
X
X bp = tgram;
X
X /*
X * The telegram comes in like this:
X * yy-mm-dd-wd-hh-mm-ss-nn
X * | | | | | | | |
X * | | | | | | | +---- 00 = winter time, 01 = sommertime, etc.
X * | | | | | | +------- Seconds
X * | | | | | +---------- Minutes
X * | | | | +------------- Hour
X * | | | +---------------- Weekday
X * | | +------------------- Day
X * | +---------------------- Month
X * +------------------------- Year
X */
X
X /*
X * Put each value where it belongs. If I don't find a dash between
X * values, the telgram is corrupt! This *should* not occur, because
X * we tested for that before ...
X */
X
X tm.tm_year = ((*bp++ - '0') * 10) + ((*bp++ - '0'));
X if ( *bp++ != '-' )
X return (-1);
X tm.tm_mon = ((*bp++ - '0') * 10) + ((*bp++ - '0'));
X if ( *bp++ != '-' )
X return (-1);
X
X tm.tm_mday = ((*bp++ - '0') * 10) + ((*bp++ - '0'));
X if ( *bp++ != '-' )
X return (-1);
X
X /*
X * Skip over weekday
X */
X bp += 3;
X
X tm.tm_hour = ((*bp++ - '0') * 10) + ((*bp++ - '0'));
X if ( *bp++ != '-' )
X return (-1);
X tm.tm_min = ((*bp++ - '0') * 10) + ((*bp++ - '0'));
X if ( *bp++ != '-' )
X return (-1);
X tm.tm_sec = ((*bp++ - '0') * 10) + ((*bp++ - '0'));
X if ( *bp++ != '-' )
X return (-1);
X
X if (verbose)
X (void)printf("UNIX = %d, ", now );
X
X /*
X * Adjust for month of year
X */
X
X j = 0;
X switch ( tm.tm_mon )
X {
X case 12:
X case 11: j++;
X case 10:
X case 9: j++;
X case 8: j++;
X case 7:
X case 6: j++;
X case 5:
X case 4: j++;
X case 3: if (tm.tm_year % 4)
X j -= 2;
X else --j;
X case 2: j++;
X case 1: break;
X };
X
X /*
X * Are we past year 2000 ?
X */
X
X if (tm.tm_year < 70)
X tm.tm_year += 30;
X else
X tm.tm_year -= 70;
X
X /*
X * Adjust for leap years and the month adjustment
X */
X tm.tm_mday = tm.tm_mday + ((tm.tm_year + 1) / 4) + j;
X
X now = (tm.tm_year * 31536000) + ((tm.tm_mon - 1) * 2592000)
X + ((tm.tm_mday - 1) * 86400) + (tm.tm_hour * 3600)
X + (tm.tm_min * 60) + (tm.tm_sec - ADJUST_SECONDS);
X
X now += tz_adjust;
X
X if (verbose) {
X (void)printf( "DCF = %ld\n", now );
X showtime(&now);
X }
X return (now);
X}
X
Xint quit(sig)
Xint sig;
X{
X char buf[BUFSIZ];
X
X (void)sprintf(buf, "I have been asked to QUIT.Signal=%d. Packing up!", sig);
X mail(buf);
X}
Xint toomanytries()
X{
X char buf[BUFSIZ];
X
X if (verbose)
X printf("Sending mail ...\n");
X
X (void)sprintf(buf,"%s: I have tried %ld times to get a correct time\
X reading from the clock.\nNo luck! Aborting...", progname, MAX_TRIES);
X mail(buf);
X}
END_OF_FILE
if test 11342 -ne `wc -c <'dcf.c'`; then
echo shar: \"'dcf.c'\" unpacked with wrong size!
fi
# end of 'dcf.c'
fi
if test -f 'defs.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'defs.h'\"
else
echo shar: Extracting \"'defs.h'\" \(5051 characters\)
sed "s/^X//" >'defs.h' <<'END_OF_FILE'
X
X/*
X * $Header: /u/tools/etc/dcf/RCS/defs.h,v 1.1 1991/07/25 15:05:21 jpm Exp jpm $
X *
X * $Log: defs.h,v $
X * Revision 1.1 1991/07/25 15:05:21 jpm
X * Initial revision
X *
X *
X */
X
X/*
X * Copyright 1991, Jan-Piet Mens
X * License to freely use and distribute this software is hereby granted
X * by the author, subject to the condition that this copyright notice
X * remains intact. The author retains the exclusive right to publish
X * derivative works based on this work, including, but not limited
X * to, revised versions of this work
X */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <fcntl.h>
X#include <time.h>
X#include <sys/termio.h>
X
X/*--------------------------------------------------------------------------
X | DEFAULT_DEVICE is the `tty' used by default, if none is specified
X | on program startup with the -l option
X --------------------------------------------------------------------------*/
X#define DEFAULT_DEVICE "/dev/tty1h"
X
X/*--------------------------------------------------------------------------
X | DEFAULT_BAUDRATE is the default baudrate that will be set, if no
X | speed is specified with the -s option.
X | Please note, that this speed should be as high as
X | possible.
X | The baudrate is specified as in <termio.h>
X --------------------------------------------------------------------------*/
X#define DEFAULT_BAUDRATE B9600
X/*--------------------------------------------------------------------------
X | POSTMASTER is the problem-solver ;-) on your system. The address
X | will be used by MAIL_COMMAND to send mail.
X --------------------------------------------------------------------------*/
X#define POSTMASTER "postmaster"
X
X/*--------------------------------------------------------------------------
X | MAIL_COMMAND is the command to use for mailing error-conditions
X | The first %s is filled with the message, and the
X | second contains the address to which to post to.
X --------------------------------------------------------------------------*/
X#define MAIL_COMMAND "echo '%s' | mail -s 'DCF CLOCK' %s"
X
X
X/*--------------------------------------------------------------------------
X | NO_LOGGING if this symbol is defined, no logging of time settings
X | and errors will occur. In this case, the symbols
X | LOGFILENAME and LOG_SIZE may be ignored
X --------------------------------------------------------------------------*/
X#undef NO_LOGGING
X
X/*--------------------------------------------------------------------------
X | LOGFILENAME name of the logfile.
X --------------------------------------------------------------------------*/
X#define LOGFILENAME "/etc/dcf.log"
X
X/*--------------------------------------------------------------------------
X | LOG_SIZE gives the size in bytes that the log file will have
X | at most. The log file is circular. It will be kept
X | at a size that should not surpass LOG_SIZE.
X | plus-or-minus a few bytes ;-)
X --------------------------------------------------------------------------*/
X#define LOG_SIZE 2048
X
X/*--------------------------------------------------------------------------
X | MAX_TRIES numeric value. The program will abort, if after
X | MAX_TRIES times, a correct time telegram has not
X | been read from the clock.
X --------------------------------------------------------------------------*/
X#define MAX_TRIES 10
X
X/*--------------------------------------------------------------------------
X | SLEEP_TIME specifies how much time should be slept between
X | time settings. Dcf will start, set the time, and
X | then rest for SLEEP_TIME seconds.
X | At 9600 bd, we need 10 seconds to receive 10 telegrams.
X --------------------------------------------------------------------------*/
X#define SLEEP_TIME (1*60-10)
X
X/*--------------------------------------------------------------------------
X | ADJUST_SECONDS number of seconds to adjust for transmission time
X | between clock and this program. The slower the
X | baudrate, the higher this value. I'm afraid I have
X | no recipe for this ;-)
X --------------------------------------------------------------------------*/
X
X#define ADJUST_SECONDS 0
X
X
X/***** END OF USER CONFIGURABLE SECTION *************************************/
X#define TELEGRAM_LENGTH 23 /* Length of DCF string */
X#define TIME_STATUS_POS 21 /* Position in telegram */
X#ifndef EOS
X# define EOS '\0'
X#endif
X#ifndef TRUE
X# define TRUE (1)
X# define FALSE (0)
X#endif
X#define MAX 50 /* Length of tmp strings */
X
Xextern char progname[];
X
X#ifdef DEBUG
X# define PUT(n) printf("%d\n", (n))
X#else
X# define PUT(n) n
X#endif
X
X
X#if defined(__STDC__) || defined(__cplusplus)
X# define P_(s) s
X#else
X# define P_(s) ()
X#endif
X
X/* dcf.c */
Xint main P_((int argc, char **argv));
Xvoid setup P_((char *device, int baudrate));
Xvoid mail P_((char *message));
Xvoid readtime P_((void));
Xlong mktm P_((char *telegram));
Xint wrong_format P_((char *telegram));
Xvoid show_string P_((char *telegram));
Xvoid showtime P_((long *secs));
Xint quit P_((int));
Xvoid log P_(());
Xvoid write_log P_((char *msg));
X
X#undef P_
END_OF_FILE
if test 5051 -ne `wc -c <'defs.h'`; then
echo shar: \"'defs.h'\" unpacked with wrong size!
fi
# end of 'defs.h'
fi
if test -f 'log.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'log.c'\"
else
echo shar: Extracting \"'log.c'\" \(2213 characters\)
sed "s/^X//" >'log.c' <<'END_OF_FILE'
X/*
X * $Header: /u/tools/etc/dcf/RCS/log.c,v 1.1 1991/07/25 15:05:21 jpm Exp $
X *
X * $Log: log.c,v $
X * Revision 1.1 1991/07/25 15:05:21 jpm
X * Initial revision
X *
X *
X */
X
X#include "defs.h"
X#include "patchlevel.h"
X#include <varargs.h>
X
X/*
X * Copyright 1991, Jan-Piet Mens
X * License to freely use and distribute this software is hereby granted
X * by the author, subject to the condition that this copyright notice
X * remains intact. The author retains the exclusive right to publish
X * derivative works based on this work, including, but not limited
X * to, revised versions of this work
X */
X
X#ifndef NO_LOGGING
X
X/*VARARGS0*/
Xvoid log(va_alist)
Xva_dcl
X{
X va_list args;
X#ifndef lint
X static char rcs_id[] = "$Id: log.c,v 1.1 1991/07/25 15:05:21 jpm Exp $";
X#endif
X char *fmt;
X char buf[BUFSIZ];
X
X va_start(args);
X fmt = va_arg(args, char *);
X vsprintf(buf,fmt,args);
X strcat(buf,"\n");
X
X write_log(buf);
X}
X
Xvoid write_log(msg)
Xchar *msg;
X{
X extern char *calloc();
X static char *mem = (char *)0;
X char *bp;
X int fd;
X long n;
X
X /*
X * Try to open. If not possible, create the logfile, and
X * reopen it.
X */
X
X if ((fd = open(LOGFILENAME, O_RDWR)) == -1)
X {
X if ((fd = creat(LOGFILENAME, 0644)) == -1)
X printf("Cannot open or creat LOG");
X close(fd);
X if ((fd = open(LOGFILENAME, O_RDWR)) == -1)
X printf("Cannot reopen LOG");
X }
X
X n = lseek(fd, 0L, 2); /* Find log size */
X lseek(fd,0L,0); /* Rewind */
X
X if (n < 100)
X n = 1024L;
X
X if ((mem = calloc(n + 10, sizeof(char))) == (char *)0)
X printf("Not enough memory to read LOG");
X
X if ((n = read(fd, mem, n)) < 0) /* Read whole log */
X printf("Read error on LOG");
X
X if (n >= 0)
X mem[n] = EOS; /* Make string */
X
X bp = mem;
X
X if (n >= LOG_SIZE)
X {
X lseek(fd,0L,0); /* Rewind logfile */
X
X /*
X * Find the first nl-terminated string
X */
X
X while ((*bp != EOS) && bp)
X {
X --n;
X if (*bp != '\n')
X {
X ++bp;
X continue;
X }
X ++bp;
X if (n >= LOG_SIZE)
X continue;
X break;
X }
X close(fd);
X fd = open(LOGFILENAME, O_WRONLY|O_TRUNC);
X if (write(fd, bp, strlen(bp)) != strlen(bp))
X printf("write error on LOG");
X }
X
X write(fd, msg, strlen(msg)); /* Write new msg */
X
X free(mem);
X close(fd);
X}
X
X#endif /* NO_LOGGING */
END_OF_FILE
if test 2213 -ne `wc -c <'log.c'`; then
echo shar: \"'log.c'\" unpacked with wrong size!
fi
# end of 'log.c'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(590 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X/*
X * $Header: /u/tools/etc/dcf/RCS/patchlevel.h,v 1.1 1991/07/25 15:05:21 jpm Exp $
X *
X * $Log: patchlevel.h,v $
X * Revision 1.1 1991/07/25 15:05:21 jpm
X * Initial revision
X *
X *
X */
X
X/*
X * Copyright 1991, Jan-Piet Mens
X * License to freely use and distribute this software is hereby granted
X * by the author, subject to the condition that this copyright notice
X * remains intact. The author retains the exclusive right to publish
X * derivative works based on this work, including, but not limited
X * to, revised versions of this work
X */
X
X#define RELEASE 1
X#define PATCHLEVEL 0
END_OF_FILE
if test 590 -ne `wc -c <'patchlevel.h'`; then
echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have the archive.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
Jan-Piet Mens, Logix GmbH j...@logixwi.UUCP
Moritzstr. 50, D-6200 Wiesbaden ...!uunet!mcsun!unido!logixwi!jpm

0 new messages