diff options
author | roberto <roberto@FreeBSD.org> | 1999-12-09 13:01:21 +0000 |
---|---|---|
committer | roberto <roberto@FreeBSD.org> | 1999-12-09 13:01:21 +0000 |
commit | ef64b99e8412f2273dd2e8b3291c2f78ffc4667f (patch) | |
tree | fc0cfa1aab0ff6b228f511b410733ef4f35d1ead /contrib/ntp/clockstuff/clktest.c | |
download | FreeBSD-src-ef64b99e8412f2273dd2e8b3291c2f78ffc4667f.zip FreeBSD-src-ef64b99e8412f2273dd2e8b3291c2f78ffc4667f.tar.gz |
Virgin import of ntpd 4.0.98f
Diffstat (limited to 'contrib/ntp/clockstuff/clktest.c')
-rw-r--r-- | contrib/ntp/clockstuff/clktest.c | 529 |
1 files changed, 529 insertions, 0 deletions
diff --git a/contrib/ntp/clockstuff/clktest.c b/contrib/ntp/clockstuff/clktest.c new file mode 100644 index 0000000..86edf59d --- /dev/null +++ b/contrib/ntp/clockstuff/clktest.c @@ -0,0 +1,529 @@ +/* clktest.c,v 3.1 1993/07/06 01:05:23 jbj Exp + * clktest - test the clock line discipline + * + * usage: clktest -b bps -f -t timeo -s cmd -c char1 -a char2 /dev/whatever + */ + +#include <stdio.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <signal.h> +#include <netinet/in.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/file.h> +#include <sgtty.h> + +#include "../include/ntp_fp.h" +#include "../include/ntp.h" +#include "../include/ntp_unixtime.h" + +#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0) + +#if defined(ULT_2_0_SUCKS) +#ifndef sigmask +#define sigmask(m) (1<<(m)) +#endif +#endif + +#ifndef STREAM +#ifndef CLKLDISC +CLOCK_LINE_DISCIPLINE_NEEDED_BY_THIS_PROGRAM; +#endif +#endif + +/* + * Mask for blocking SIGIO and SIGALRM + */ +#define BLOCKSIGMASK (sigmask(SIGIO)|sigmask(SIGALRM)) + +/* + * speed table + */ +struct speeds { + int bps; + int rate; +} speedtab[] = { + { 300, B300 }, + { 1200, B1200 }, + { 2400, B2400 }, + { 4800, B4800 }, + { 9600, B9600 }, + { 19200, EXTA }, + { 38400, EXTB }, + { 0, 0 } +}; + +char *progname; +int debug; + +#ifdef CLKLDISC +#define DEFMAGIC '\r' +#endif + +#ifdef CLKLDISC +# ifdef STREAM +# include <stropts.h> +# ifdef HAVE_SYS_CLKDEFS_H +# include <sys/clkdefs.h> +# endif +# define DEFMAGIC "\r" +# endif +#endif + +struct timeval timeout = { 0 }; +char *cmd = NULL; +int cmdlen; +int docmd = 0; +#ifdef CLKLDISC +u_long magic1 = DEFMAGIC; +u_long magic2 = DEFMAGIC; +#endif +#ifdef STREAM +char magic[32]; +#endif +int speed = B9600; +int ttflags = RAW|EVENP|ODDP; + +volatile int wasalarmed; +volatile int iosig; + +struct timeval lasttv; + +extern u_long ustotslo[]; +extern u_long ustotsmid[]; +extern u_long ustotshi[]; + +/* + * main - parse arguments and handle options + */ +int +main( + int argc, + char *argv[] + ) +{ + int c; + int errflg = 0; + struct speeds *spd; + u_long tmp; + int fd; + struct sgttyb ttyb; + struct itimerval itimer; + extern int ntp_optind; + extern char *ntp_optarg; + int alarming(); + int ioready(); + + progname = argv[0]; +#ifdef STREAM + magic[0] = 0; +#endif + while ((c = ntp_getopt(argc, argv, "a:b:c:dfs:t:")) != EOF) + switch (c) { +#ifdef CLKLDISC + case 'a': +#endif + case 'c': + if (!atouint(ntp_optarg, &tmp)) { + (void) fprintf(stderr, + "%s: argument for -%c must be integer\n", + progname, c); + errflg++; + break; + } +#ifdef CLKLDISC + if (c == 'c') + magic1 = tmp; + else + magic2 = tmp; +#endif +#ifdef STREAM + magic[strlen(magic)+1] = '\0'; + magic[strlen(magic)] = tmp; +#endif + break; + case 'b': + if (!atouint(ntp_optarg, &tmp)) { + errflg++; + break; + } + spd = speedtab; + while (spd->bps != 0) + if ((int)tmp == spd->bps) + break; + if (spd->bps == 0) { + (void) fprintf(stderr, + "%s: speed %lu is unsupported\n", + progname, tmp); + errflg++; + } else { + speed = spd->rate; + } + break; + case 'd': + ++debug; + break; + case 'f': + ttflags |= CRMOD; + break; + case 's': + cmdlen = strlen(ntp_optarg); + if (cmdlen == 0) + errflg++; + else + cmd = ntp_optarg; + break; + case 't': + if (!atouint(ntp_optarg, &tmp)) + errflg++; + else { + timeout.tv_sec = (long)tmp; + docmd = 1; + } + break; + default: + errflg++; + break; + } + if (errflg || ntp_optind+1 != argc) { + (void) fprintf(stderr, +#ifdef CLKLDISC + "usage: %s [-b bps] [-c magic1] [-a magic2] [-f] [-s cmd] [-t timeo] tty_device\n", +#endif +#ifdef STREAM + "usage: %s [-b bps] [-c magic1] [-c magic2]... [-f] [-s cmd] [-t timeo] tty_device\n", +#endif + progname); + exit(2); + } + +#ifdef STREAM + if (!strlen(magic)) + strcpy(magic,DEFMAGIC); +#endif + + if (docmd) + fd = open(argv[ntp_optind], O_RDWR, 0777); + else + fd = open(argv[ntp_optind], O_RDONLY, 0777); + if (fd == -1) { + (void) fprintf(stderr, "%s: open(%s): ", progname, + argv[ntp_optind]); + perror(""); + exit(1); + } + + if (ioctl(fd, TIOCEXCL, (char *)0) < 0) { + (void) fprintf(stderr, "%s: ioctl(TIOCEXCL): ", progname); + perror(""); + exit(1); + } + + /* + * If we have the clock discipline, set the port to raw. Otherwise + * we run cooked. + */ + ttyb.sg_ispeed = ttyb.sg_ospeed = speed; +#ifdef CLKLDISC + ttyb.sg_erase = (char)magic1; + ttyb.sg_kill = (char)magic2; +#endif + ttyb.sg_flags = (short)ttflags; + if (ioctl(fd, TIOCSETP, (char *)&ttyb) < 0) { + (void) fprintf(stderr, "%s: ioctl(TIOCSETP): ", progname); + perror(""); + exit(1); + } + + if (fcntl(fd, F_SETOWN, getpid()) == -1) { + (void) fprintf(stderr, "%s: fcntl(F_SETOWN): ", progname); + perror(""); + exit(1); + } + +#ifdef CLKLDISC + { + int ldisc; + ldisc = CLKLDISC; + if (ioctl(fd, TIOCSETD, (char *)&ldisc) < 0) { + (void) fprintf(stderr, "%s: ioctl(TIOCSETD): ", progname); + perror(""); + exit(1); + } + } +#endif +#ifdef STREAM + if (ioctl(fd, I_POP, 0) >=0 ) ; + if (ioctl(fd, I_PUSH, "clk") < 0) { + (void) fprintf(stderr, "%s: ioctl(I_PUSH): ", progname); + perror(""); + exit(1); + } + if (ioctl(fd, CLK_SETSTR, magic) < 0) { + (void) fprintf(stderr, "%s: ioctl(CLK_SETSTR): ", progname); + perror(""); + exit(1); + } +#endif + + + (void) gettimeofday(&lasttv, (struct timezone *)0); + if (docmd) { + /* + * set non-blocking, async I/O on the descriptor + */ + iosig = 0; + (void) signal(SIGIO, ioready); + if (fcntl(fd, F_SETFL, FNDELAY|FASYNC) < 0) { + (void) fprintf(stderr, "%s: fcntl(F_SETFL): ", + progname); + perror(""); + exit(1); + } + + /* + * Set up the alarm interrupt. + */ + wasalarmed = 0; + (void) signal(SIGALRM, alarming); + itimer.it_interval = itimer.it_value = timeout; + setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0); + doboth(fd); + } + doioonly(fd); +} + + +/* + * doboth - handle both I/O and alarms via SIGIO + */ +int +doboth( + int fd + ) +{ + int n; + int sawalarm; + int sawiosig; + int omask; + fd_set fds; + struct timeval tvzero; + + sawalarm = 0; + sawiosig = 0; + FD_ZERO(&fds); + for (;;) { + omask = sigblock(BLOCKSIGMASK); + if (wasalarmed) { /* alarmed? */ + sawalarm = 1; + wasalarmed = 0; + } + if (iosig) { + sawiosig = 1; + iosig = 0; + } + + if (!sawalarm && !sawiosig) { + /* + * Nothing to do. Wait for something. + */ + sigpause(omask); + if (wasalarmed) { /* alarmed? */ + sawalarm = 1; + wasalarmed = 0; + } + if (iosig) { + sawiosig = 1; + iosig = 0; + } + } + (void)sigsetmask(omask); + + if (sawiosig) { + + do { + tvzero.tv_sec = tvzero.tv_usec = 0; + FD_SET(fd, &fds); + n = select(fd+1, &fds, (fd_set *)0, + (fd_set *)0, &tvzero); + if (n > 0) + doio(fd); + } while (n > 0); + + if (n == -1) { + (void) fprintf(stderr, "%s: select: ", + progname); + perror(""); + exit(1); + } + sawiosig = 0; + } + if (sawalarm) { + doalarm(fd); + sawalarm = 0; + } + } +} + + +/* + * doioonly - do I/O. This avoids the use of signals + */ +int +doioonly( + int fd + ) +{ + int n; + fd_set fds; + + FD_ZERO(&fds); + for (;;) { + FD_SET(fd, &fds); + n = select(fd+1, &fds, (fd_set *)0, (fd_set *)0, + (struct timeval *)0); + if (n > 0) + doio(fd); + } +} + + +/* + * doio - read a buffer full of stuff and print it out + */ +int +doio( + int fd + ) +{ + register char *rp, *rpend; + register char *cp; + register int i; + char raw[512]; + struct timeval tv, tvd; + int rlen; + int ind; + char cooked[2049]; + static char *digits = "0123456789abcdef"; + + rlen = read(fd, raw, sizeof(raw)); + if (rlen < 0) { + (void) fprintf(stderr, "%s: read(): ", progname); + perror(""); + return; + } + if (rlen == 0) { + (void) printf("Zero length read\n"); + return; + } + + cp = cooked; + rp = raw; + rpend = &raw[rlen]; + ind = 0; + + while (rp < rpend) { + ind = 1; + if (isprint(*rp)) + *cp++ = *rp; + else { + *cp++ = '<'; + *cp++ = digits[((*rp)>>4) & 0xf]; + *cp++ = digits[*rp & 0xf]; + *cp++ = '>'; + } + if ( +#ifdef CLKLDISC + (*rp == (char)magic1 || *rp == (char)magic2) +#else + ( strchr( magic, *rp) != NULL ) +#endif + ) { + rp++; + ind = 0; + *cp = '\0'; + if ((rpend - rp) < sizeof(struct timeval)) { + (void)printf( + "Too little data (%d): %s\n", + rpend-rp, cooked); + return; + } + + tv.tv_sec = 0; + for (i = 0; i < 4; i++) { + tv.tv_sec <<= 8; + tv.tv_sec |= ((long)*rp++) & 0xff; + } + tv.tv_usec = 0; + for (i = 0; i < 4; i++) { + tv.tv_usec <<= 8; + tv.tv_usec |= ((long)*rp++) & 0xff; + } + + tvd.tv_sec = tv.tv_sec - lasttv.tv_sec; + tvd.tv_usec = tv.tv_usec - lasttv.tv_usec; + if (tvd.tv_usec < 0) { + tvd.tv_usec += 1000000; + tvd.tv_sec--; + } + + (void)printf("%lu.%06lu %lu.%06lu %s\n", + tv.tv_sec, tv.tv_usec, tvd.tv_sec, tvd.tv_usec, + cooked); + lasttv = tv; + } else { + rp++; + } + } + + if (ind) { + *cp = '\0'; + (void)printf("Incomplete data: %s\n", cooked); + } +} + + +/* + * doalarm - send a string out the port, if we have one. + */ +int +doalarm( + int fd + ) +{ + int n; + + if (cmd == NULL || cmdlen <= 0) + return; + + n = write(fd, cmd, cmdlen); + + if (n < 0) { + (void) fprintf(stderr, "%s: write(): ", progname); + perror(""); + } else if (n < cmdlen) { + (void) printf("Short write (%d bytes, should be %d)\n", + n, cmdlen); + } +} + + +/* + * alarming - receive alarm interupt + */ +void +alarming(void) +{ + wasalarmed = 1; +} + +/* + * ioready - handle SIGIO interrupt + */ +void +ioready(void) +{ + iosig = 1; +} |