Annotation of embedaddon/ntp/util/ntptime.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * NTP test program
        !             3:  *
        !             4:  * This program tests to see if the NTP user interface routines
        !             5:  * ntp_gettime() and ntp_adjtime() have been implemented in the kernel.
        !             6:  * If so, each of these routines is called to display current timekeeping
        !             7:  * data.
        !             8:  *
        !             9:  * For more information, see the README.kern file in the doc directory
        !            10:  * of the xntp3 distribution.
        !            11:  */
        !            12: 
        !            13: #ifdef HAVE_CONFIG_H
        !            14: # include <config.h>
        !            15: #endif /* HAVE_CONFIG_H */
        !            16: 
        !            17: #include "ntp_fp.h"
        !            18: #include "ntp_unixtime.h"
        !            19: #include "ntp_syscall.h"
        !            20: #include "ntp_stdlib.h"
        !            21: 
        !            22: #include <stdio.h>
        !            23: #include <ctype.h>
        !            24: #include <signal.h>
        !            25: #include <setjmp.h>
        !            26: 
        !            27: #ifdef NTP_SYSCALLS_STD
        !            28: # ifndef SYS_DECOSF1
        !            29: #  define BADCALL -1           /* this is supposed to be a bad syscall */
        !            30: # endif /* SYS_DECOSF1 */
        !            31: #endif
        !            32: 
        !            33: #ifdef HAVE_STRUCT_NTPTIMEVAL_TIME_TV_NSEC
        !            34: #define tv_frac_sec tv_nsec
        !            35: #else
        !            36: #define tv_frac_sec tv_usec
        !            37: #endif
        !            38: 
        !            39: 
        !            40: #define TIMEX_MOD_BITS \
        !            41: "\20\1OFFSET\2FREQUENCY\3MAXERROR\4ESTERROR\5STATUS\6TIMECONST\
        !            42: \13PLL\14FLL\15MICRO\16NANO\17CLKB\20CLKA"
        !            43:  
        !            44: #define TIMEX_STA_BITS \
        !            45: "\20\1PLL\2PPSFREQ\3PPSTIME\4FLL\5INS\6DEL\7UNSYNC\10FREQHOLD\
        !            46: \11PPSSIGNAL\12PPSJITTER\13PPSWANDER\14PPSERROR\15CLOCKERR\
        !            47: \16NANO\17MODE\20CLK"
        !            48: 
        !            49: #define SCALE_FREQ 65536               /* frequency scale */
        !            50: 
        !            51: 
        !            52: /*
        !            53:  * Function prototypes
        !            54:  */
        !            55: char *sprintb          (u_int, const char *);
        !            56: const char *timex_state        (int);
        !            57: 
        !            58: #ifdef SIGSYS
        !            59: void pll_trap          (int);
        !            60: 
        !            61: static struct sigaction newsigsys;     /* new sigaction status */
        !            62: static struct sigaction sigsys;                /* current sigaction status */
        !            63: static sigjmp_buf env;         /* environment var. for pll_trap() */
        !            64: #endif
        !            65: 
        !            66: static volatile int pll_control; /* (0) daemon, (1) kernel loop */
        !            67: static volatile int status;    /* most recent status bits */
        !            68: static volatile int flash;     /* most recent ntp_adjtime() bits */
        !            69: char* progname;
        !            70: volatile int debug;            /* for libntp */
        !            71: static char optargs[] = "MNT:cde:f:hm:o:rs:t:";
        !            72: 
        !            73: int
        !            74: main(
        !            75:        int argc,
        !            76:        char *argv[]
        !            77:        )
        !            78: {
        !            79:        extern int ntp_optind;
        !            80:        extern char *ntp_optarg;
        !            81: #ifdef SUBST_ADJTIMEX
        !            82:       struct timex ntv;
        !            83: #else
        !            84:        struct ntptimeval ntv;
        !            85: #endif
        !            86:        struct timeval tv;
        !            87:        struct timex ntx, _ntx;
        !            88:        int     times[20];
        !            89:        double ftemp, gtemp, htemp;
        !            90:        long time_frac;                         /* ntv.time.tv_frac_sec (us/ns) */
        !            91:        l_fp ts;
        !            92:        volatile unsigned ts_mask = TS_MASK;            /* defaults to 20 bits (us) */
        !            93:        volatile unsigned ts_roundbit = TS_ROUNDBIT;    /* defaults to 20 bits (us) */
        !            94:        volatile int fdigits = 6;                       /* fractional digits for us */
        !            95:        int c;
        !            96:        int errflg      = 0;
        !            97:        int cost        = 0;
        !            98:        volatile int rawtime    = 0;
        !            99: 
        !           100:        memset((char *)&ntx, 0, sizeof(ntx));
        !           101:        progname = argv[0];
        !           102:        while ((c = ntp_getopt(argc, argv, optargs)) != EOF) switch (c) {
        !           103: #ifdef MOD_MICRO
        !           104:            case 'M':
        !           105:                ntx.modes |= MOD_MICRO;
        !           106:                break;
        !           107: #endif
        !           108: #ifdef MOD_NANO
        !           109:            case 'N':
        !           110:                ntx.modes |= MOD_NANO;
        !           111:                break;
        !           112: #endif
        !           113: #ifdef NTP_API
        !           114: # if NTP_API > 3
        !           115:            case 'T':
        !           116:                ntx.modes = MOD_TAI;
        !           117:                ntx.constant = atoi(ntp_optarg);
        !           118:                break;
        !           119: # endif
        !           120: #endif
        !           121:            case 'c':
        !           122:                cost++;
        !           123:                break;
        !           124:            case 'e':
        !           125:                ntx.modes |= MOD_ESTERROR;
        !           126:                ntx.esterror = atoi(ntp_optarg);
        !           127:                break;
        !           128:            case 'f':
        !           129:                ntx.modes |= MOD_FREQUENCY;
        !           130:                ntx.freq = (long)(atof(ntp_optarg) * SCALE_FREQ);
        !           131:                break;
        !           132:            case 'm':
        !           133:                ntx.modes |= MOD_MAXERROR;
        !           134:                ntx.maxerror = atoi(ntp_optarg);
        !           135:                break;
        !           136:            case 'o':
        !           137:                ntx.modes |= MOD_OFFSET;
        !           138:                ntx.offset = atoi(ntp_optarg);
        !           139:                break;
        !           140:            case 'r':
        !           141:                rawtime++;
        !           142:                break;
        !           143:            case 's':
        !           144:                ntx.modes |= MOD_STATUS;
        !           145:                ntx.status = atoi(ntp_optarg);
        !           146:                if (ntx.status < 0 || ntx.status >= 0x100) errflg++;
        !           147:                break;
        !           148:            case 't':
        !           149:                ntx.modes |= MOD_TIMECONST;
        !           150:                ntx.constant = atoi(ntp_optarg);
        !           151:                break;
        !           152:            default:
        !           153:                errflg++;
        !           154:        }
        !           155:        if (errflg || (ntp_optind != argc)) {
        !           156:                (void) fprintf(stderr,
        !           157:                               "usage: %s [-%s]\n\n\
        !           158: %s%s%s\
        !           159: -c             display the time taken to call ntp_gettime (us)\n\
        !           160: -e esterror    estimate of the error (us)\n\
        !           161: -f frequency   Frequency error (-500 .. 500) (ppm)\n\
        !           162: -h             display this help info\n\
        !           163: -m maxerror    max possible error (us)\n\
        !           164: -o offset      current offset (ms)\n\
        !           165: -r             print the unix and NTP time raw\n\
        !           166: -s status      Set the status bits\n\
        !           167: -t timeconstant        log2 of PLL time constant (0 .. %d)\n",
        !           168:                               progname, optargs,
        !           169: #ifdef MOD_MICRO
        !           170: "-M            switch to microsecond mode\n",
        !           171: #else
        !           172: "",
        !           173: #endif
        !           174: #ifdef MOD_NANO
        !           175: "-N            switch to nanosecond mode\n",
        !           176: #else
        !           177: "",
        !           178: #endif
        !           179: #ifdef NTP_API
        !           180: # if NTP_API > 3
        !           181: "-T tai_offset set TAI offset\n",
        !           182: # else
        !           183: "",
        !           184: # endif
        !           185: #else
        !           186: "",
        !           187: #endif
        !           188:                               MAXTC);
        !           189:                exit(2);
        !           190:        }
        !           191: 
        !           192: #ifdef SIGSYS
        !           193:        /*
        !           194:         * Test to make sure the sigaction() works in case of invalid
        !           195:         * syscall codes.
        !           196:         */
        !           197:        newsigsys.sa_handler = pll_trap;
        !           198:        newsigsys.sa_flags = 0;
        !           199:        if (sigaction(SIGSYS, &newsigsys, &sigsys)) {
        !           200:                perror("sigaction() fails to save SIGSYS trap");
        !           201:                exit(1);
        !           202:        }
        !           203: #endif /* SIGSYS */
        !           204: 
        !           205: #ifdef BADCALL
        !           206:        /*
        !           207:         * Make sure the trapcatcher works.
        !           208:         */
        !           209:        pll_control = 1;
        !           210: #ifdef SIGSYS
        !           211:        if (sigsetjmp(env, 1) == 0)
        !           212:        {
        !           213: #endif
        !           214:                status = syscall(BADCALL, &ntv); /* dummy parameter */
        !           215:                if ((status < 0) && (errno == ENOSYS))
        !           216:                        --pll_control;
        !           217: #ifdef SIGSYS
        !           218:        }
        !           219: #endif
        !           220:        if (pll_control)
        !           221:            printf("sigaction() failed to catch an invalid syscall\n");
        !           222: #endif /* BADCALL */
        !           223: 
        !           224:        if (cost) {
        !           225: #ifdef SIGSYS
        !           226:                if (sigsetjmp(env, 1) == 0) {
        !           227: #endif
        !           228:                        for (c = 0; c < sizeof times / sizeof times[0]; c++) {
        !           229:                                status = ntp_gettime(&ntv);
        !           230:                                if ((status < 0) && (errno == ENOSYS))
        !           231:                                        --pll_control;
        !           232:                                if (pll_control < 0)
        !           233:                                        break;
        !           234:                                times[c] = ntv.time.tv_frac_sec;
        !           235:                        }
        !           236: #ifdef SIGSYS
        !           237:                }
        !           238: #endif
        !           239:                if (pll_control >= 0) {
        !           240:                        printf("[ us %06d:", times[0]);
        !           241:                        for (c = 1; c < sizeof times / sizeof times[0]; c++)
        !           242:                            printf(" %d", times[c] - times[c - 1]);
        !           243:                        printf(" ]\n");
        !           244:                }
        !           245:        }
        !           246: #ifdef SIGSYS
        !           247:        if (sigsetjmp(env, 1) == 0) {
        !           248: #endif
        !           249:                status = ntp_gettime(&ntv);
        !           250:                if ((status < 0) && (errno == ENOSYS))
        !           251:                        --pll_control;
        !           252: #ifdef SIGSYS
        !           253:        }
        !           254: #endif
        !           255:        _ntx.modes = 0;                         /* Ensure nothing is set */
        !           256: #ifdef SIGSYS
        !           257:        if (sigsetjmp(env, 1) == 0) {
        !           258: #endif
        !           259:                status = ntp_adjtime(&_ntx);
        !           260:                if ((status < 0) && (errno == ENOSYS))
        !           261:                        --pll_control;
        !           262:                flash = _ntx.status;
        !           263: #ifdef SIGSYS
        !           264:        }
        !           265: #endif
        !           266:        if (pll_control < 0) {
        !           267:                printf("NTP user interface routines are not configured in this kernel.\n");
        !           268:                goto lexit;
        !           269:        }
        !           270: 
        !           271:        /*
        !           272:         * Fetch timekeeping data and display.
        !           273:         */
        !           274:        status = ntp_gettime(&ntv);
        !           275:        if (status < 0)
        !           276:                perror("ntp_gettime() call fails");
        !           277:        else {
        !           278:                printf("ntp_gettime() returns code %d (%s)\n",
        !           279:                    status, timex_state(status));
        !           280:                time_frac = ntv.time.tv_frac_sec;
        !           281: #ifdef STA_NANO
        !           282:                if (flash & STA_NANO) {
        !           283:                        ntv.time.tv_frac_sec /= 1000;
        !           284:                        ts_mask = 0xfffffffc;   /* 1/2^30 */
        !           285:                        ts_roundbit = 0x00000002;
        !           286:                        fdigits = 9;
        !           287:                }
        !           288: #endif
        !           289:                tv.tv_sec = ntv.time.tv_sec;
        !           290:                tv.tv_usec = ntv.time.tv_frac_sec;
        !           291:                TVTOTS(&tv, &ts);
        !           292:                ts.l_ui += JAN_1970;
        !           293:                ts.l_uf += ts_roundbit;
        !           294:                ts.l_uf &= ts_mask;
        !           295:                printf("  time %s, (.%0*d),\n",
        !           296:                       prettydate(&ts), fdigits, (int) time_frac);
        !           297:                printf("  maximum error %lu us, estimated error %lu us",
        !           298:                       (u_long)ntv.maxerror, (u_long)ntv.esterror);
        !           299:                if (rawtime)
        !           300:                    printf("  ntptime=%x.%x unixtime=%x.%0*d %s",
        !           301:                    (unsigned int) ts.l_ui, (unsigned int) ts.l_uf,
        !           302:                    (int) ntv.time.tv_sec, fdigits, (int) time_frac,
        !           303:                    ctime((const time_t *) &ntv.time.tv_sec));
        !           304: #if NTP_API > 3
        !           305:                printf(", TAI offset %ld\n", (long)ntv.tai);
        !           306: #else
        !           307:                printf("\n");
        !           308: #endif /* NTP_API */
        !           309:        }
        !           310:        status = ntp_adjtime(&ntx);
        !           311:        if (status < 0)
        !           312:                perror((errno == EPERM) ? 
        !           313:                   "Must be root to set kernel values\nntp_adjtime() call fails" :
        !           314:                   "ntp_adjtime() call fails");
        !           315:        else {
        !           316:                flash = ntx.status;
        !           317:                printf("ntp_adjtime() returns code %d (%s)\n",
        !           318:                     status, timex_state(status));
        !           319:                printf("  modes %s,\n", sprintb(ntx.modes, TIMEX_MOD_BITS));
        !           320:                ftemp = (double)ntx.offset;
        !           321: #ifdef STA_NANO
        !           322:                if (flash & STA_NANO)
        !           323:                        ftemp /= 1000.0;
        !           324: #endif
        !           325:                printf("  offset %.3f", ftemp);
        !           326:                ftemp = (double)ntx.freq / SCALE_FREQ;
        !           327:                printf(" us, frequency %.3f ppm, interval %d s,\n",
        !           328:                     ftemp, 1 << ntx.shift);
        !           329:                printf("  maximum error %lu us, estimated error %lu us,\n",
        !           330:                     (u_long)ntx.maxerror, (u_long)ntx.esterror);
        !           331:                printf("  status %s,\n", sprintb((u_int)ntx.status, TIMEX_STA_BITS));
        !           332:                ftemp = (double)ntx.tolerance / SCALE_FREQ;
        !           333:                gtemp = (double)ntx.precision;
        !           334: #ifdef STA_NANO
        !           335:                if (flash & STA_NANO)
        !           336:                        gtemp /= 1000.0;
        !           337: #endif
        !           338:                printf(
        !           339:                    "  time constant %lu, precision %.3f us, tolerance %.0f ppm,\n",
        !           340:                    (u_long)ntx.constant, gtemp, ftemp);
        !           341:                if (ntx.shift == 0)
        !           342:                        exit (0);
        !           343:                ftemp = (double)ntx.ppsfreq / SCALE_FREQ;
        !           344:                gtemp = (double)ntx.stabil / SCALE_FREQ;
        !           345:                htemp = (double)ntx.jitter;
        !           346: #ifdef STA_NANO
        !           347:                if (flash & STA_NANO)
        !           348:                        htemp /= 1000.0;
        !           349: #endif
        !           350:                printf(
        !           351:                    "  pps frequency %.3f ppm, stability %.3f ppm, jitter %.3f us,\n",
        !           352:                    ftemp, gtemp, htemp);
        !           353:                printf("  intervals %lu, jitter exceeded %lu, stability exceeded %lu, errors %lu.\n",
        !           354:                    (u_long)ntx.calcnt, (u_long)ntx.jitcnt,
        !           355:                    (u_long)ntx.stbcnt, (u_long)ntx.errcnt);
        !           356:                return (0);
        !           357:        }
        !           358: 
        !           359:        /*
        !           360:         * Put things back together the way we found them.
        !           361:         */
        !           362:     lexit:
        !           363: #ifdef SIGSYS
        !           364:        if (sigaction(SIGSYS, &sigsys, (struct sigaction *)NULL)) {
        !           365:                perror("sigaction() fails to restore SIGSYS trap");
        !           366:                exit(1);
        !           367:        }
        !           368: #endif
        !           369:        exit(0);
        !           370: }
        !           371: 
        !           372: #ifdef SIGSYS
        !           373: /*
        !           374:  * pll_trap - trap processor for undefined syscalls
        !           375:  */
        !           376: void
        !           377: pll_trap(
        !           378:        int arg
        !           379:        )
        !           380: {
        !           381:        pll_control--;
        !           382:        siglongjmp(env, 1);
        !           383: }
        !           384: #endif
        !           385: 
        !           386: /*
        !           387:  * Print a value a la the %b format of the kernel's printf
        !           388:  */
        !           389: char *
        !           390: sprintb(
        !           391:        register u_int v,
        !           392:        register const char *bits
        !           393:        )
        !           394: {
        !           395:        register char *cp;
        !           396:        register int i, any = 0;
        !           397:        register char c;
        !           398:        static char buf[132];
        !           399: 
        !           400:        if (bits && *bits == 8)
        !           401:            (void)sprintf(buf, "0%o", v);
        !           402:        else
        !           403:            (void)sprintf(buf, "0x%x", v);
        !           404:        cp = buf + strlen(buf);
        !           405:        if (bits) {
        !           406:                bits++;
        !           407:                *cp++ = ' ';
        !           408:                *cp++ = '(';
        !           409:                while ((i = *bits++) != 0) {
        !           410:                        if (v & (1 << (i-1))) {
        !           411:                                if (any)
        !           412:                                    *cp++ = ',';
        !           413:                                any = 1;
        !           414:                                for (; (c = *bits) > 32; bits++)
        !           415:                                    *cp++ = c;
        !           416:                        } else
        !           417:                            for (; *bits > 32; bits++)
        !           418:                                continue;
        !           419:                }
        !           420:                *cp++ = ')';
        !           421:        }
        !           422:        *cp = '\0';
        !           423:        return (buf);
        !           424: }
        !           425: 
        !           426: const char *timex_states[] = {
        !           427:        "OK", "INS", "DEL", "OOP", "WAIT", "ERROR"
        !           428: };
        !           429: 
        !           430: const char *
        !           431: timex_state(
        !           432:        register int s
        !           433:        )
        !           434: {
        !           435:        static char buf[32];
        !           436: 
        !           437:        if (s >= 0 && s < sizeof(timex_states) / sizeof(timex_states[0]))
        !           438:            return (timex_states[s]);
        !           439:        sprintf(buf, "TIME-#%d", s);
        !           440:        return (buf);
        !           441: }

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