Annotation of embedaddon/ntp/util/ntptime.c, revision 1.1.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>