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