Annotation of embedaddon/ntp/parseutil/dcfd.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>