diff options
Diffstat (limited to 'ntpshmmon.c')
-rw-r--r-- | ntpshmmon.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/ntpshmmon.c b/ntpshmmon.c new file mode 100644 index 00000000..044f9268 --- /dev/null +++ b/ntpshmmon.c @@ -0,0 +1,127 @@ +/* ntpshmmon.c -- monitor the inner end of an ntpshmwrite.connection + * + * This file is Copyright (c) 2010 by the GPSD project + * BSD terms apply: see the file COPYING in the distribution root for details. + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <getopt.h> +#ifndef S_SPLINT_S +#include <unistd.h> +#endif /* S_SPLINT_S */ + +#include "ntpshm.h" + +#define NTPSEGMENTS 256 /* NTPx for x any byte */ + +static struct shmTime *segments[NTPSEGMENTS + 1]; +static struct timespec tick[NTPSEGMENTS + 1]; + +static void shm_shutdown(void) +/* shut down all active segments */ +{ + struct shmTime **pp; + + for (pp = segments; pp < segments + NTPSEGMENTS; pp++) + if (*pp != NULL) + (void)shmdt((void *)(*pp)); +} + +int main(int argc, char **argv) +{ + int units = 0; + int option; + int i; + bool verbose = false; + +#define USAGE "usage: ntpshmmon [-s] [-v] [-h]\n" + while ((option = getopt(argc, argv, "hsv")) != -1) { + switch (option) { + case 's': + if (units > 0) { + shm_shutdown(); + exit(EXIT_SUCCESS); + } else { + fprintf(stderr, "ntpshmmon: zero units declared.\n"); + exit(EXIT_FAILURE); + } + //0break; + case 'v': + verbose = true; + break; + case 'h': + default: + fprintf(stderr, USAGE); + break; + } + } + + /* grab all segments, keep the non-null ones */ + for (i = 0; i < NTPSEGMENTS; i++) { + segments[i] = shm_get(i, false, true); + if (verbose && segments[i] != NULL) + fprintf(stderr, "unit %d opened\n", i); + } + (void)printf("ntpshmmon version 1\n"); + + for (;;) { + struct shm_stat_t shm_stat; + + for (i = 0; i < NTPSEGMENTS; i++) { + enum segstat_t status = shm_query(segments[i], &shm_stat); + if (verbose) + fprintf(stderr, "unit %d status %d\n", i, status); + switch(status) + { + case OK: + /*@-mustfreefresh -formattype@*/ + /*@-type@*//* splint is confused about struct timespec */ + if (shm_stat.tvc.tv_sec != tick[i].tv_sec || shm_stat.tvc.tv_nsec != tick[i].tv_nsec) { + printf("sample %s %ld.%09ld %ld.%09ld %ld.%09ld %d %3d\n", + shm_name(i), + shm_stat.tvc.tv_sec, shm_stat.tvc.tv_nsec, + shm_stat.tvr.tv_sec, shm_stat.tvr.tv_nsec, + shm_stat.tvt.tv_sec, shm_stat.tvt.tv_nsec, + shm_stat.leap, shm_stat.precision); + tick[i] = shm_stat.tvc; + } + /*@+type@*/ + /*@+mustfreefresh +formattype@*/ + break; + case NO_SEGMENT: + break; + case NOT_READY: + /* do nothing, data not ready, wait another cycle */ + break; + case BAD_MODE: + /*@-mustfreefresh@*/ + fprintf(stderr, "ntpshmmon: unknown mode %d on segment %s\n", + shm_stat.status, shm_name(i)); + /*@+mustfreefresh@*/ + break; + case CLASH: + /* do nothing, data is corrupt, wait another cycle */ + break; + default: + /*@-mustfreefresh@*/ + fprintf(stderr, "ntpshmmon: unknown status %d on segment %s\n", + status, shm_name(i)); + /*@+mustfreefresh@*/ + break; + } + } + + /* + * Even on a 1 Hz PPS, a sleep(1) may end up + * being sleep(1.1) and missing a beat. Since + * we're ignoring duplicates via timestamp, polling + * at interval < 1 sec shouldn't be a problem. + */ + (void)usleep(1000); + } + + //exit(EXIT_SUCCESS); +} + +/* end */ |