Home | History | Annotate | Line # | Download | only in parseutil
dcfd.c revision 1.1.1.10
      1   1.1.1.9  christos /*	$NetBSD: dcfd.c,v 1.1.1.10 2024/08/18 20:37:38 christos Exp $	*/
      2   1.1.1.9  christos 
      3       1.1    kardel /*
      4       1.1    kardel  * /src/NTP/REPOSITORY/ntp4-dev/parseutil/dcfd.c,v 4.18 2005/10/07 22:08:18 kardel RELEASE_20051008_A
      5   1.1.1.3  christos  *
      6       1.1    kardel  * dcfd.c,v 4.18 2005/10/07 22:08:18 kardel RELEASE_20051008_A
      7       1.1    kardel  *
      8       1.1    kardel  * DCF77 100/200ms pulse synchronisation daemon program (via 50Baud serial line)
      9       1.1    kardel  *
     10       1.1    kardel  * Features:
     11       1.1    kardel  *  DCF77 decoding
     12       1.1    kardel  *  simple NTP loopfilter logic for local clock
     13       1.1    kardel  *  interactive display for debugging
     14       1.1    kardel  *
     15       1.1    kardel  * Lacks:
     16       1.1    kardel  *  Leap second handling (at that level you should switch to NTP Version 4 - really!)
     17       1.1    kardel  *
     18   1.1.1.4  christos  * Copyright (c) 1995-2015 by Frank Kardel <kardel <AT> ntp.org>
     19   1.1.1.3  christos  * Copyright (c) 1989-1994 by Frank Kardel, Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
     20       1.1    kardel  *
     21       1.1    kardel  * Redistribution and use in source and binary forms, with or without
     22       1.1    kardel  * modification, are permitted provided that the following conditions
     23       1.1    kardel  * are met:
     24       1.1    kardel  * 1. Redistributions of source code must retain the above copyright
     25       1.1    kardel  *    notice, this list of conditions and the following disclaimer.
     26       1.1    kardel  * 2. Redistributions in binary form must reproduce the above copyright
     27       1.1    kardel  *    notice, this list of conditions and the following disclaimer in the
     28       1.1    kardel  *    documentation and/or other materials provided with the distribution.
     29       1.1    kardel  * 3. Neither the name of the author nor the names of its contributors
     30       1.1    kardel  *    may be used to endorse or promote products derived from this software
     31       1.1    kardel  *    without specific prior written permission.
     32       1.1    kardel  *
     33       1.1    kardel  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
     34       1.1    kardel  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     35       1.1    kardel  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     36       1.1    kardel  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     37       1.1    kardel  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     38       1.1    kardel  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     39       1.1    kardel  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     40       1.1    kardel  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     41       1.1    kardel  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     42       1.1    kardel  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     43       1.1    kardel  * SUCH DAMAGE.
     44       1.1    kardel  *
     45       1.1    kardel  */
     46       1.1    kardel 
     47       1.1    kardel #ifdef HAVE_CONFIG_H
     48       1.1    kardel # include <config.h>
     49       1.1    kardel #endif
     50       1.1    kardel 
     51       1.1    kardel #include <sys/ioctl.h>
     52       1.1    kardel #include <unistd.h>
     53       1.1    kardel #include <stdio.h>
     54       1.1    kardel #include <fcntl.h>
     55       1.1    kardel #include <sys/types.h>
     56       1.1    kardel #include <sys/time.h>
     57       1.1    kardel #include <signal.h>
     58       1.1    kardel #include <syslog.h>
     59       1.1    kardel #include <time.h>
     60       1.1    kardel 
     61       1.1    kardel /*
     62       1.1    kardel  * NTP compilation environment
     63       1.1    kardel  */
     64       1.1    kardel #include "ntp_stdlib.h"
     65       1.1    kardel #include "ntpd.h"   /* indirectly include ntp.h to get YEAR_PIVOT   Y2KFixes */
     66       1.1    kardel 
     67       1.1    kardel /*
     68       1.1    kardel  * select which terminal handling to use (currently only SysV variants)
     69       1.1    kardel  */
     70       1.1    kardel #if defined(HAVE_TERMIOS_H) || defined(STREAM)
     71       1.1    kardel #include <termios.h>
     72       1.1    kardel #define TTY_GETATTR(_FD_, _ARG_) tcgetattr((_FD_), (_ARG_))
     73       1.1    kardel #define TTY_SETATTR(_FD_, _ARG_) tcsetattr((_FD_), TCSANOW, (_ARG_))
     74       1.1    kardel #else  /* not HAVE_TERMIOS_H || STREAM */
     75       1.1    kardel # if defined(HAVE_TERMIO_H) || defined(HAVE_SYSV_TTYS)
     76       1.1    kardel #  include <termio.h>
     77       1.1    kardel #  define TTY_GETATTR(_FD_, _ARG_) ioctl((_FD_), TCGETA, (_ARG_))
     78       1.1    kardel #  define TTY_SETATTR(_FD_, _ARG_) ioctl((_FD_), TCSETAW, (_ARG_))
     79       1.1    kardel # endif/* HAVE_TERMIO_H || HAVE_SYSV_TTYS */
     80       1.1    kardel #endif /* not HAVE_TERMIOS_H || STREAM */
     81       1.1    kardel 
     82       1.1    kardel 
     83       1.1    kardel #ifndef TTY_GETATTR
     84       1.1    kardel #include "Bletch: MUST DEFINE ONE OF 'HAVE_TERMIOS_H' or 'HAVE_TERMIO_H'"
     85       1.1    kardel #endif
     86       1.1    kardel 
     87       1.1    kardel #ifndef days_per_year
     88       1.1    kardel #define days_per_year(_x_) (((_x_) % 4) ? 365 : (((_x_) % 400) ? 365 : 366))
     89       1.1    kardel #endif
     90       1.1    kardel 
     91       1.1    kardel #define timernormalize(_a_) \
     92       1.1    kardel 	if ((_a_)->tv_usec >= 1000000) \
     93       1.1    kardel 	{ \
     94       1.1    kardel 		(_a_)->tv_sec  += (_a_)->tv_usec / 1000000; \
     95       1.1    kardel 		(_a_)->tv_usec  = (_a_)->tv_usec % 1000000; \
     96       1.1    kardel 	} \
     97       1.1    kardel 	if ((_a_)->tv_usec < 0) \
     98       1.1    kardel 	{ \
     99       1.1    kardel 		(_a_)->tv_sec  -= 1 + (-(_a_)->tv_usec / 1000000); \
    100       1.1    kardel 		(_a_)->tv_usec = 999999 - (-(_a_)->tv_usec - 1); \
    101       1.1    kardel 	}
    102       1.1    kardel 
    103       1.1    kardel #ifdef timeradd
    104       1.1    kardel #undef timeradd
    105       1.1    kardel #endif
    106       1.1    kardel #define timeradd(_a_, _b_) \
    107       1.1    kardel 	(_a_)->tv_sec  += (_b_)->tv_sec; \
    108       1.1    kardel 	(_a_)->tv_usec += (_b_)->tv_usec; \
    109       1.1    kardel 	timernormalize((_a_))
    110       1.1    kardel 
    111       1.1    kardel #ifdef timersub
    112       1.1    kardel #undef timersub
    113       1.1    kardel #endif
    114       1.1    kardel #define timersub(_a_, _b_) \
    115       1.1    kardel 	(_a_)->tv_sec  -= (_b_)->tv_sec; \
    116       1.1    kardel 	(_a_)->tv_usec -= (_b_)->tv_usec; \
    117       1.1    kardel 	timernormalize((_a_))
    118       1.1    kardel 
    119       1.1    kardel /*
    120       1.1    kardel  * debug macros
    121       1.1    kardel  */
    122       1.1    kardel #define PRINTF if (interactive) printf
    123       1.1    kardel #define LPRINTF if (interactive && loop_filter_debug) printf
    124       1.1    kardel 
    125       1.1    kardel #ifdef DEBUG
    126   1.1.1.9  christos #define DPRINTF(_x_) LPRINTF _x_
    127       1.1    kardel #else
    128   1.1.1.9  christos #define DPRINTF(_x_)
    129       1.1    kardel #endif
    130       1.1    kardel 
    131       1.1    kardel #ifdef DECL_ERRNO
    132       1.1    kardel      extern int errno;
    133       1.1    kardel #endif
    134       1.1    kardel 
    135       1.1    kardel static char *revision = "4.18";
    136       1.1    kardel 
    137       1.1    kardel /*
    138       1.1    kardel  * display received data (avoids also detaching from tty)
    139       1.1    kardel  */
    140       1.1    kardel static int interactive = 0;
    141       1.1    kardel 
    142       1.1    kardel /*
    143       1.1    kardel  * display loopfilter (clock control) variables
    144       1.1    kardel  */
    145       1.1    kardel static int loop_filter_debug = 0;
    146       1.1    kardel 
    147       1.1    kardel /*
    148       1.1    kardel  * do not set/adjust system time
    149       1.1    kardel  */
    150       1.1    kardel static int no_set = 0;
    151       1.1    kardel 
    152       1.1    kardel /*
    153       1.1    kardel  * time that passes between start of DCF impulse and time stamping (fine
    154       1.1    kardel  * adjustment) in microseconds (receiver/OS dependent)
    155       1.1    kardel  */
    156       1.1    kardel #define DEFAULT_DELAY	230000	/* rough estimate */
    157       1.1    kardel 
    158       1.1    kardel /*
    159       1.1    kardel  * The two states we can be in - eithe we receive nothing
    160       1.1    kardel  * usable or we have the correct time
    161       1.1    kardel  */
    162       1.1    kardel #define NO_SYNC		0x01
    163       1.1    kardel #define SYNC		0x02
    164       1.1    kardel 
    165       1.1    kardel static int    sync_state = NO_SYNC;
    166       1.1    kardel static time_t last_sync;
    167       1.1    kardel 
    168       1.1    kardel static unsigned long ticks = 0;
    169       1.1    kardel 
    170       1.1    kardel static char pat[] = "-\\|/";
    171       1.1    kardel 
    172       1.1    kardel #define LINES		(24-2)	/* error lines after which the two headlines are repeated */
    173       1.1    kardel 
    174       1.1    kardel #define MAX_UNSYNC	(10*60)	/* allow synchronisation loss for 10 minutes */
    175       1.1    kardel #define NOTICE_INTERVAL (20*60)	/* mention missing synchronisation every 20 minutes */
    176       1.1    kardel 
    177       1.1    kardel /*
    178       1.1    kardel  * clock adjustment PLL - see NTP protocol spec (RFC1305) for details
    179       1.1    kardel  */
    180       1.1    kardel 
    181       1.1    kardel #define USECSCALE	10
    182       1.1    kardel #define TIMECONSTANT	2
    183       1.1    kardel #define ADJINTERVAL	0
    184       1.1    kardel #define FREQ_WEIGHT	18
    185       1.1    kardel #define PHASE_WEIGHT	7
    186       1.1    kardel #define MAX_DRIFT	0x3FFFFFFF
    187       1.1    kardel 
    188       1.1    kardel #define R_SHIFT(_X_, _Y_) (((_X_) < 0) ? -(-(_X_) >> (_Y_)) : ((_X_) >> (_Y_)))
    189       1.1    kardel 
    190       1.1    kardel static long max_adj_offset_usec = 128000;
    191       1.1    kardel 
    192       1.1    kardel static long clock_adjust = 0;	/* current adjustment value (usec * 2^USECSCALE) */
    193       1.1    kardel static long accum_drift   = 0;	/* accumulated drift value  (usec / ADJINTERVAL) */
    194       1.1    kardel static long adjustments  = 0;
    195       1.1    kardel static char skip_adjust  = 1;	/* discard first adjustment (bad samples) */
    196       1.1    kardel 
    197       1.1    kardel /*
    198       1.1    kardel  * DCF77 state flags
    199       1.1    kardel  */
    200       1.1    kardel #define DCFB_ANNOUNCE		0x0001 /* switch time zone warning (DST switch) */
    201       1.1    kardel #define DCFB_DST		0x0002 /* DST in effect */
    202       1.1    kardel #define DCFB_LEAP		0x0004 /* LEAP warning (1 hour prior to occurrence) */
    203   1.1.1.3  christos #define DCFB_CALLBIT		0x0008 /* "call bit" used to signalize irregularities in the control facilities */
    204       1.1    kardel 
    205       1.1    kardel struct clocktime		/* clock time broken up from time code */
    206       1.1    kardel {
    207       1.1    kardel 	long wday;		/* Day of week: 1: Monday - 7: Sunday */
    208       1.1    kardel 	long day;
    209       1.1    kardel 	long month;
    210       1.1    kardel 	long year;
    211       1.1    kardel 	long hour;
    212       1.1    kardel 	long minute;
    213       1.1    kardel 	long second;
    214       1.1    kardel 	long usecond;
    215       1.1    kardel 	long utcoffset;	/* in minutes */
    216       1.1    kardel 	long flags;		/* current clock status  (DCF77 state flags) */
    217       1.1    kardel };
    218       1.1    kardel 
    219       1.1    kardel typedef struct clocktime clocktime_t;
    220       1.1    kardel 
    221       1.1    kardel /*
    222       1.1    kardel  * (usually) quick constant multiplications
    223       1.1    kardel  */
    224   1.1.1.3  christos #ifndef TIMES10
    225       1.1    kardel #define TIMES10(_X_) (((_X_) << 3) + ((_X_) << 1))	/* *8 + *2 */
    226   1.1.1.3  christos #endif
    227   1.1.1.3  christos #ifndef TIMES24
    228       1.1    kardel #define TIMES24(_X_) (((_X_) << 4) + ((_X_) << 3))      /* *16 + *8 */
    229   1.1.1.3  christos #endif
    230   1.1.1.3  christos #ifndef TIMES60
    231       1.1    kardel #define TIMES60(_X_) ((((_X_) << 4)  - (_X_)) << 2)     /* *(16 - 1) *4 */
    232   1.1.1.3  christos #endif
    233   1.1.1.3  christos 
    234       1.1    kardel /*
    235       1.1    kardel  * generic l_abs() function
    236       1.1    kardel  */
    237       1.1    kardel #define l_abs(_x_)     (((_x_) < 0) ? -(_x_) : (_x_))
    238       1.1    kardel 
    239       1.1    kardel /*
    240       1.1    kardel  * conversion related return/error codes
    241       1.1    kardel  */
    242       1.1    kardel #define CVT_MASK	0x0000000F /* conversion exit code */
    243       1.1    kardel #define   CVT_NONE	0x00000001 /* format not applicable */
    244       1.1    kardel #define   CVT_FAIL	0x00000002 /* conversion failed - error code returned */
    245       1.1    kardel #define   CVT_OK	0x00000004 /* conversion succeeded */
    246       1.1    kardel #define CVT_BADFMT	0x00000010 /* general format error - (unparsable) */
    247       1.1    kardel #define CVT_BADDATE	0x00000020 /* invalid date */
    248       1.1    kardel #define CVT_BADTIME	0x00000040 /* invalid time */
    249       1.1    kardel 
    250       1.1    kardel /*
    251       1.1    kardel  * DCF77 raw time code
    252       1.1    kardel  *
    253       1.1    kardel  * From "Zur Zeit", Physikalisch-Technische Bundesanstalt (PTB), Braunschweig
    254       1.1    kardel  * und Berlin, Maerz 1989
    255       1.1    kardel  *
    256       1.1    kardel  * Timecode transmission:
    257       1.1    kardel  * AM:
    258       1.1    kardel  *	time marks are send every second except for the second before the
    259       1.1    kardel  *	next minute mark
    260       1.1    kardel  *	time marks consist of a reduction of transmitter power to 25%
    261       1.1    kardel  *	of the nominal level
    262       1.1    kardel  *	the falling edge is the time indication (on time)
    263       1.1    kardel  *	time marks of a 100ms duration constitute a logical 0
    264       1.1    kardel  *	time marks of a 200ms duration constitute a logical 1
    265       1.1    kardel  * FM:
    266       1.1    kardel  *	see the spec. (basically a (non-)inverted psuedo random phase shift)
    267       1.1    kardel  *
    268       1.1    kardel  * Encoding:
    269       1.1    kardel  * Second	Contents
    270       1.1    kardel  * 0  - 10	AM: free, FM: 0
    271       1.1    kardel  * 11 - 14	free
    272   1.1.1.3  christos  * 15		R     - "call bit" used to signalize irregularities in the control facilities
    273   1.1.1.3  christos  *		        (until 2003 indicated transmission via alternate antenna)
    274       1.1    kardel  * 16		A1    - expect zone change (1 hour before)
    275       1.1    kardel  * 17 - 18	Z1,Z2 - time zone
    276       1.1    kardel  *		 0  0 illegal
    277       1.1    kardel  *		 0  1 MEZ  (MET)
    278       1.1    kardel  *		 1  0 MESZ (MED, MET DST)
    279       1.1    kardel  *		 1  1 illegal
    280       1.1    kardel  * 19		A2    - expect leap insertion/deletion (1 hour before)
    281       1.1    kardel  * 20		S     - start of time code (1)
    282       1.1    kardel  * 21 - 24	M1    - BCD (lsb first) Minutes
    283       1.1    kardel  * 25 - 27	M10   - BCD (lsb first) 10 Minutes
    284       1.1    kardel  * 28		P1    - Minute Parity (even)
    285       1.1    kardel  * 29 - 32	H1    - BCD (lsb first) Hours
    286       1.1    kardel  * 33 - 34      H10   - BCD (lsb first) 10 Hours
    287       1.1    kardel  * 35		P2    - Hour Parity (even)
    288       1.1    kardel  * 36 - 39	D1    - BCD (lsb first) Days
    289       1.1    kardel  * 40 - 41	D10   - BCD (lsb first) 10 Days
    290       1.1    kardel  * 42 - 44	DW    - BCD (lsb first) day of week (1: Monday -> 7: Sunday)
    291       1.1    kardel  * 45 - 49	MO    - BCD (lsb first) Month
    292       1.1    kardel  * 50           MO0   - 10 Months
    293       1.1    kardel  * 51 - 53	Y1    - BCD (lsb first) Years
    294       1.1    kardel  * 54 - 57	Y10   - BCD (lsb first) 10 Years
    295       1.1    kardel  * 58 		P3    - Date Parity (even)
    296       1.1    kardel  * 59		      - usually missing (minute indication), except for leap insertion
    297       1.1    kardel  */
    298       1.1    kardel 
    299       1.1    kardel /*-----------------------------------------------------------------------
    300       1.1    kardel  * conversion table to map DCF77 bit stream into data fields.
    301       1.1    kardel  * Encoding:
    302       1.1    kardel  *   Each field of the DCF77 code is described with two adjacent entries in
    303       1.1    kardel  *   this table. The first entry specifies the offset into the DCF77 data stream
    304       1.1    kardel  *   while the length is given as the difference between the start index and
    305       1.1    kardel  *   the start index of the following field.
    306       1.1    kardel  */
    307   1.1.1.3  christos static struct rawdcfcode
    308       1.1    kardel {
    309       1.1    kardel 	char offset;			/* start bit */
    310       1.1    kardel } rawdcfcode[] =
    311       1.1    kardel {
    312       1.1    kardel 	{  0 }, { 15 }, { 16 }, { 17 }, { 19 }, { 20 }, { 21 }, { 25 }, { 28 }, { 29 },
    313       1.1    kardel 	{ 33 }, { 35 }, { 36 }, { 40 }, { 42 }, { 45 }, { 49 }, { 50 }, { 54 }, { 58 }, { 59 }
    314       1.1    kardel };
    315       1.1    kardel 
    316       1.1    kardel /*-----------------------------------------------------------------------
    317       1.1    kardel  * symbolic names for the fields of DCF77 describes in "rawdcfcode".
    318       1.1    kardel  * see comment above for the structure of the DCF77 data
    319       1.1    kardel  */
    320       1.1    kardel #define DCF_M	0
    321       1.1    kardel #define DCF_R	1
    322       1.1    kardel #define DCF_A1	2
    323       1.1    kardel #define DCF_Z	3
    324       1.1    kardel #define DCF_A2	4
    325       1.1    kardel #define DCF_S	5
    326       1.1    kardel #define DCF_M1	6
    327       1.1    kardel #define DCF_M10	7
    328       1.1    kardel #define DCF_P1	8
    329       1.1    kardel #define DCF_H1	9
    330       1.1    kardel #define DCF_H10	10
    331       1.1    kardel #define DCF_P2	11
    332       1.1    kardel #define DCF_D1	12
    333       1.1    kardel #define DCF_D10	13
    334       1.1    kardel #define DCF_DW	14
    335       1.1    kardel #define DCF_MO	15
    336       1.1    kardel #define DCF_MO0	16
    337       1.1    kardel #define DCF_Y1	17
    338       1.1    kardel #define DCF_Y10	18
    339       1.1    kardel #define DCF_P3	19
    340       1.1    kardel 
    341       1.1    kardel /*-----------------------------------------------------------------------
    342       1.1    kardel  * parity field table (same encoding as rawdcfcode)
    343       1.1    kardel  * This table describes the sections of the DCF77 code that are
    344       1.1    kardel  * parity protected
    345       1.1    kardel  */
    346       1.1    kardel static struct partab
    347       1.1    kardel {
    348       1.1    kardel 	char offset;			/* start bit of parity field */
    349       1.1    kardel } partab[] =
    350       1.1    kardel {
    351       1.1    kardel 	{ 21 }, { 29 }, { 36 }, { 59 }
    352       1.1    kardel };
    353       1.1    kardel 
    354       1.1    kardel /*-----------------------------------------------------------------------
    355       1.1    kardel  * offsets for parity field descriptions
    356       1.1    kardel  */
    357       1.1    kardel #define DCF_P_P1	0
    358       1.1    kardel #define DCF_P_P2	1
    359       1.1    kardel #define DCF_P_P3	2
    360       1.1    kardel 
    361       1.1    kardel /*-----------------------------------------------------------------------
    362       1.1    kardel  * legal values for time zone information
    363       1.1    kardel  */
    364       1.1    kardel #define DCF_Z_MET 0x2
    365       1.1    kardel #define DCF_Z_MED 0x1
    366       1.1    kardel 
    367       1.1    kardel /*-----------------------------------------------------------------------
    368       1.1    kardel  * symbolic representation if the DCF77 data stream
    369       1.1    kardel  */
    370       1.1    kardel static struct dcfparam
    371       1.1    kardel {
    372       1.1    kardel 	unsigned char onebits[60];
    373       1.1    kardel 	unsigned char zerobits[60];
    374   1.1.1.3  christos } dcfparam =
    375       1.1    kardel {
    376       1.1    kardel 	"###############RADMLS1248124P124812P1248121241248112481248P", /* 'ONE' representation */
    377       1.1    kardel 	"--------------------s-------p------p----------------------p"  /* 'ZERO' representation */
    378       1.1    kardel };
    379       1.1    kardel 
    380       1.1    kardel /*-----------------------------------------------------------------------
    381       1.1    kardel  * extract a bitfield from DCF77 datastream
    382       1.1    kardel  * All numeric fields are LSB first.
    383       1.1    kardel  * buf holds a pointer to a DCF77 data buffer in symbolic
    384       1.1    kardel  *     representation
    385       1.1    kardel  * idx holds the index to the field description in rawdcfcode
    386       1.1    kardel  */
    387       1.1    kardel static unsigned long
    388       1.1    kardel ext_bf(
    389       1.1    kardel 	register unsigned char *buf,
    390       1.1    kardel 	register int   idx
    391       1.1    kardel 	)
    392       1.1    kardel {
    393       1.1    kardel 	register unsigned long sum = 0;
    394       1.1    kardel 	register int i, first;
    395       1.1    kardel 
    396       1.1    kardel 	first = rawdcfcode[idx].offset;
    397   1.1.1.3  christos 
    398       1.1    kardel 	for (i = rawdcfcode[idx+1].offset - 1; i >= first; i--)
    399       1.1    kardel 	{
    400       1.1    kardel 		sum <<= 1;
    401       1.1    kardel 		sum |= (buf[i] != dcfparam.zerobits[i]);
    402       1.1    kardel 	}
    403       1.1    kardel 	return sum;
    404       1.1    kardel }
    405       1.1    kardel 
    406       1.1    kardel /*-----------------------------------------------------------------------
    407       1.1    kardel  * check even parity integrity for a bitfield
    408       1.1    kardel  *
    409       1.1    kardel  * buf holds a pointer to a DCF77 data buffer in symbolic
    410       1.1    kardel  *     representation
    411       1.1    kardel  * idx holds the index to the field description in partab
    412       1.1    kardel  */
    413       1.1    kardel static unsigned
    414       1.1    kardel pcheck(
    415       1.1    kardel 	register unsigned char *buf,
    416       1.1    kardel 	register int   idx
    417       1.1    kardel 	)
    418       1.1    kardel {
    419       1.1    kardel 	register int i,last;
    420       1.1    kardel 	register unsigned psum = 1;
    421       1.1    kardel 
    422       1.1    kardel 	last = partab[idx+1].offset;
    423       1.1    kardel 
    424       1.1    kardel 	for (i = partab[idx].offset; i < last; i++)
    425       1.1    kardel 	    psum ^= (buf[i] != dcfparam.zerobits[i]);
    426       1.1    kardel 
    427       1.1    kardel 	return psum;
    428       1.1    kardel }
    429       1.1    kardel 
    430       1.1    kardel /*-----------------------------------------------------------------------
    431       1.1    kardel  * convert a DCF77 data buffer into wall clock time + flags
    432       1.1    kardel  *
    433       1.1    kardel  * buffer holds a pointer to a DCF77 data buffer in symbolic
    434       1.1    kardel  *        representation
    435       1.1    kardel  * size   describes the length of DCF77 information in bits (represented
    436       1.1    kardel  *        as chars in symbolic notation
    437       1.1    kardel  * clock  points to a wall clock time description of the DCF77 data (result)
    438       1.1    kardel  */
    439       1.1    kardel static unsigned long
    440       1.1    kardel convert_rawdcf(
    441       1.1    kardel 	       unsigned char   *buffer,
    442       1.1    kardel 	       int              size,
    443       1.1    kardel 	       clocktime_t     *clock_time
    444       1.1    kardel 	       )
    445       1.1    kardel {
    446       1.1    kardel 	if (size < 57)
    447       1.1    kardel 	{
    448       1.1    kardel 		PRINTF("%-30s", "*** INCOMPLETE");
    449       1.1    kardel 		return CVT_NONE;
    450       1.1    kardel 	}
    451   1.1.1.3  christos 
    452       1.1    kardel 	/*
    453       1.1    kardel 	 * check Start and Parity bits
    454       1.1    kardel 	 */
    455       1.1    kardel 	if ((ext_bf(buffer, DCF_S) == 1) &&
    456       1.1    kardel 	    pcheck(buffer, DCF_P_P1) &&
    457       1.1    kardel 	    pcheck(buffer, DCF_P_P2) &&
    458       1.1    kardel 	    pcheck(buffer, DCF_P_P3))
    459       1.1    kardel 	{
    460       1.1    kardel 		/*
    461       1.1    kardel 		 * buffer OK - extract all fields and build wall clock time from them
    462       1.1    kardel 		 */
    463       1.1    kardel 
    464       1.1    kardel 		clock_time->flags  = 0;
    465       1.1    kardel 		clock_time->usecond= 0;
    466       1.1    kardel 		clock_time->second = 0;
    467       1.1    kardel 		clock_time->minute = ext_bf(buffer, DCF_M10);
    468       1.1    kardel 		clock_time->minute = TIMES10(clock_time->minute) + ext_bf(buffer, DCF_M1);
    469       1.1    kardel 		clock_time->hour   = ext_bf(buffer, DCF_H10);
    470       1.1    kardel 		clock_time->hour   = TIMES10(clock_time->hour)   + ext_bf(buffer, DCF_H1);
    471       1.1    kardel 		clock_time->day    = ext_bf(buffer, DCF_D10);
    472       1.1    kardel 		clock_time->day    = TIMES10(clock_time->day)    + ext_bf(buffer, DCF_D1);
    473       1.1    kardel 		clock_time->month  = ext_bf(buffer, DCF_MO0);
    474       1.1    kardel 		clock_time->month  = TIMES10(clock_time->month)  + ext_bf(buffer, DCF_MO);
    475       1.1    kardel 		clock_time->year   = ext_bf(buffer, DCF_Y10);
    476       1.1    kardel 		clock_time->year   = TIMES10(clock_time->year)   + ext_bf(buffer, DCF_Y1);
    477       1.1    kardel 		clock_time->wday   = ext_bf(buffer, DCF_DW);
    478       1.1    kardel 
    479       1.1    kardel 		/*
    480       1.1    kardel 		 * determine offset to UTC by examining the time zone
    481       1.1    kardel 		 */
    482       1.1    kardel 		switch (ext_bf(buffer, DCF_Z))
    483       1.1    kardel 		{
    484       1.1    kardel 		    case DCF_Z_MET:
    485       1.1    kardel 			clock_time->utcoffset = -60;
    486       1.1    kardel 			break;
    487       1.1    kardel 
    488       1.1    kardel 		    case DCF_Z_MED:
    489       1.1    kardel 			clock_time->flags     |= DCFB_DST;
    490       1.1    kardel 			clock_time->utcoffset  = -120;
    491       1.1    kardel 			break;
    492       1.1    kardel 
    493       1.1    kardel 		    default:
    494       1.1    kardel 			PRINTF("%-30s", "*** BAD TIME ZONE");
    495       1.1    kardel 			return CVT_FAIL|CVT_BADFMT;
    496       1.1    kardel 		}
    497       1.1    kardel 
    498       1.1    kardel 		/*
    499       1.1    kardel 		 * extract various warnings from DCF77
    500       1.1    kardel 		 */
    501       1.1    kardel 		if (ext_bf(buffer, DCF_A1))
    502       1.1    kardel 		    clock_time->flags |= DCFB_ANNOUNCE;
    503       1.1    kardel 
    504       1.1    kardel 		if (ext_bf(buffer, DCF_A2))
    505       1.1    kardel 		    clock_time->flags |= DCFB_LEAP;
    506       1.1    kardel 
    507       1.1    kardel 		if (ext_bf(buffer, DCF_R))
    508   1.1.1.3  christos 		    clock_time->flags |= DCFB_CALLBIT;
    509       1.1    kardel 
    510       1.1    kardel 		return CVT_OK;
    511       1.1    kardel 	}
    512       1.1    kardel 	else
    513       1.1    kardel 	{
    514       1.1    kardel 		/*
    515       1.1    kardel 		 * bad format - not for us
    516       1.1    kardel 		 */
    517       1.1    kardel 		PRINTF("%-30s", "*** BAD FORMAT (invalid/parity)");
    518       1.1    kardel 		return CVT_FAIL|CVT_BADFMT;
    519       1.1    kardel 	}
    520       1.1    kardel }
    521       1.1    kardel 
    522       1.1    kardel /*-----------------------------------------------------------------------
    523       1.1    kardel  * raw dcf input routine - fix up 50 baud
    524       1.1    kardel  * characters for 1/0 decision
    525       1.1    kardel  */
    526       1.1    kardel static unsigned long
    527       1.1    kardel cvt_rawdcf(
    528       1.1    kardel 	   unsigned char   *buffer,
    529       1.1    kardel 	   int              size,
    530       1.1    kardel 	   clocktime_t     *clock_time
    531       1.1    kardel 	   )
    532       1.1    kardel {
    533       1.1    kardel 	register unsigned char *s = buffer;
    534       1.1    kardel 	register unsigned char *e = buffer + size;
    535       1.1    kardel 	register unsigned char *b = dcfparam.onebits;
    536       1.1    kardel 	register unsigned char *c = dcfparam.zerobits;
    537       1.1    kardel 	register unsigned rtc = CVT_NONE;
    538       1.1    kardel 	register unsigned int i, lowmax, highmax, cutoff, span;
    539       1.1    kardel #define BITS 9
    540       1.1    kardel 	unsigned char     histbuf[BITS];
    541       1.1    kardel 	/*
    542       1.1    kardel 	 * the input buffer contains characters with runs of consecutive
    543       1.1    kardel 	 * bits set. These set bits are an indication of the DCF77 pulse
    544       1.1    kardel 	 * length. We assume that we receive the pulse at 50 Baud. Thus
    545       1.1    kardel 	 * a 100ms pulse would generate a 4 bit train (20ms per bit and
    546       1.1    kardel 	 * start bit)
    547       1.1    kardel 	 * a 200ms pulse would create all zeroes (and probably a frame error)
    548       1.1    kardel 	 *
    549       1.1    kardel 	 * The basic idea is that on corret reception we must have two
    550       1.1    kardel 	 * maxima in the pulse length distribution histogram. (one for
    551       1.1    kardel 	 * the zero representing pulses and one for the one representing
    552       1.1    kardel 	 * pulses)
    553       1.1    kardel 	 * There will always be ones in the datastream, thus we have to see
    554       1.1    kardel 	 * two maxima.
    555       1.1    kardel 	 * The best point to cut for a 1/0 decision is the minimum between those
    556       1.1    kardel 	 * between the maxima. The following code tries to find this cutoff point.
    557       1.1    kardel 	 */
    558       1.1    kardel 
    559       1.1    kardel 	/*
    560       1.1    kardel 	 * clear histogram buffer
    561       1.1    kardel 	 */
    562       1.1    kardel 	for (i = 0; i < BITS; i++)
    563       1.1    kardel 	{
    564       1.1    kardel 		histbuf[i] = 0;
    565       1.1    kardel 	}
    566       1.1    kardel 
    567       1.1    kardel 	cutoff = 0;
    568       1.1    kardel 	lowmax = 0;
    569       1.1    kardel 
    570       1.1    kardel 	/*
    571       1.1    kardel 	 * convert sequences of set bits into bits counts updating
    572       1.1    kardel 	 * the histogram alongway
    573       1.1    kardel 	 */
    574       1.1    kardel 	while (s < e)
    575       1.1    kardel 	{
    576       1.1    kardel 		register unsigned int ch = *s ^ 0xFF;
    577       1.1    kardel 		/*
    578       1.1    kardel 		 * check integrity and update histogramm
    579       1.1    kardel 		 */
    580       1.1    kardel 		if (!((ch+1) & ch) || !*s)
    581       1.1    kardel 		{
    582       1.1    kardel 			/*
    583       1.1    kardel 			 * character ok
    584       1.1    kardel 			 */
    585       1.1    kardel 			for (i = 0; ch; i++)
    586       1.1    kardel 			{
    587       1.1    kardel 				ch >>= 1;
    588       1.1    kardel 			}
    589       1.1    kardel 
    590       1.1    kardel 			*s = i;
    591       1.1    kardel 			histbuf[i]++;
    592       1.1    kardel 			cutoff += i;
    593       1.1    kardel 			lowmax++;
    594       1.1    kardel 		}
    595       1.1    kardel 		else
    596       1.1    kardel 		{
    597       1.1    kardel 			/*
    598       1.1    kardel 			 * invalid character (no consecutive bit sequence)
    599       1.1    kardel 			 */
    600   1.1.1.9  christos 			DPRINTF(("parse: cvt_rawdcf: character check for 0x%x@%ld FAILED\n",
    601   1.1.1.2  christos 				 (u_int)*s, (long)(s - buffer)));
    602       1.1    kardel 			*s = (unsigned char)~0;
    603       1.1    kardel 			rtc = CVT_FAIL|CVT_BADFMT;
    604       1.1    kardel 		}
    605       1.1    kardel 		s++;
    606       1.1    kardel 	}
    607       1.1    kardel 
    608       1.1    kardel 	/*
    609       1.1    kardel 	 * first cutoff estimate (average bit count - must be between both
    610       1.1    kardel 	 * maxima)
    611       1.1    kardel 	 */
    612       1.1    kardel 	if (lowmax)
    613       1.1    kardel 	{
    614       1.1    kardel 		cutoff /= lowmax;
    615       1.1    kardel 	}
    616       1.1    kardel 	else
    617       1.1    kardel 	{
    618       1.1    kardel 		cutoff = 4;	/* doesn't really matter - it'll fail anyway, but gives error output */
    619       1.1    kardel 	}
    620       1.1    kardel 
    621   1.1.1.9  christos 	DPRINTF(("parse: cvt_rawdcf: average bit count: %d\n", cutoff));
    622       1.1    kardel 
    623       1.1    kardel 	lowmax = 0;  /* weighted sum */
    624       1.1    kardel 	highmax = 0; /* bitcount */
    625       1.1    kardel 
    626       1.1    kardel 	/*
    627       1.1    kardel 	 * collect weighted sum of lower bits (left of initial guess)
    628       1.1    kardel 	 */
    629   1.1.1.9  christos 	DPRINTF(("parse: cvt_rawdcf: histogram:"));
    630       1.1    kardel 	for (i = 0; i <= cutoff; i++)
    631       1.1    kardel 	{
    632       1.1    kardel 		lowmax  += histbuf[i] * i;
    633       1.1    kardel 		highmax += histbuf[i];
    634   1.1.1.9  christos 		DPRINTF((" %d", histbuf[i]));
    635       1.1    kardel 	}
    636   1.1.1.9  christos 	DPRINTF((" <M>"));
    637       1.1    kardel 
    638       1.1    kardel 	/*
    639       1.1    kardel 	 * round up
    640       1.1    kardel 	 */
    641       1.1    kardel 	lowmax += highmax / 2;
    642       1.1    kardel 
    643       1.1    kardel 	/*
    644       1.1    kardel 	 * calculate lower bit maximum (weighted sum / bit count)
    645       1.1    kardel 	 *
    646       1.1    kardel 	 * avoid divide by zero
    647       1.1    kardel 	 */
    648       1.1    kardel 	if (highmax)
    649       1.1    kardel 	{
    650       1.1    kardel 		lowmax /= highmax;
    651       1.1    kardel 	}
    652       1.1    kardel 	else
    653       1.1    kardel 	{
    654       1.1    kardel 		lowmax = 0;
    655       1.1    kardel 	}
    656       1.1    kardel 
    657       1.1    kardel 	highmax = 0; /* weighted sum of upper bits counts */
    658       1.1    kardel 	cutoff = 0;  /* bitcount */
    659       1.1    kardel 
    660       1.1    kardel 	/*
    661       1.1    kardel 	 * collect weighted sum of lower bits (right of initial guess)
    662       1.1    kardel 	 */
    663       1.1    kardel 	for (; i < BITS; i++)
    664       1.1    kardel 	{
    665       1.1    kardel 		highmax+=histbuf[i] * i;
    666       1.1    kardel 		cutoff +=histbuf[i];
    667   1.1.1.9  christos 		DPRINTF((" %d", histbuf[i]));
    668       1.1    kardel 	}
    669   1.1.1.9  christos 	DPRINTF(("\n"));
    670       1.1    kardel 
    671       1.1    kardel 	/*
    672       1.1    kardel 	 * determine upper maximum (weighted sum / bit count)
    673       1.1    kardel 	 */
    674       1.1    kardel 	if (cutoff)
    675       1.1    kardel 	{
    676       1.1    kardel 		highmax /= cutoff;
    677       1.1    kardel 	}
    678       1.1    kardel 	else
    679       1.1    kardel 	{
    680       1.1    kardel 		highmax = BITS-1;
    681       1.1    kardel 	}
    682       1.1    kardel 
    683       1.1    kardel 	/*
    684       1.1    kardel 	 * following now holds:
    685       1.1    kardel 	 * lowmax <= cutoff(initial guess) <= highmax
    686       1.1    kardel 	 * best cutoff is the minimum nearest to higher bits
    687       1.1    kardel 	 */
    688       1.1    kardel 
    689       1.1    kardel 	/*
    690       1.1    kardel 	 * find the minimum between lowmax and highmax (detecting
    691       1.1    kardel 	 * possibly a minimum span)
    692       1.1    kardel 	 */
    693       1.1    kardel 	span = cutoff = lowmax;
    694       1.1    kardel 	for (i = lowmax; i <= highmax; i++)
    695       1.1    kardel 	{
    696       1.1    kardel 		if (histbuf[cutoff] > histbuf[i])
    697       1.1    kardel 		{
    698       1.1    kardel 			/*
    699       1.1    kardel 			 * got a new minimum move beginning of minimum (cutoff) and
    700       1.1    kardel 			 * end of minimum (span) there
    701       1.1    kardel 			 */
    702       1.1    kardel 			cutoff = span = i;
    703       1.1    kardel 		}
    704       1.1    kardel 		else
    705       1.1    kardel 		    if (histbuf[cutoff] == histbuf[i])
    706       1.1    kardel 		    {
    707       1.1    kardel 			    /*
    708       1.1    kardel 			     * minimum not better yet - but it spans more than
    709       1.1    kardel 			     * one bit value - follow it
    710       1.1    kardel 			     */
    711       1.1    kardel 			    span = i;
    712       1.1    kardel 		    }
    713       1.1    kardel 	}
    714       1.1    kardel 
    715       1.1    kardel 	/*
    716       1.1    kardel 	 * cutoff point for 1/0 decision is the middle of the minimum section
    717       1.1    kardel 	 * in the histogram
    718       1.1    kardel 	 */
    719       1.1    kardel 	cutoff = (cutoff + span) / 2;
    720       1.1    kardel 
    721   1.1.1.9  christos 	DPRINTF(("parse: cvt_rawdcf: lower maximum %d, higher maximum %d, cutoff %d\n", lowmax, highmax, cutoff));
    722       1.1    kardel 
    723       1.1    kardel 	/*
    724       1.1    kardel 	 * convert the bit counts to symbolic 1/0 information for data conversion
    725       1.1    kardel 	 */
    726       1.1    kardel 	s = buffer;
    727       1.1    kardel 	while ((s < e) && *c && *b)
    728       1.1    kardel 	{
    729       1.1    kardel 		if (*s == (unsigned char)~0)
    730       1.1    kardel 		{
    731       1.1    kardel 			/*
    732       1.1    kardel 			 * invalid character
    733       1.1    kardel 			 */
    734       1.1    kardel 			*s = '?';
    735       1.1    kardel 		}
    736       1.1    kardel 		else
    737       1.1    kardel 		{
    738       1.1    kardel 			/*
    739       1.1    kardel 			 * symbolic 1/0 representation
    740       1.1    kardel 			 */
    741       1.1    kardel 			*s = (*s >= cutoff) ? *b : *c;
    742       1.1    kardel 		}
    743       1.1    kardel 		s++;
    744       1.1    kardel 		b++;
    745       1.1    kardel 		c++;
    746       1.1    kardel 	}
    747       1.1    kardel 
    748       1.1    kardel 	/*
    749       1.1    kardel 	 * if everything went well so far return the result of the symbolic
    750       1.1    kardel 	 * conversion routine else just the accumulated errors
    751       1.1    kardel 	 */
    752   1.1.1.3  christos 	if (rtc != CVT_NONE)
    753       1.1    kardel 	{
    754       1.1    kardel 		PRINTF("%-30s", "*** BAD DATA");
    755       1.1    kardel 	}
    756       1.1    kardel 
    757       1.1    kardel 	return (rtc == CVT_NONE) ? convert_rawdcf(buffer, size, clock_time) : rtc;
    758       1.1    kardel }
    759       1.1    kardel 
    760       1.1    kardel /*-----------------------------------------------------------------------
    761       1.1    kardel  * convert a wall clock time description of DCF77 to a Unix time (seconds
    762       1.1    kardel  * since 1.1. 1970 UTC)
    763       1.1    kardel  */
    764       1.1    kardel static time_t
    765       1.1    kardel dcf_to_unixtime(
    766       1.1    kardel 		clocktime_t   *clock_time,
    767       1.1    kardel 		unsigned *cvtrtc
    768       1.1    kardel 		)
    769       1.1    kardel {
    770       1.1    kardel #define SETRTC(_X_)	{ if (cvtrtc) *cvtrtc = (_X_); }
    771   1.1.1.3  christos 	static int days_of_month[] =
    772       1.1    kardel 	{
    773       1.1    kardel 		0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    774       1.1    kardel 	};
    775       1.1    kardel 	register int i;
    776       1.1    kardel 	time_t t;
    777   1.1.1.3  christos 
    778       1.1    kardel 	/*
    779       1.1    kardel 	 * map 2 digit years to 19xx (DCF77 is a 20th century item)
    780       1.1    kardel 	 */
    781       1.1    kardel 	if ( clock_time->year < YEAR_PIVOT ) 	/* in case of	   Y2KFixes [ */
    782       1.1    kardel 		clock_time->year += 100;	/* *year%100, make tm_year */
    783       1.1    kardel 						/* *(do we need this?) */
    784       1.1    kardel 	if ( clock_time->year < YEAR_BREAK )	/* (failsafe if) */
    785       1.1    kardel 	    clock_time->year += 1900;				/* Y2KFixes ] */
    786       1.1    kardel 
    787       1.1    kardel 	/*
    788       1.1    kardel 	 * must have been a really bad year code - drop it
    789       1.1    kardel 	 */
    790       1.1    kardel 	if (clock_time->year < (YEAR_PIVOT + 1900) )		/* Y2KFixes */
    791       1.1    kardel 	{
    792       1.1    kardel 		SETRTC(CVT_FAIL|CVT_BADDATE);
    793       1.1    kardel 		return -1;
    794       1.1    kardel 	}
    795       1.1    kardel 	/*
    796       1.1    kardel 	 * sorry, slow section here - but it's not time critical anyway
    797       1.1    kardel 	 */
    798       1.1    kardel 
    799       1.1    kardel 	/*
    800       1.1    kardel 	 * calculate days since 1970 (watching leap years)
    801       1.1    kardel 	 */
    802       1.1    kardel 	t = julian0( clock_time->year ) - julian0( 1970 );
    803       1.1    kardel 
    804       1.1    kardel   				/* month */
    805       1.1    kardel 	if (clock_time->month <= 0 || clock_time->month > 12)
    806       1.1    kardel 	{
    807       1.1    kardel 		SETRTC(CVT_FAIL|CVT_BADDATE);
    808       1.1    kardel 		return -1;		/* bad month */
    809       1.1    kardel 	}
    810       1.1    kardel 				/* adjust current leap year */
    811       1.1    kardel #if 0
    812       1.1    kardel 	if (clock_time->month < 3 && days_per_year(clock_time->year) == 366)
    813       1.1    kardel 	    t--;
    814       1.1    kardel #endif
    815       1.1    kardel 
    816       1.1    kardel 	/*
    817       1.1    kardel 	 * collect days from months excluding the current one
    818       1.1    kardel 	 */
    819       1.1    kardel 	for (i = 1; i < clock_time->month; i++)
    820       1.1    kardel 	{
    821       1.1    kardel 		t += days_of_month[i];
    822       1.1    kardel 	}
    823       1.1    kardel 				/* day */
    824       1.1    kardel 	if (clock_time->day < 1 || ((clock_time->month == 2 && days_per_year(clock_time->year) == 366) ?
    825       1.1    kardel 			       clock_time->day > 29 : clock_time->day > days_of_month[clock_time->month]))
    826       1.1    kardel 	{
    827       1.1    kardel 		SETRTC(CVT_FAIL|CVT_BADDATE);
    828       1.1    kardel 		return -1;		/* bad day */
    829       1.1    kardel 	}
    830       1.1    kardel 
    831       1.1    kardel 	/*
    832       1.1    kardel 	 * collect days from date excluding the current one
    833       1.1    kardel 	 */
    834       1.1    kardel 	t += clock_time->day - 1;
    835       1.1    kardel 
    836       1.1    kardel 				/* hour */
    837       1.1    kardel 	if (clock_time->hour < 0 || clock_time->hour >= 24)
    838       1.1    kardel 	{
    839       1.1    kardel 		SETRTC(CVT_FAIL|CVT_BADTIME);
    840       1.1    kardel 		return -1;		/* bad hour */
    841       1.1    kardel 	}
    842       1.1    kardel 
    843       1.1    kardel 	/*
    844       1.1    kardel 	 * calculate hours from 1. 1. 1970
    845       1.1    kardel 	 */
    846       1.1    kardel 	t = TIMES24(t) + clock_time->hour;
    847       1.1    kardel 
    848       1.1    kardel   				/* min */
    849       1.1    kardel 	if (clock_time->minute < 0 || clock_time->minute > 59)
    850       1.1    kardel 	{
    851       1.1    kardel 		SETRTC(CVT_FAIL|CVT_BADTIME);
    852       1.1    kardel 		return -1;		/* bad min */
    853       1.1    kardel 	}
    854       1.1    kardel 
    855       1.1    kardel 	/*
    856       1.1    kardel 	 * calculate minutes from 1. 1. 1970
    857       1.1    kardel 	 */
    858       1.1    kardel 	t = TIMES60(t) + clock_time->minute;
    859       1.1    kardel 				/* sec */
    860   1.1.1.3  christos 
    861       1.1    kardel 	/*
    862       1.1    kardel 	 * calculate UTC in minutes
    863       1.1    kardel 	 */
    864       1.1    kardel 	t += clock_time->utcoffset;
    865       1.1    kardel 
    866       1.1    kardel 	if (clock_time->second < 0 || clock_time->second > 60)	/* allow for LEAPs */
    867       1.1    kardel 	{
    868       1.1    kardel 		SETRTC(CVT_FAIL|CVT_BADTIME);
    869       1.1    kardel 		return -1;		/* bad sec */
    870       1.1    kardel 	}
    871       1.1    kardel 
    872       1.1    kardel 	/*
    873       1.1    kardel 	 * calculate UTC in seconds - phew !
    874       1.1    kardel 	 */
    875       1.1    kardel 	t  = TIMES60(t) + clock_time->second;
    876       1.1    kardel 				/* done */
    877       1.1    kardel 	return t;
    878       1.1    kardel }
    879       1.1    kardel 
    880       1.1    kardel /*-----------------------------------------------------------------------
    881       1.1    kardel  * cheap half baked 1/0 decision - for interactive operation only
    882       1.1    kardel  */
    883       1.1    kardel static char
    884       1.1    kardel type(
    885       1.1    kardel      unsigned int c
    886       1.1    kardel      )
    887       1.1    kardel {
    888       1.1    kardel 	c ^= 0xFF;
    889       1.1    kardel 	return (c > 0xF);
    890       1.1    kardel }
    891       1.1    kardel 
    892       1.1    kardel /*-----------------------------------------------------------------------
    893       1.1    kardel  * week day representation
    894       1.1    kardel  */
    895       1.1    kardel static const char *wday[8] =
    896       1.1    kardel {
    897       1.1    kardel 	"??",
    898       1.1    kardel 	"Mo",
    899       1.1    kardel 	"Tu",
    900       1.1    kardel 	"We",
    901       1.1    kardel 	"Th",
    902       1.1    kardel 	"Fr",
    903       1.1    kardel 	"Sa",
    904       1.1    kardel 	"Su"
    905       1.1    kardel };
    906       1.1    kardel 
    907       1.1    kardel /*-----------------------------------------------------------------------
    908       1.1    kardel  * generate a string representation for a timeval
    909       1.1    kardel  */
    910       1.1    kardel static char *
    911       1.1    kardel pr_timeval(
    912   1.1.1.2  christos 	struct timeval *val
    913   1.1.1.2  christos 	)
    914       1.1    kardel {
    915       1.1    kardel 	static char buf[20];
    916       1.1    kardel 
    917       1.1    kardel 	if (val->tv_sec == 0)
    918   1.1.1.2  christos 		snprintf(buf, sizeof(buf), "%c0.%06ld",
    919   1.1.1.2  christos 			 (val->tv_usec < 0) ? '-' : '+',
    920   1.1.1.2  christos 			 (long int)l_abs(val->tv_usec));
    921       1.1    kardel 	else
    922   1.1.1.2  christos 		snprintf(buf, sizeof(buf), "%ld.%06ld",
    923   1.1.1.2  christos 			 (long int)val->tv_sec,
    924   1.1.1.2  christos 			 (long int)l_abs(val->tv_usec));
    925       1.1    kardel 	return buf;
    926       1.1    kardel }
    927       1.1    kardel 
    928       1.1    kardel /*-----------------------------------------------------------------------
    929       1.1    kardel  * correct the current time by an offset by setting the time rigorously
    930       1.1    kardel  */
    931       1.1    kardel static void
    932       1.1    kardel set_time(
    933       1.1    kardel 	 struct timeval *offset
    934       1.1    kardel 	 )
    935       1.1    kardel {
    936       1.1    kardel 	struct timeval the_time;
    937       1.1    kardel 
    938       1.1    kardel 	if (no_set)
    939       1.1    kardel 	    return;
    940       1.1    kardel 
    941       1.1    kardel 	LPRINTF("set_time: %s ", pr_timeval(offset));
    942       1.1    kardel 	syslog(LOG_NOTICE, "setting time (offset %s)", pr_timeval(offset));
    943       1.1    kardel 
    944       1.1    kardel 	if (gettimeofday(&the_time, 0L) == -1)
    945       1.1    kardel 	{
    946       1.1    kardel 		perror("gettimeofday()");
    947       1.1    kardel 	}
    948       1.1    kardel 	else
    949       1.1    kardel 	{
    950       1.1    kardel 		timeradd(&the_time, offset);
    951       1.1    kardel 		if (settimeofday(&the_time, 0L) == -1)
    952       1.1    kardel 		{
    953       1.1    kardel 			perror("settimeofday()");
    954       1.1    kardel 		}
    955       1.1    kardel 	}
    956       1.1    kardel }
    957       1.1    kardel 
    958       1.1    kardel /*-----------------------------------------------------------------------
    959       1.1    kardel  * slew the time by a given offset
    960       1.1    kardel  */
    961       1.1    kardel static void
    962       1.1    kardel adj_time(
    963       1.1    kardel 	 long offset
    964       1.1    kardel 	 )
    965       1.1    kardel {
    966       1.1    kardel 	struct timeval time_offset;
    967       1.1    kardel 
    968       1.1    kardel 	if (no_set)
    969       1.1    kardel 	    return;
    970       1.1    kardel 
    971       1.1    kardel 	time_offset.tv_sec  = offset / 1000000;
    972       1.1    kardel 	time_offset.tv_usec = offset % 1000000;
    973       1.1    kardel 
    974       1.1    kardel 	LPRINTF("adj_time: %ld us ", (long int)offset);
    975       1.1    kardel 	if (adjtime(&time_offset, 0L) == -1)
    976       1.1    kardel 	    perror("adjtime()");
    977       1.1    kardel }
    978       1.1    kardel 
    979       1.1    kardel /*-----------------------------------------------------------------------
    980       1.1    kardel  * read in a possibly previously written drift value
    981       1.1    kardel  */
    982       1.1    kardel static void
    983       1.1    kardel read_drift(
    984       1.1    kardel 	   const char *drift_file
    985       1.1    kardel 	   )
    986       1.1    kardel {
    987       1.1    kardel 	FILE *df;
    988       1.1    kardel 
    989       1.1    kardel 	df = fopen(drift_file, "r");
    990       1.1    kardel 	if (df != NULL)
    991       1.1    kardel 	{
    992       1.1    kardel 		int idrift = 0, fdrift = 0;
    993       1.1    kardel 
    994  1.1.1.10  christos 		if (2 != fscanf(df, "%4d.%03d", &idrift, &fdrift))
    995  1.1.1.10  christos 			LPRINTF("read_drift: trouble reading drift file");
    996       1.1    kardel 		fclose(df);
    997       1.1    kardel 		LPRINTF("read_drift: %d.%03d ppm ", idrift, fdrift);
    998       1.1    kardel 
    999       1.1    kardel 		accum_drift = idrift << USECSCALE;
   1000       1.1    kardel 		fdrift     = (fdrift << USECSCALE) / 1000;
   1001       1.1    kardel 		accum_drift += fdrift & (1<<USECSCALE);
   1002       1.1    kardel 		LPRINTF("read_drift: drift_comp %ld ", (long int)accum_drift);
   1003       1.1    kardel 	}
   1004       1.1    kardel }
   1005       1.1    kardel 
   1006       1.1    kardel /*-----------------------------------------------------------------------
   1007       1.1    kardel  * write out the current drift value
   1008       1.1    kardel  */
   1009       1.1    kardel static void
   1010       1.1    kardel update_drift(
   1011       1.1    kardel 	     const char *drift_file,
   1012       1.1    kardel 	     long offset,
   1013       1.1    kardel 	     time_t reftime
   1014       1.1    kardel 	     )
   1015       1.1    kardel {
   1016       1.1    kardel 	FILE *df;
   1017       1.1    kardel 
   1018       1.1    kardel 	df = fopen(drift_file, "w");
   1019       1.1    kardel 	if (df != NULL)
   1020       1.1    kardel 	{
   1021       1.1    kardel 		int idrift = R_SHIFT(accum_drift, USECSCALE);
   1022       1.1    kardel 		int fdrift = accum_drift & ((1<<USECSCALE)-1);
   1023       1.1    kardel 
   1024       1.1    kardel 		LPRINTF("update_drift: drift_comp %ld ", (long int)accum_drift);
   1025       1.1    kardel 		fdrift = (fdrift * 1000) / (1<<USECSCALE);
   1026       1.1    kardel 		fprintf(df, "%4d.%03d %c%ld.%06ld %.24s\n", idrift, fdrift,
   1027       1.1    kardel 			(offset < 0) ? '-' : '+', (long int)(l_abs(offset) / 1000000),
   1028       1.1    kardel 			(long int)(l_abs(offset) % 1000000), asctime(localtime(&reftime)));
   1029       1.1    kardel 		fclose(df);
   1030       1.1    kardel 		LPRINTF("update_drift: %d.%03d ppm ", idrift, fdrift);
   1031       1.1    kardel 	}
   1032       1.1    kardel }
   1033       1.1    kardel 
   1034       1.1    kardel /*-----------------------------------------------------------------------
   1035       1.1    kardel  * process adjustments derived from the DCF77 observation
   1036       1.1    kardel  * (controls clock PLL)
   1037       1.1    kardel  */
   1038       1.1    kardel static void
   1039       1.1    kardel adjust_clock(
   1040       1.1    kardel 	     struct timeval *offset,
   1041       1.1    kardel 	     const char *drift_file,
   1042       1.1    kardel 	     time_t reftime
   1043       1.1    kardel 	     )
   1044       1.1    kardel {
   1045       1.1    kardel 	struct timeval toffset;
   1046       1.1    kardel 	register long usecoffset;
   1047       1.1    kardel 	int tmp;
   1048       1.1    kardel 
   1049       1.1    kardel 	if (no_set)
   1050       1.1    kardel 	    return;
   1051       1.1    kardel 
   1052       1.1    kardel 	if (skip_adjust)
   1053       1.1    kardel 	{
   1054       1.1    kardel 		skip_adjust = 0;
   1055       1.1    kardel 		return;
   1056       1.1    kardel 	}
   1057       1.1    kardel 
   1058       1.1    kardel 	toffset = *offset;
   1059       1.1    kardel 	toffset.tv_sec  = l_abs(toffset.tv_sec);
   1060       1.1    kardel 	toffset.tv_usec = l_abs(toffset.tv_usec);
   1061       1.1    kardel 	if (toffset.tv_sec ||
   1062       1.1    kardel 	    (!toffset.tv_sec && toffset.tv_usec > max_adj_offset_usec))
   1063       1.1    kardel 	{
   1064       1.1    kardel 		/*
   1065       1.1    kardel 		 * hopeless - set the clock - and clear the timing
   1066       1.1    kardel 		 */
   1067       1.1    kardel 		set_time(offset);
   1068       1.1    kardel 		clock_adjust = 0;
   1069       1.1    kardel 		skip_adjust  = 1;
   1070       1.1    kardel 		return;
   1071       1.1    kardel 	}
   1072       1.1    kardel 
   1073       1.1    kardel 	usecoffset   = offset->tv_sec * 1000000 + offset->tv_usec;
   1074       1.1    kardel 
   1075       1.1    kardel 	clock_adjust = R_SHIFT(usecoffset, TIMECONSTANT);	/* adjustment to make for next period */
   1076       1.1    kardel 
   1077       1.1    kardel 	tmp = 0;
   1078       1.1    kardel 	while (adjustments > (1 << tmp))
   1079       1.1    kardel 	    tmp++;
   1080       1.1    kardel 	adjustments = 0;
   1081       1.1    kardel 	if (tmp > FREQ_WEIGHT)
   1082       1.1    kardel 	    tmp = FREQ_WEIGHT;
   1083       1.1    kardel 
   1084       1.1    kardel 	accum_drift  += R_SHIFT(usecoffset << USECSCALE, TIMECONSTANT+TIMECONSTANT+FREQ_WEIGHT-tmp);
   1085       1.1    kardel 
   1086       1.1    kardel 	if (accum_drift > MAX_DRIFT)		/* clamp into interval */
   1087       1.1    kardel 	    accum_drift = MAX_DRIFT;
   1088       1.1    kardel 	else
   1089       1.1    kardel 	    if (accum_drift < -MAX_DRIFT)
   1090       1.1    kardel 		accum_drift = -MAX_DRIFT;
   1091       1.1    kardel 
   1092       1.1    kardel 	update_drift(drift_file, usecoffset, reftime);
   1093       1.1    kardel 	LPRINTF("clock_adjust: %s, clock_adjust %ld, drift_comp %ld(%ld) ",
   1094       1.1    kardel 		pr_timeval(offset),(long int) R_SHIFT(clock_adjust, USECSCALE),
   1095       1.1    kardel 		(long int)R_SHIFT(accum_drift, USECSCALE), (long int)accum_drift);
   1096       1.1    kardel }
   1097       1.1    kardel 
   1098       1.1    kardel /*-----------------------------------------------------------------------
   1099       1.1    kardel  * adjust the clock by a small mount to simulate frequency correction
   1100       1.1    kardel  */
   1101       1.1    kardel static void
   1102       1.1    kardel periodic_adjust(
   1103       1.1    kardel 		void
   1104       1.1    kardel 		)
   1105       1.1    kardel {
   1106       1.1    kardel 	register long adjustment;
   1107       1.1    kardel 
   1108       1.1    kardel 	adjustments++;
   1109       1.1    kardel 
   1110       1.1    kardel 	adjustment = R_SHIFT(clock_adjust, PHASE_WEIGHT);
   1111       1.1    kardel 
   1112       1.1    kardel 	clock_adjust -= adjustment;
   1113       1.1    kardel 
   1114       1.1    kardel 	adjustment += R_SHIFT(accum_drift, USECSCALE+ADJINTERVAL);
   1115       1.1    kardel 
   1116       1.1    kardel 	adj_time(adjustment);
   1117       1.1    kardel }
   1118       1.1    kardel 
   1119       1.1    kardel /*-----------------------------------------------------------------------
   1120       1.1    kardel  * control synchronisation status (warnings) and do periodic adjusts
   1121       1.1    kardel  * (frequency control simulation)
   1122       1.1    kardel  */
   1123       1.1    kardel static void
   1124       1.1    kardel tick(
   1125       1.1    kardel      int signum
   1126       1.1    kardel      )
   1127       1.1    kardel {
   1128       1.1    kardel 	static unsigned long last_notice = 0;
   1129       1.1    kardel 
   1130       1.1    kardel #if !defined(HAVE_SIGACTION) && !defined(HAVE_SIGVEC)
   1131       1.1    kardel 	(void)signal(SIGALRM, tick);
   1132       1.1    kardel #endif
   1133       1.1    kardel 
   1134       1.1    kardel 	periodic_adjust();
   1135       1.1    kardel 
   1136       1.1    kardel 	ticks += 1<<ADJINTERVAL;
   1137       1.1    kardel 
   1138       1.1    kardel 	if ((ticks - last_sync) > MAX_UNSYNC)
   1139       1.1    kardel 	{
   1140       1.1    kardel 		/*
   1141       1.1    kardel 		 * not getting time for a while
   1142       1.1    kardel 		 */
   1143       1.1    kardel 		if (sync_state == SYNC)
   1144       1.1    kardel 		{
   1145       1.1    kardel 			/*
   1146       1.1    kardel 			 * completely lost information
   1147       1.1    kardel 			 */
   1148       1.1    kardel 			sync_state = NO_SYNC;
   1149       1.1    kardel 			syslog(LOG_INFO, "DCF77 reception lost (timeout)");
   1150       1.1    kardel 			last_notice = ticks;
   1151       1.1    kardel 		}
   1152       1.1    kardel 		else
   1153       1.1    kardel 		    /*
   1154       1.1    kardel 		     * in NO_SYNC state - look whether its time to speak up again
   1155       1.1    kardel 		     */
   1156       1.1    kardel 		    if ((ticks - last_notice) > NOTICE_INTERVAL)
   1157       1.1    kardel 		    {
   1158       1.1    kardel 			    syslog(LOG_NOTICE, "still not synchronized to DCF77 - check receiver/signal");
   1159       1.1    kardel 			    last_notice = ticks;
   1160       1.1    kardel 		    }
   1161       1.1    kardel 	}
   1162       1.1    kardel 
   1163       1.1    kardel #ifndef ITIMER_REAL
   1164       1.1    kardel 	(void) alarm(1<<ADJINTERVAL);
   1165       1.1    kardel #endif
   1166       1.1    kardel }
   1167       1.1    kardel 
   1168       1.1    kardel /*-----------------------------------------------------------------------
   1169       1.1    kardel  * break association from terminal to avoid catching terminal
   1170       1.1    kardel  * or process group related signals (-> daemon operation)
   1171       1.1    kardel  */
   1172       1.1    kardel static void
   1173       1.1    kardel detach(
   1174       1.1    kardel        void
   1175       1.1    kardel        )
   1176       1.1    kardel {
   1177       1.1    kardel #   ifdef HAVE_DAEMON
   1178  1.1.1.10  christos 	if (daemon(0, 0)) {
   1179  1.1.1.10  christos 		fprintf(stderr, "'daemon()' fails: %d(%s)\n",
   1180  1.1.1.10  christos 			errno, strerror(errno));
   1181  1.1.1.10  christos 	}
   1182       1.1    kardel #   else /* not HAVE_DAEMON */
   1183       1.1    kardel 	if (fork())
   1184       1.1    kardel 	    exit(0);
   1185       1.1    kardel 
   1186       1.1    kardel 	{
   1187       1.1    kardel 		u_long s;
   1188       1.1    kardel 		int max_fd;
   1189       1.1    kardel 
   1190       1.1    kardel #if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
   1191       1.1    kardel 		max_fd = sysconf(_SC_OPEN_MAX);
   1192       1.1    kardel #else /* HAVE_SYSCONF && _SC_OPEN_MAX */
   1193       1.1    kardel 		max_fd = getdtablesize();
   1194       1.1    kardel #endif /* HAVE_SYSCONF && _SC_OPEN_MAX */
   1195       1.1    kardel 		for (s = 0; s < max_fd; s++)
   1196       1.1    kardel 		    (void) close((int)s);
   1197       1.1    kardel 		(void) open("/", 0);
   1198       1.1    kardel 		(void) dup2(0, 1);
   1199       1.1    kardel 		(void) dup2(0, 2);
   1200       1.1    kardel #ifdef SYS_DOMAINOS
   1201       1.1    kardel 		{
   1202       1.1    kardel 			uid_$t puid;
   1203       1.1    kardel 			status_$t st;
   1204       1.1    kardel 
   1205       1.1    kardel 			proc2_$who_am_i(&puid);
   1206       1.1    kardel 			proc2_$make_server(&puid, &st);
   1207       1.1    kardel 		}
   1208       1.1    kardel #endif /* SYS_DOMAINOS */
   1209       1.1    kardel #if defined(HAVE_SETPGID) || defined(HAVE_SETSID)
   1210       1.1    kardel # ifdef HAVE_SETSID
   1211       1.1    kardel 		if (setsid() == (pid_t)-1)
   1212       1.1    kardel 		    syslog(LOG_ERR, "dcfd: setsid(): %m");
   1213       1.1    kardel # else
   1214       1.1    kardel 		if (setpgid(0, 0) == -1)
   1215       1.1    kardel 		    syslog(LOG_ERR, "dcfd: setpgid(): %m");
   1216       1.1    kardel # endif
   1217       1.1    kardel #else /* HAVE_SETPGID || HAVE_SETSID */
   1218       1.1    kardel 		{
   1219       1.1    kardel 			int fid;
   1220       1.1    kardel 
   1221       1.1    kardel 			fid = open("/dev/tty", 2);
   1222       1.1    kardel 			if (fid >= 0)
   1223       1.1    kardel 			{
   1224       1.1    kardel 				(void) ioctl(fid, (u_long) TIOCNOTTY, (char *) 0);
   1225       1.1    kardel 				(void) close(fid);
   1226       1.1    kardel 			}
   1227       1.1    kardel # ifdef HAVE_SETPGRP_0
   1228       1.1    kardel 			(void) setpgrp();
   1229       1.1    kardel # else /* HAVE_SETPGRP_0 */
   1230       1.1    kardel 			(void) setpgrp(0, getpid());
   1231       1.1    kardel # endif /* HAVE_SETPGRP_0 */
   1232       1.1    kardel 		}
   1233       1.1    kardel #endif /* HAVE_SETPGID || HAVE_SETSID */
   1234       1.1    kardel 	}
   1235       1.1    kardel #endif /* not HAVE_DAEMON */
   1236       1.1    kardel }
   1237       1.1    kardel 
   1238       1.1    kardel /*-----------------------------------------------------------------------
   1239       1.1    kardel  * list possible arguments and options
   1240       1.1    kardel  */
   1241       1.1    kardel static void
   1242       1.1    kardel usage(
   1243       1.1    kardel       char *program
   1244       1.1    kardel       )
   1245       1.1    kardel {
   1246       1.1    kardel   fprintf(stderr, "usage: %s [-n] [-f] [-l] [-t] [-i] [-o] [-d <drift_file>] [-D <input delay>] <device>\n", program);
   1247       1.1    kardel 	fprintf(stderr, "\t-n              do not change time\n");
   1248       1.1    kardel 	fprintf(stderr, "\t-i              interactive\n");
   1249       1.1    kardel 	fprintf(stderr, "\t-t              trace (print all datagrams)\n");
   1250       1.1    kardel 	fprintf(stderr, "\t-f              print all databits (includes PTB private data)\n");
   1251       1.1    kardel 	fprintf(stderr, "\t-l              print loop filter debug information\n");
   1252       1.1    kardel 	fprintf(stderr, "\t-o              print offet average for current minute\n");
   1253       1.1    kardel 	fprintf(stderr, "\t-Y              make internal Y2K checks then exit\n");	/* Y2KFixes */
   1254       1.1    kardel 	fprintf(stderr, "\t-d <drift_file> specify alternate drift file\n");
   1255       1.1    kardel 	fprintf(stderr, "\t-D <input delay>specify delay from input edge to processing in micro seconds\n");
   1256       1.1    kardel }
   1257       1.1    kardel 
   1258       1.1    kardel /*-----------------------------------------------------------------------
   1259       1.1    kardel  * check_y2k() - internal check of Y2K logic
   1260       1.1    kardel  *	(a lot of this logic lifted from ../ntpd/check_y2k.c)
   1261       1.1    kardel  */
   1262       1.1    kardel static int
   1263       1.1    kardel check_y2k( void )
   1264   1.1.1.3  christos {
   1265       1.1    kardel     int  year;			/* current working year */
   1266       1.1    kardel     int  year0 = 1900;		/* sarting year for NTP time */
   1267       1.1    kardel     int  yearend;		/* ending year we test for NTP time.
   1268       1.1    kardel 				    * 32-bit systems: through 2036, the
   1269       1.1    kardel 				      **year in which NTP time overflows.
   1270       1.1    kardel 				    * 64-bit systems: a reasonable upper
   1271       1.1    kardel 				      **limit (well, maybe somewhat beyond
   1272       1.1    kardel 				      **reasonable, but well before the
   1273       1.1    kardel 				      **max time, by which time the earth
   1274       1.1    kardel 				      **will be dead.) */
   1275       1.1    kardel     time_t Time;
   1276       1.1    kardel     struct tm LocalTime;
   1277       1.1    kardel 
   1278       1.1    kardel     int Fatals, Warnings;
   1279       1.1    kardel #define Error(year) if ( (year)>=2036 && LocalTime.tm_year < 110 ) \
   1280       1.1    kardel 	Warnings++; else Fatals++
   1281       1.1    kardel 
   1282       1.1    kardel     Fatals = Warnings = 0;
   1283       1.1    kardel 
   1284       1.1    kardel     Time = time( (time_t *)NULL );
   1285       1.1    kardel     LocalTime = *localtime( &Time );
   1286       1.1    kardel 
   1287       1.1    kardel     year = ( sizeof( u_long ) > 4 ) 	/* save max span using year as temp */
   1288       1.1    kardel 		? ( 400 * 3 ) 		/* three greater gregorian cycles */
   1289       1.1    kardel 		: ((int)(0x7FFFFFFF / 365.242 / 24/60/60)* 2 ); /*32-bit limit*/
   1290       1.1    kardel 			/* NOTE: will automacially expand test years on
   1291       1.1    kardel 			 * 64 bit machines.... this may cause some of the
   1292       1.1    kardel 			 * existing ntp logic to fail for years beyond
   1293       1.1    kardel 			 * 2036 (the current 32-bit limit). If all checks
   1294       1.1    kardel 			 * fail ONLY beyond year 2036 you may ignore such
   1295       1.1    kardel 			 * errors, at least for a decade or so. */
   1296       1.1    kardel     yearend = year0 + year;
   1297       1.1    kardel 
   1298       1.1    kardel     year = 1900+YEAR_PIVOT;
   1299       1.1    kardel     printf( "  starting year %04d\n", (int) year );
   1300       1.1    kardel     printf( "  ending year   %04d\n", (int) yearend );
   1301       1.1    kardel 
   1302       1.1    kardel     for ( ; year < yearend; year++ )
   1303       1.1    kardel     {
   1304       1.1    kardel 	clocktime_t  ct;
   1305       1.1    kardel 	time_t	     Observed;
   1306       1.1    kardel 	time_t	     Expected;
   1307       1.1    kardel 	unsigned     Flag;
   1308       1.1    kardel 	unsigned long t;
   1309       1.1    kardel 
   1310       1.1    kardel 	ct.day = 1;
   1311       1.1    kardel 	ct.month = 1;
   1312       1.1    kardel 	ct.year = year;
   1313       1.1    kardel 	ct.hour = ct.minute = ct.second = ct.usecond = 0;
   1314       1.1    kardel 	ct.utcoffset = 0;
   1315       1.1    kardel 	ct.flags = 0;
   1316       1.1    kardel 
   1317       1.1    kardel 	Flag = 0;
   1318       1.1    kardel  	Observed = dcf_to_unixtime( &ct, &Flag );
   1319       1.1    kardel 		/* seems to be a clone of parse_to_unixtime() with
   1320       1.1    kardel 		 * *a minor difference to arg2 type */
   1321       1.1    kardel 	if ( ct.year != year )
   1322       1.1    kardel 	{
   1323   1.1.1.3  christos 	    fprintf( stdout,
   1324       1.1    kardel 	       "%04d: dcf_to_unixtime(,%d) CORRUPTED ct.year: was %d\n",
   1325       1.1    kardel 	       (int)year, (int)Flag, (int)ct.year );
   1326       1.1    kardel 	    Error(year);
   1327       1.1    kardel 	    break;
   1328       1.1    kardel 	}
   1329       1.1    kardel 	t = julian0(year) - julian0(1970);	/* Julian day from 1970 */
   1330       1.1    kardel 	Expected = t * 24 * 60 * 60;
   1331       1.1    kardel 	if ( Observed != Expected  ||  Flag )
   1332       1.1    kardel 	{   /* time difference */
   1333   1.1.1.3  christos 	    fprintf( stdout,
   1334       1.1    kardel 	       "%04d: dcf_to_unixtime(,%d) FAILURE: was=%lu s/b=%lu  (%ld)\n",
   1335   1.1.1.3  christos 	       year, (int)Flag,
   1336       1.1    kardel 	       (unsigned long)Observed, (unsigned long)Expected,
   1337       1.1    kardel 	       ((long)Observed - (long)Expected) );
   1338       1.1    kardel 	    Error(year);
   1339       1.1    kardel 	    break;
   1340       1.1    kardel 	}
   1341       1.1    kardel 
   1342       1.1    kardel     }
   1343       1.1    kardel 
   1344       1.1    kardel     return ( Fatals );
   1345       1.1    kardel }
   1346       1.1    kardel 
   1347       1.1    kardel /*--------------------------------------------------
   1348       1.1    kardel  * rawdcf_init - set up modem lines for RAWDCF receivers
   1349       1.1    kardel  */
   1350       1.1    kardel #if defined(TIOCMSET) && (defined(TIOCM_DTR) || defined(CIOCM_DTR))
   1351       1.1    kardel static void
   1352       1.1    kardel rawdcf_init(
   1353       1.1    kardel 	int fd
   1354       1.1    kardel 	)
   1355       1.1    kardel {
   1356       1.1    kardel 	/*
   1357       1.1    kardel 	 * You can use the RS232 to supply the power for a DCF77 receiver.
   1358       1.1    kardel 	 * Here a voltage between the DTR and the RTS line is used. Unfortunately
   1359       1.1    kardel 	 * the name has changed from CIOCM_DTR to TIOCM_DTR recently.
   1360       1.1    kardel 	 */
   1361   1.1.1.3  christos 
   1362       1.1    kardel #ifdef TIOCM_DTR
   1363       1.1    kardel 	int sl232 = TIOCM_DTR;	/* turn on DTR for power supply */
   1364       1.1    kardel #else
   1365       1.1    kardel 	int sl232 = CIOCM_DTR;	/* turn on DTR for power supply */
   1366       1.1    kardel #endif
   1367       1.1    kardel 
   1368       1.1    kardel 	if (ioctl(fd, TIOCMSET, (caddr_t)&sl232) == -1)
   1369       1.1    kardel 	{
   1370       1.1    kardel 		syslog(LOG_NOTICE, "rawdcf_init: WARNING: ioctl(fd, TIOCMSET, [C|T]IOCM_DTR): %m");
   1371       1.1    kardel 	}
   1372       1.1    kardel }
   1373       1.1    kardel #else
   1374       1.1    kardel static void
   1375       1.1    kardel rawdcf_init(
   1376       1.1    kardel 	    int fd
   1377       1.1    kardel 	)
   1378       1.1    kardel {
   1379       1.1    kardel 	syslog(LOG_NOTICE, "rawdcf_init: WARNING: OS interface incapable of setting DTR to power DCF modules");
   1380       1.1    kardel }
   1381       1.1    kardel #endif  /* DTR initialisation type */
   1382       1.1    kardel 
   1383       1.1    kardel /*-----------------------------------------------------------------------
   1384       1.1    kardel  * main loop - argument interpreter / setup / main loop
   1385       1.1    kardel  */
   1386       1.1    kardel int
   1387       1.1    kardel main(
   1388       1.1    kardel      int argc,
   1389       1.1    kardel      char **argv
   1390       1.1    kardel      )
   1391       1.1    kardel {
   1392       1.1    kardel 	unsigned char c;
   1393       1.1    kardel 	char **a = argv;
   1394       1.1    kardel 	int  ac = argc;
   1395       1.1    kardel 	char *file = NULL;
   1396       1.1    kardel 	const char *drift_file = "/etc/dcfd.drift";
   1397       1.1    kardel 	int fd;
   1398       1.1    kardel 	int offset = 15;
   1399       1.1    kardel 	int offsets = 0;
   1400       1.1    kardel 	int delay = DEFAULT_DELAY;	/* average delay from input edge to time stamping */
   1401       1.1    kardel 	int trace = 0;
   1402       1.1    kardel 	int errs = 0;
   1403       1.1    kardel 
   1404       1.1    kardel 	/*
   1405       1.1    kardel 	 * process arguments
   1406       1.1    kardel 	 */
   1407       1.1    kardel 	while (--ac)
   1408       1.1    kardel 	{
   1409       1.1    kardel 		char *arg = *++a;
   1410       1.1    kardel 		if (*arg == '-')
   1411       1.1    kardel 		    while ((c = *++arg))
   1412       1.1    kardel 			switch (c)
   1413       1.1    kardel 			{
   1414       1.1    kardel 			    case 't':
   1415       1.1    kardel 				trace = 1;
   1416       1.1    kardel 				interactive = 1;
   1417       1.1    kardel 				break;
   1418       1.1    kardel 
   1419       1.1    kardel 			    case 'f':
   1420       1.1    kardel 				offset = 0;
   1421       1.1    kardel 				interactive = 1;
   1422       1.1    kardel 				break;
   1423       1.1    kardel 
   1424       1.1    kardel 			    case 'l':
   1425       1.1    kardel 				loop_filter_debug = 1;
   1426       1.1    kardel 				offsets = 1;
   1427       1.1    kardel 				interactive = 1;
   1428       1.1    kardel 				break;
   1429       1.1    kardel 
   1430       1.1    kardel 			    case 'n':
   1431       1.1    kardel 				no_set = 1;
   1432       1.1    kardel 				break;
   1433       1.1    kardel 
   1434       1.1    kardel 			    case 'o':
   1435       1.1    kardel 				offsets = 1;
   1436       1.1    kardel 				interactive = 1;
   1437       1.1    kardel 				break;
   1438       1.1    kardel 
   1439       1.1    kardel 			    case 'i':
   1440       1.1    kardel 				interactive = 1;
   1441       1.1    kardel 				break;
   1442       1.1    kardel 
   1443       1.1    kardel 			    case 'D':
   1444       1.1    kardel 				if (ac > 1)
   1445       1.1    kardel 				{
   1446       1.1    kardel 					delay = atoi(*++a);
   1447       1.1    kardel 					ac--;
   1448       1.1    kardel 				}
   1449       1.1    kardel 				else
   1450       1.1    kardel 				{
   1451       1.1    kardel 					fprintf(stderr, "%s: -D requires integer argument\n", argv[0]);
   1452       1.1    kardel 					errs=1;
   1453       1.1    kardel 				}
   1454       1.1    kardel 				break;
   1455   1.1.1.3  christos 
   1456       1.1    kardel 			    case 'd':
   1457       1.1    kardel 				if (ac > 1)
   1458       1.1    kardel 				{
   1459       1.1    kardel 					drift_file = *++a;
   1460       1.1    kardel 					ac--;
   1461       1.1    kardel 				}
   1462       1.1    kardel 				else
   1463       1.1    kardel 				{
   1464       1.1    kardel 					fprintf(stderr, "%s: -d requires file name argument\n", argv[0]);
   1465       1.1    kardel 					errs=1;
   1466       1.1    kardel 				}
   1467       1.1    kardel 				break;
   1468   1.1.1.3  christos 
   1469   1.1.1.3  christos 			    case 'Y':
   1470       1.1    kardel 				errs=check_y2k();
   1471       1.1    kardel 				exit( errs ? 1 : 0 );
   1472       1.1    kardel 
   1473       1.1    kardel 			    default:
   1474       1.1    kardel 				fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
   1475       1.1    kardel 				errs=1;
   1476       1.1    kardel 				break;
   1477       1.1    kardel 			}
   1478       1.1    kardel 		else
   1479       1.1    kardel 		    if (file == NULL)
   1480       1.1    kardel 			file = arg;
   1481       1.1    kardel 		    else
   1482       1.1    kardel 		    {
   1483       1.1    kardel 			    fprintf(stderr, "%s: device specified twice\n", argv[0]);
   1484       1.1    kardel 			    errs=1;
   1485       1.1    kardel 		    }
   1486       1.1    kardel 	}
   1487       1.1    kardel 
   1488       1.1    kardel 	if (errs)
   1489       1.1    kardel 	{
   1490       1.1    kardel 		usage(argv[0]);
   1491       1.1    kardel 		exit(1);
   1492       1.1    kardel 	}
   1493       1.1    kardel 	else
   1494       1.1    kardel 	    if (file == NULL)
   1495       1.1    kardel 	    {
   1496       1.1    kardel 		    fprintf(stderr, "%s: device not specified\n", argv[0]);
   1497       1.1    kardel 		    usage(argv[0]);
   1498       1.1    kardel 		    exit(1);
   1499       1.1    kardel 	    }
   1500       1.1    kardel 
   1501       1.1    kardel 	errs = LINES+1;
   1502       1.1    kardel 
   1503       1.1    kardel 	/*
   1504       1.1    kardel 	 * get access to DCF77 tty port
   1505       1.1    kardel 	 */
   1506       1.1    kardel 	fd = open(file, O_RDONLY);
   1507       1.1    kardel 	if (fd == -1)
   1508       1.1    kardel 	{
   1509       1.1    kardel 		perror(file);
   1510       1.1    kardel 		exit(1);
   1511       1.1    kardel 	}
   1512       1.1    kardel 	else
   1513       1.1    kardel 	{
   1514       1.1    kardel 		int i, rrc;
   1515       1.1    kardel 		struct timeval t, tt, tlast;
   1516       1.1    kardel 		struct timeval timeout;
   1517       1.1    kardel 		struct timeval phase;
   1518       1.1    kardel 		struct timeval time_offset;
   1519       1.1    kardel 		char pbuf[61];		/* printable version */
   1520       1.1    kardel 		char buf[61];		/* raw data */
   1521       1.1    kardel 		clocktime_t clock_time;	/* wall clock time */
   1522       1.1    kardel 		time_t utc_time = 0;
   1523       1.1    kardel 		time_t last_utc_time = 0;
   1524       1.1    kardel 		long usecerror = 0;
   1525       1.1    kardel 		long lasterror = 0;
   1526       1.1    kardel #if defined(HAVE_TERMIOS_H) || defined(STREAM)
   1527       1.1    kardel 		struct termios term;
   1528       1.1    kardel #else  /* not HAVE_TERMIOS_H || STREAM */
   1529       1.1    kardel # if defined(HAVE_TERMIO_H) || defined(HAVE_SYSV_TTYS)
   1530       1.1    kardel 		struct termio term;
   1531       1.1    kardel # endif/* HAVE_TERMIO_H || HAVE_SYSV_TTYS */
   1532       1.1    kardel #endif /* not HAVE_TERMIOS_H || STREAM */
   1533       1.1    kardel 		unsigned int rtc = CVT_NONE;
   1534       1.1    kardel 
   1535       1.1    kardel 		rawdcf_init(fd);
   1536   1.1.1.3  christos 
   1537       1.1    kardel 		timeout.tv_sec  = 1;
   1538       1.1    kardel 		timeout.tv_usec = 500000;
   1539       1.1    kardel 
   1540       1.1    kardel 		phase.tv_sec    = 0;
   1541       1.1    kardel 		phase.tv_usec   = delay;
   1542       1.1    kardel 
   1543       1.1    kardel 		/*
   1544       1.1    kardel 		 * setup TTY (50 Baud, Read, 8Bit, No Hangup, 1 character IO)
   1545       1.1    kardel 		 */
   1546       1.1    kardel 		if (TTY_GETATTR(fd,  &term) == -1)
   1547       1.1    kardel 		{
   1548       1.1    kardel 			perror("tcgetattr");
   1549       1.1    kardel 			exit(1);
   1550       1.1    kardel 		}
   1551       1.1    kardel 
   1552       1.1    kardel 		memset(term.c_cc, 0, sizeof(term.c_cc));
   1553       1.1    kardel 		term.c_cc[VMIN] = 1;
   1554       1.1    kardel #ifdef NO_PARENB_IGNPAR
   1555       1.1    kardel 		term.c_cflag = CS8|CREAD|CLOCAL;
   1556       1.1    kardel #else
   1557       1.1    kardel 		term.c_cflag = CS8|CREAD|CLOCAL|PARENB;
   1558       1.1    kardel #endif
   1559       1.1    kardel 		term.c_iflag = IGNPAR;
   1560       1.1    kardel 		term.c_oflag = 0;
   1561       1.1    kardel 		term.c_lflag = 0;
   1562       1.1    kardel 
   1563       1.1    kardel 		cfsetispeed(&term, B50);
   1564       1.1    kardel 		cfsetospeed(&term, B50);
   1565       1.1    kardel 
   1566       1.1    kardel 		if (TTY_SETATTR(fd, &term) == -1)
   1567       1.1    kardel 		{
   1568       1.1    kardel 			perror("tcsetattr");
   1569       1.1    kardel 			exit(1);
   1570       1.1    kardel 		}
   1571       1.1    kardel 
   1572       1.1    kardel 		/*
   1573       1.1    kardel 		 * lose terminal if in daemon operation
   1574       1.1    kardel 		 */
   1575       1.1    kardel 		if (!interactive)
   1576       1.1    kardel 		    detach();
   1577   1.1.1.3  christos 
   1578       1.1    kardel 		/*
   1579       1.1    kardel 		 * get syslog() initialized
   1580       1.1    kardel 		 */
   1581       1.1    kardel #ifdef LOG_DAEMON
   1582       1.1    kardel 		openlog("dcfd", LOG_PID, LOG_DAEMON);
   1583       1.1    kardel #else
   1584       1.1    kardel 		openlog("dcfd", LOG_PID);
   1585       1.1    kardel #endif
   1586       1.1    kardel 
   1587       1.1    kardel 		/*
   1588       1.1    kardel 		 * setup periodic operations (state control / frequency control)
   1589       1.1    kardel 		 */
   1590       1.1    kardel #ifdef HAVE_SIGACTION
   1591       1.1    kardel 		{
   1592       1.1    kardel 			struct sigaction act;
   1593       1.1    kardel 
   1594       1.1    kardel # ifdef HAVE_SA_SIGACTION_IN_STRUCT_SIGACTION
   1595       1.1    kardel 			act.sa_sigaction = (void (*) (int, siginfo_t *, void *))0;
   1596       1.1    kardel # endif /* HAVE_SA_SIGACTION_IN_STRUCT_SIGACTION */
   1597       1.1    kardel 			act.sa_handler   = tick;
   1598       1.1    kardel 			sigemptyset(&act.sa_mask);
   1599       1.1    kardel 			act.sa_flags     = 0;
   1600       1.1    kardel 
   1601       1.1    kardel 			if (sigaction(SIGALRM, &act, (struct sigaction *)0) == -1)
   1602       1.1    kardel 			{
   1603       1.1    kardel 				syslog(LOG_ERR, "sigaction(SIGALRM): %m");
   1604       1.1    kardel 				exit(1);
   1605       1.1    kardel 			}
   1606       1.1    kardel 		}
   1607       1.1    kardel #else
   1608       1.1    kardel #ifdef HAVE_SIGVEC
   1609       1.1    kardel 		{
   1610       1.1    kardel 			struct sigvec vec;
   1611       1.1    kardel 
   1612       1.1    kardel 			vec.sv_handler   = tick;
   1613       1.1    kardel 			vec.sv_mask      = 0;
   1614       1.1    kardel 			vec.sv_flags     = 0;
   1615       1.1    kardel 
   1616       1.1    kardel 			if (sigvec(SIGALRM, &vec, (struct sigvec *)0) == -1)
   1617       1.1    kardel 			{
   1618       1.1    kardel 				syslog(LOG_ERR, "sigvec(SIGALRM): %m");
   1619       1.1    kardel 				exit(1);
   1620       1.1    kardel 			}
   1621       1.1    kardel 		}
   1622       1.1    kardel #else
   1623       1.1    kardel 		(void) signal(SIGALRM, tick);
   1624       1.1    kardel #endif
   1625       1.1    kardel #endif
   1626       1.1    kardel 
   1627       1.1    kardel #ifdef ITIMER_REAL
   1628       1.1    kardel 		{
   1629       1.1    kardel 			struct itimerval it;
   1630       1.1    kardel 
   1631       1.1    kardel 			it.it_interval.tv_sec  = 1<<ADJINTERVAL;
   1632       1.1    kardel 			it.it_interval.tv_usec = 0;
   1633       1.1    kardel 			it.it_value.tv_sec     = 1<<ADJINTERVAL;
   1634       1.1    kardel 			it.it_value.tv_usec    = 0;
   1635   1.1.1.3  christos 
   1636       1.1    kardel 			if (setitimer(ITIMER_REAL, &it, (struct itimerval *)0) == -1)
   1637       1.1    kardel 			{
   1638       1.1    kardel 				syslog(LOG_ERR, "setitimer: %m");
   1639       1.1    kardel 				exit(1);
   1640       1.1    kardel 			}
   1641       1.1    kardel 		}
   1642       1.1    kardel #else
   1643       1.1    kardel 		(void) alarm(1<<ADJINTERVAL);
   1644       1.1    kardel #endif
   1645       1.1    kardel 
   1646       1.1    kardel 		PRINTF("  DCF77 monitor %s - Copyright (C) 1993-2005 by Frank Kardel\n\n", revision);
   1647       1.1    kardel 
   1648       1.1    kardel 		pbuf[60] = '\0';
   1649       1.1    kardel 		for ( i = 0; i < 60; i++)
   1650       1.1    kardel 		    pbuf[i] = '.';
   1651       1.1    kardel 
   1652       1.1    kardel 		read_drift(drift_file);
   1653       1.1    kardel 
   1654       1.1    kardel 		/*
   1655       1.1    kardel 		 * what time is it now (for interval measurement)
   1656       1.1    kardel 		 */
   1657       1.1    kardel 		gettimeofday(&tlast, 0L);
   1658       1.1    kardel 		i = 0;
   1659       1.1    kardel 		/*
   1660       1.1    kardel 		 * loop until input trouble ...
   1661       1.1    kardel 		 */
   1662       1.1    kardel 		do
   1663       1.1    kardel 		{
   1664       1.1    kardel 			/*
   1665       1.1    kardel 			 * get an impulse
   1666       1.1    kardel 			 */
   1667       1.1    kardel 			while ((rrc = read(fd, &c, 1)) == 1)
   1668       1.1    kardel 			{
   1669       1.1    kardel 				gettimeofday(&t, 0L);
   1670       1.1    kardel 				tt = t;
   1671       1.1    kardel 				timersub(&t, &tlast);
   1672       1.1    kardel 
   1673       1.1    kardel 				if (errs > LINES)
   1674       1.1    kardel 				{
   1675       1.1    kardel 					PRINTF("  %s", &"PTB private....RADMLSMin....PHour..PMDay..DayMonthYear....P\n"[offset]);
   1676       1.1    kardel 					PRINTF("  %s", &"---------------RADMLS1248124P124812P1248121241248112481248P\n"[offset]);
   1677       1.1    kardel 					errs = 0;
   1678       1.1    kardel 				}
   1679       1.1    kardel 
   1680       1.1    kardel 				/*
   1681       1.1    kardel 				 * timeout -> possible minute mark -> interpretation
   1682       1.1    kardel 				 */
   1683       1.1    kardel 				if (timercmp(&t, &timeout, >))
   1684       1.1    kardel 				{
   1685       1.1    kardel 					PRINTF("%c %.*s ", pat[i % (sizeof(pat)-1)], 59 - offset, &pbuf[offset]);
   1686       1.1    kardel 
   1687       1.1    kardel 					if ((rtc = cvt_rawdcf((unsigned char *)buf, i, &clock_time)) != CVT_OK)
   1688       1.1    kardel 					{
   1689       1.1    kardel 						/*
   1690       1.1    kardel 						 * this data was bad - well - forget synchronisation for now
   1691       1.1    kardel 						 */
   1692       1.1    kardel 						PRINTF("\n");
   1693       1.1    kardel 						if (sync_state == SYNC)
   1694       1.1    kardel 						{
   1695       1.1    kardel 							sync_state = NO_SYNC;
   1696       1.1    kardel 							syslog(LOG_INFO, "DCF77 reception lost (bad data)");
   1697       1.1    kardel 						}
   1698       1.1    kardel 						errs++;
   1699       1.1    kardel 					}
   1700       1.1    kardel 					else
   1701       1.1    kardel 					    if (trace)
   1702       1.1    kardel 					    {
   1703       1.1    kardel 						    PRINTF("\r  %.*s ", 59 - offset, &buf[offset]);
   1704       1.1    kardel 					    }
   1705       1.1    kardel 
   1706       1.1    kardel 
   1707       1.1    kardel 					buf[0] = c;
   1708       1.1    kardel 
   1709       1.1    kardel 					/*
   1710       1.1    kardel 					 * collect first character
   1711       1.1    kardel 					 */
   1712       1.1    kardel 					if (((c^0xFF)+1) & (c^0xFF))
   1713       1.1    kardel 					    pbuf[0] = '?';
   1714       1.1    kardel 					else
   1715       1.1    kardel 					    pbuf[0] = type(c) ? '#' : '-';
   1716       1.1    kardel 
   1717       1.1    kardel 					for ( i = 1; i < 60; i++)
   1718       1.1    kardel 					    pbuf[i] = '.';
   1719       1.1    kardel 
   1720       1.1    kardel 					i = 0;
   1721       1.1    kardel 				}
   1722       1.1    kardel 				else
   1723       1.1    kardel 				{
   1724       1.1    kardel 					/*
   1725       1.1    kardel 					 * collect character
   1726       1.1    kardel 					 */
   1727       1.1    kardel 					buf[i] = c;
   1728       1.1    kardel 
   1729       1.1    kardel 					/*
   1730       1.1    kardel 					 * initial guess (usually correct)
   1731       1.1    kardel 					 */
   1732       1.1    kardel 					if (((c^0xFF)+1) & (c^0xFF))
   1733       1.1    kardel 					    pbuf[i] = '?';
   1734       1.1    kardel 					else
   1735       1.1    kardel 					    pbuf[i] = type(c) ? '#' : '-';
   1736       1.1    kardel 
   1737       1.1    kardel 					PRINTF("%c %.*s ", pat[i % (sizeof(pat)-1)], 59 - offset, &pbuf[offset]);
   1738       1.1    kardel 				}
   1739       1.1    kardel 
   1740       1.1    kardel 				if (i == 0 && rtc == CVT_OK)
   1741       1.1    kardel 				{
   1742       1.1    kardel 					/*
   1743       1.1    kardel 					 * we got a good time code here - try to convert it to
   1744       1.1    kardel 					 * UTC
   1745       1.1    kardel 					 */
   1746       1.1    kardel 					if ((utc_time = dcf_to_unixtime(&clock_time, &rtc)) == -1)
   1747       1.1    kardel 					{
   1748       1.1    kardel 						PRINTF("*** BAD CONVERSION\n");
   1749       1.1    kardel 					}
   1750       1.1    kardel 
   1751       1.1    kardel 					if (utc_time != (last_utc_time + 60))
   1752       1.1    kardel 					{
   1753       1.1    kardel 						/*
   1754       1.1    kardel 						 * well, two successive sucessful telegrams are not 60 seconds
   1755       1.1    kardel 						 * apart
   1756       1.1    kardel 						 */
   1757       1.1    kardel 						PRINTF("*** NO MINUTE INC\n");
   1758       1.1    kardel 						if (sync_state == SYNC)
   1759       1.1    kardel 						{
   1760       1.1    kardel 							sync_state = NO_SYNC;
   1761       1.1    kardel 							syslog(LOG_INFO, "DCF77 reception lost (data mismatch)");
   1762       1.1    kardel 						}
   1763       1.1    kardel 						errs++;
   1764       1.1    kardel 						rtc = CVT_FAIL|CVT_BADTIME|CVT_BADDATE;
   1765       1.1    kardel 					}
   1766       1.1    kardel 					else
   1767       1.1    kardel 					    usecerror = 0;
   1768       1.1    kardel 
   1769       1.1    kardel 					last_utc_time = utc_time;
   1770       1.1    kardel 				}
   1771       1.1    kardel 
   1772       1.1    kardel 				if (rtc == CVT_OK)
   1773       1.1    kardel 				{
   1774       1.1    kardel 					if (i == 0)
   1775       1.1    kardel 					{
   1776       1.1    kardel 						/*
   1777       1.1    kardel 						 * valid time code - determine offset and
   1778       1.1    kardel 						 * note regained reception
   1779       1.1    kardel 						 */
   1780       1.1    kardel 						last_sync = ticks;
   1781       1.1    kardel 						if (sync_state == NO_SYNC)
   1782       1.1    kardel 						{
   1783       1.1    kardel 							syslog(LOG_INFO, "receiving DCF77");
   1784       1.1    kardel 						}
   1785       1.1    kardel 						else
   1786       1.1    kardel 						{
   1787       1.1    kardel 							/*
   1788       1.1    kardel 							 * we had at least one minute SYNC - thus
   1789       1.1    kardel 							 * last error is valid
   1790       1.1    kardel 							 */
   1791       1.1    kardel 							time_offset.tv_sec  = lasterror / 1000000;
   1792       1.1    kardel 							time_offset.tv_usec = lasterror % 1000000;
   1793       1.1    kardel 							adjust_clock(&time_offset, drift_file, utc_time);
   1794       1.1    kardel 						}
   1795       1.1    kardel 						sync_state = SYNC;
   1796       1.1    kardel 					}
   1797       1.1    kardel 
   1798       1.1    kardel 					time_offset.tv_sec  = utc_time + i;
   1799       1.1    kardel 					time_offset.tv_usec = 0;
   1800       1.1    kardel 
   1801       1.1    kardel 					timeradd(&time_offset, &phase);
   1802       1.1    kardel 
   1803       1.1    kardel 					usecerror += (time_offset.tv_sec - tt.tv_sec) * 1000000 + time_offset.tv_usec
   1804       1.1    kardel 						-tt.tv_usec;
   1805       1.1    kardel 
   1806       1.1    kardel 					/*
   1807       1.1    kardel 					 * output interpreted DCF77 data
   1808       1.1    kardel 					 */
   1809       1.1    kardel 					PRINTF(offsets ? "%s, %2ld:%02ld:%02d, %ld.%02ld.%02ld, <%s%s%s%s> (%c%ld.%06lds)" :
   1810       1.1    kardel 					       "%s, %2ld:%02ld:%02d, %ld.%02ld.%02ld, <%s%s%s%s>",
   1811       1.1    kardel 					       wday[clock_time.wday],
   1812       1.1    kardel 					       clock_time.hour, clock_time.minute, i, clock_time.day, clock_time.month,
   1813       1.1    kardel 					       clock_time.year,
   1814   1.1.1.3  christos 					       (clock_time.flags & DCFB_CALLBIT) ? "R" : "_",
   1815       1.1    kardel 					       (clock_time.flags & DCFB_ANNOUNCE) ? "A" : "_",
   1816       1.1    kardel 					       (clock_time.flags & DCFB_DST) ? "D" : "_",
   1817       1.1    kardel 					       (clock_time.flags & DCFB_LEAP) ? "L" : "_",
   1818       1.1    kardel 					       (lasterror < 0) ? '-' : '+', l_abs(lasterror) / 1000000, l_abs(lasterror) % 1000000
   1819       1.1    kardel 					       );
   1820       1.1    kardel 
   1821       1.1    kardel 					if (trace && (i == 0))
   1822       1.1    kardel 					{
   1823       1.1    kardel 						PRINTF("\n");
   1824       1.1    kardel 						errs++;
   1825       1.1    kardel 					}
   1826       1.1    kardel 					lasterror = usecerror / (i+1);
   1827       1.1    kardel 				}
   1828       1.1    kardel 				else
   1829       1.1    kardel 				{
   1830       1.1    kardel 					lasterror = 0; /* we cannot calculate phase errors on bad reception */
   1831       1.1    kardel 				}
   1832       1.1    kardel 
   1833       1.1    kardel 				PRINTF("\r");
   1834       1.1    kardel 
   1835       1.1    kardel 				if (i < 60)
   1836       1.1    kardel 				{
   1837       1.1    kardel 					i++;
   1838       1.1    kardel 				}
   1839       1.1    kardel 
   1840       1.1    kardel 				tlast = tt;
   1841       1.1    kardel 
   1842       1.1    kardel 				if (interactive)
   1843       1.1    kardel 				    fflush(stdout);
   1844       1.1    kardel 			}
   1845       1.1    kardel 		} while ((rrc == -1) && (errno == EINTR));
   1846   1.1.1.3  christos 
   1847       1.1    kardel 		/*
   1848       1.1    kardel 		 * lost IO - sorry guys
   1849       1.1    kardel 		 */
   1850       1.1    kardel 		syslog(LOG_ERR, "TERMINATING - cannot read from device %s (%m)", file);
   1851       1.1    kardel 
   1852       1.1    kardel 		(void)close(fd);
   1853       1.1    kardel 	}
   1854       1.1    kardel 
   1855       1.1    kardel 	closelog();
   1856   1.1.1.3  christos 
   1857       1.1    kardel 	return 0;
   1858       1.1    kardel }
   1859       1.1    kardel 
   1860       1.1    kardel /*
   1861       1.1    kardel  * History:
   1862       1.1    kardel  *
   1863       1.1    kardel  * dcfd.c,v
   1864       1.1    kardel  * Revision 4.18  2005/10/07 22:08:18  kardel
   1865       1.1    kardel  * make dcfd.c compile on NetBSD 3.99.9 again (configure/sigvec compatibility fix)
   1866       1.1    kardel  *
   1867       1.1    kardel  * Revision 4.17.2.1  2005/10/03 19:15:16  kardel
   1868       1.1    kardel  * work around configure not detecting a missing sigvec compatibility
   1869       1.1    kardel  * interface on NetBSD 3.99.9 and above
   1870       1.1    kardel  *
   1871       1.1    kardel  * Revision 4.17  2005/08/10 10:09:44  kardel
   1872       1.1    kardel  * output revision information
   1873       1.1    kardel  *
   1874       1.1    kardel  * Revision 4.16  2005/08/10 06:33:25  kardel
   1875       1.1    kardel  * cleanup warnings
   1876       1.1    kardel  *
   1877       1.1    kardel  * Revision 4.15  2005/08/10 06:28:45  kardel
   1878       1.1    kardel  * fix setting of baud rate
   1879       1.1    kardel  *
   1880       1.1    kardel  * Revision 4.14  2005/04/16 17:32:10  kardel
   1881       1.1    kardel  * update copyright
   1882       1.1    kardel  *
   1883       1.1    kardel  * Revision 4.13  2004/11/14 15:29:41  kardel
   1884       1.1    kardel  * support PPSAPI, upgrade Copyright to Berkeley style
   1885       1.1    kardel  *
   1886       1.1    kardel  */
   1887