Annotation of embedaddon/ntp/parseutil/dcfd.c, revision 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>