home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xntp3.zip / clockstuff / clktest.c < prev    next >
C/C++ Source or Header  |  1992-05-11  |  9KB  |  511 lines

  1. /*
  2.  * clktest - test the clock line discipline
  3.  *
  4.  * usage: clktest -b bps -f -t timeo -s cmd -c char1 -a char2 /dev/whatever
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9. #include <sys/types.h>
  10. #include <sys/socket.h>
  11. #include <signal.h>
  12. #include <netinet/in.h>
  13. #include <sys/ioctl.h>
  14. #include <sys/time.h>
  15. #include <sys/file.h>
  16. #include <sgtty.h>
  17.  
  18. #include "../include/ntp_fp.h"
  19. #include "../include/ntp.h"
  20. #include "../include/ntp_unixtime.h"
  21.  
  22. #define    STREQ(a, b)    (*(a) == *(b) && strcmp((a), (b)) == 0)
  23.  
  24. #if defined(ULT_2_0_SUCKS)
  25. #ifndef sigmask
  26. #define    sigmask(m)    (1<<(m))
  27. #endif
  28. #endif
  29.  
  30. #ifndef STREAM
  31. #ifndef CLKLDISC
  32.     CLOCK_LINE_DISCIPLINE_NEEDED_BY_THIS_PROGRAM;
  33. #endif
  34. #endif
  35.  
  36. /*
  37.  * Mask for blocking SIGIO and SIGALRM
  38.  */
  39. #define    BLOCKSIGMASK    (sigmask(SIGIO)|sigmask(SIGALRM))
  40.  
  41. /*
  42.  * speed table
  43.  */
  44. struct speeds {
  45.     int bps;
  46.     int rate;
  47. } speedtab[] = {
  48.     { 300,        B300 },
  49.     { 1200,        B1200 },
  50.     { 2400,        B2400 },
  51.     { 4800,        B4800 },
  52.     { 9600,        B9600 },
  53.     { 19200,    EXTA },
  54.     { 0,        0 }
  55. };
  56.  
  57. char *progname;
  58. int debug;
  59.  
  60. #ifdef CLKDISC
  61. #define    DEFMAGIC    '\r'
  62. #endif
  63.  
  64. #ifdef STREAM
  65. #include <stropts.h>
  66. #include <sys/clkdefs.h>
  67. #define DEFMAGIC    "\r"
  68. #endif
  69.  
  70. struct timeval timeout = { 0 };
  71. char *cmd = NULL;
  72. int cmdlen;
  73. int docmd = 0;
  74. #ifdef CLKDISC
  75. u_long magic1 = DEFMAGIC;
  76. u_long magic2 = DEFMAGIC;
  77. #endif
  78. #ifdef STREAM
  79. char magic[32];
  80. #endif
  81. int speed = B9600;
  82. int ttflags = RAW|EVENP|ODDP;
  83.  
  84. int wasalarmed;
  85. int iosig;
  86.  
  87. struct timeval lasttv;
  88.  
  89. extern u_long ustotslo[];
  90. extern u_long ustotsmid[];
  91. extern u_long ustotshi[];
  92.  
  93. /*
  94.  * main - parse arguments and handle options
  95.  */
  96. main(argc, argv)
  97. int argc;
  98. char *argv[];
  99. {
  100.     int c;
  101.     int errflg = 0;
  102.     struct speeds *spd;
  103.     u_long tmp;
  104.     int fd;
  105.     struct sgttyb ttyb;
  106.     struct itimerval itimer;
  107.     extern int optind;
  108.     extern char *optarg;
  109.     int alarming();
  110.     int ioready();
  111.  
  112.     progname = argv[0];
  113. #ifdef STREAM
  114.     magic[0] = 0;
  115. #endif
  116.     while ((c = getopt(argc, argv, "a:c:dfs:t:")) != EOF)
  117.         switch (c) {
  118. #ifdef CLKDISC
  119.         case 'a':
  120. #endif
  121.         case 'c':
  122.             if (!atouint(optarg, &tmp)) {
  123.                 (void) fprintf(stderr,
  124.                     "%s: argument for -%c must be integer\n",
  125.                     progname, c);
  126.                 errflg++;
  127.                 break;
  128.             }
  129. #ifdef CLKDISC
  130.             if (c == 'c')
  131.                 magic1 = tmp;
  132.             else
  133.                 magic2 = tmp;
  134. #endif
  135. #ifdef STREAM
  136.             magic[strlen(magic)+1] = '\0';
  137.             magic[strlen(magic)] = tmp;
  138. #endif
  139.             break;
  140.         case 'b':
  141.             if (!atouint(optarg, &tmp)) {
  142.                 errflg++;
  143.                 break;
  144.             }
  145.             spd = speedtab;
  146.             while (spd->bps != 0)
  147.                 if ((int)tmp == spd->bps)
  148.                     break;
  149.             if (spd->bps == 0) {
  150.                 (void) fprintf(stderr,
  151.                     "%s: speed %lu is unsupported\n",
  152.                     progname, tmp);
  153.                 errflg++;
  154.             } else {
  155.                 speed = spd->rate;
  156.             }
  157.             break;
  158.         case 'd':
  159.             ++debug;
  160.             break;
  161.         case 'f':
  162.             ttflags |= CRMOD;
  163.             break;
  164.         case 's':
  165.             cmdlen = strlen(optarg);
  166.             if (cmdlen == 0)
  167.                 errflg++;
  168.             else
  169.                 cmd = optarg;
  170.             break;
  171.         case 't':
  172.             if (!atouint(optarg, &tmp))
  173.                 errflg++;
  174.             else {
  175.                 timeout.tv_sec = (long)tmp;
  176.                 docmd = 1;
  177.             }
  178.             break;
  179.         default:
  180.             errflg++;
  181.             break;
  182.         }
  183.     if (errflg || optind+1 != argc) {
  184.         (void) fprintf(stderr,
  185. #ifdef CLKDISC
  186. "usage: %s [-c magic1] [-a magic2] [-f] [-s cmd] [-t timeo]  tty_device\n",
  187. #endif
  188. #ifdef STREAM
  189. "usage: %s [-c magic1] [-c magic2]... [-f] [-s cmd] [-t timeo]  tty_device\n",
  190. #endif
  191.             progname);
  192.         exit(2);
  193.     }
  194.  
  195. #ifdef STREAM
  196.     if (!strlen(magic))
  197.         strcpy(magic,DEFMAGIC);
  198. #endif
  199.  
  200.     if (docmd)
  201.         fd = open(argv[optind], O_RDWR, 0777);
  202.     else
  203.         fd = open(argv[optind], O_RDONLY, 0777);
  204.     if (fd == -1) {
  205.         (void) fprintf(stderr, "%s: open(%s): ", progname,
  206.             argv[optind]);
  207.         perror("");
  208.         exit(1);
  209.     }
  210.  
  211.     if (ioctl(fd, TIOCEXCL, (char *)0) < 0) {
  212.         (void) fprintf(stderr, "%s: ioctl(TIOCEXCL): ", progname);
  213.         perror("");
  214.         exit(1);
  215.     }
  216.  
  217.     /*
  218.      * If we have the clock discipline, set the port to raw.  Otherwise
  219.      * we run cooked.
  220.      */
  221.     ttyb.sg_ispeed = ttyb.sg_ospeed = speed;
  222. #ifdef CLKDISC
  223.     ttyb.sg_erase = (char)magic1;
  224.     ttyb.sg_kill = (char)magic2;
  225. #endif
  226.     ttyb.sg_flags = (short)ttflags;
  227.     if (ioctl(fd, TIOCSETP, (char *)&ttyb) < 0) {
  228.         (void) fprintf(stderr, "%s: ioctl(TIOCSETP): ", progname);
  229.         perror("");
  230.         exit(1);
  231.     }
  232.  
  233.     if (fcntl(fd, F_SETOWN, getpid()) == -1) {
  234.         (void) fprintf(stderr, "%s: fcntl(F_SETOWN): ", progname);
  235.         perror("");
  236.         exit(1);
  237.     }
  238.  
  239. #ifdef CLKDISC
  240.     {
  241.     int ldisc;
  242.     ldisc = CLKLDISC;
  243.     if (ioctl(fd, TIOCSETD, (char *)&ldisc) < 0) {
  244.         (void) fprintf(stderr, "%s: ioctl(TIOCSETD): ", progname);
  245.         perror("");
  246.         exit(1);
  247.     }
  248.     }
  249. #endif
  250. #ifdef STREAM
  251.     if (ioctl(fd, I_POP, 0) >=0 ) ;
  252.     if (ioctl(fd, I_PUSH, "chu") < 0) {
  253.         (void) fprintf(stderr, "%s: ioctl(I_PUSH): ", progname);
  254.         perror("");
  255.         exit(1);
  256.     }
  257.     if (ioctl(fd, CLK_SETSTR, magic) < 0) {
  258.         (void) fprintf(stderr, "%s: ioctl(CLK_SETSTR): ", progname);
  259.         perror("");
  260.         exit(1);
  261.     }
  262. #endif
  263.  
  264.  
  265.     (void) gettimeofday(&lasttv, (struct timezone *)0);
  266.     if (docmd) {
  267.         /*
  268.          * set non-blocking, async I/O on the descriptor
  269.          */
  270.         iosig = 0;
  271.         (void) signal(SIGIO, ioready);
  272.         if (fcntl(fd, F_SETFL, FNDELAY|FASYNC) < 0) {
  273.             (void) fprintf(stderr, "%s: fcntl(F_SETFL): ",
  274.             progname);
  275.             perror("");
  276.             exit(1);
  277.         }
  278.  
  279.         /*
  280.          * Set up the alarm interrupt.
  281.          */
  282.         wasalarmed = 0;
  283.         (void) signal(SIGALRM, alarming);
  284.         itimer.it_interval = itimer.it_value = timeout;
  285.     setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
  286.         doboth(fd);
  287.     }
  288.     doioonly(fd);
  289. }
  290.  
  291.  
  292. /*
  293.  * doboth - handle both I/O and alarms via SIGIO
  294.  */
  295. doboth(fd)
  296.     int fd;
  297. {
  298.     int n;
  299.     int sawalarm;
  300.     int sawiosig;
  301.     int omask;
  302.     fd_set fds;
  303.     struct timeval tvzero;
  304.  
  305.     sawalarm = 0;
  306.     sawiosig = 0;
  307.     FD_ZERO(&fds);
  308.     for (;;) {
  309.         omask = sigblock(BLOCKSIGMASK);
  310.         if (wasalarmed) {        /* alarmed? */
  311.             sawalarm = 1;
  312.             wasalarmed = 0;
  313.         }
  314.         if (iosig) {
  315.             sawiosig = 1;
  316.             iosig = 0;
  317.         }
  318.  
  319.         if (!sawalarm && !sawiosig) {
  320.             /*
  321.              * Nothing to do.  Wait for something.
  322.              */
  323.             sigpause(omask);
  324.             if (wasalarmed) {        /* alarmed? */
  325.                 sawalarm = 1;
  326.                 wasalarmed = 0;
  327.             }
  328.             if (iosig) {
  329.                 sawiosig = 1;
  330.                 iosig = 0;
  331.             }
  332.         }
  333.         (void)sigsetmask(omask);
  334.  
  335.         if (sawiosig) {
  336.  
  337.             do {
  338.                 tvzero.tv_sec = tvzero.tv_usec = 0;
  339.                 FD_SET(fd, &fds);
  340.                 n = select(fd+1, &fds, (fd_set *)0,
  341.                     (fd_set *)0, &tvzero);
  342.                 if (n > 0)
  343.                     doio(fd);
  344.             } while (n > 0);
  345.  
  346.             if (n == -1) {
  347.                 (void) fprintf(stderr, "%s: select: ",
  348.                     progname);
  349.                 perror("");
  350.                 exit(1);
  351.             }
  352.             sawiosig = 0;
  353.         }
  354.         if (sawalarm) {
  355.             doalarm(fd);
  356.             sawalarm = 0;
  357.         }
  358.     }
  359. }
  360.  
  361.  
  362. /*
  363.  * doioonly - do I/O.  This avoids the use of signals
  364.  */
  365. doioonly(fd)
  366.     int fd;
  367. {
  368.     int n;
  369.     fd_set fds;
  370.  
  371.     FD_ZERO(&fds);
  372.     for (;;) {
  373.         FD_SET(fd, &fds);
  374.         n = select(fd+1, &fds, (fd_set *)0, (fd_set *)0,
  375.             (struct timeval *)0);
  376.         if (n > 0)
  377.             doio(fd);
  378.     }
  379. }
  380.  
  381.  
  382. /*
  383.  * doio - read a buffer full of stuff and print it out
  384.  */
  385. doio(fd)
  386.     int fd;
  387. {
  388.     register char *rp, *rpend;
  389.     register char *cp;
  390.     register int i;
  391.     char raw[512];
  392.     struct timeval tv, tvd;
  393.     int rlen;
  394.     int ind;
  395.     char cooked[2049];
  396.     static char *digits = "0123456789abcdef";
  397.  
  398.     rlen = read(fd, raw, sizeof(raw));
  399.     if (rlen < 0) {
  400.         (void) fprintf(stderr, "%s: read(): ", progname);
  401.         perror("");
  402.         return;
  403.     }
  404.     if (rlen == 0) {
  405.         (void) printf("Zero length read\n");
  406.         return;
  407.     }
  408.  
  409.     cp = cooked;
  410.     rp = raw;
  411.     rpend = &raw[rlen];
  412.     ind = 0;
  413.  
  414.     while (rp < rpend) {
  415.         ind = 1;
  416.         if (isprint(*rp))
  417.             *cp++ = *rp;
  418.         else {
  419.             *cp++ = '<';
  420.             *cp++ = digits[((*rp)>>4) & 0xf];
  421.             *cp++ = digits[*rp & 0xf];
  422.             *cp++ = '>';
  423.         }
  424. #ifdef CLKDISC
  425.         if (*rp == (char)magic1 || *rp == (char)magic2) {
  426. #else
  427.         if ( strchr( magic, *rp) != NULL ) {
  428. #endif
  429.             rp++;
  430.             ind = 0;
  431.             *cp = '\0';
  432.             if ((rpend - rp) < sizeof(struct timeval)) {
  433.                 (void)printf(
  434.                     "Too little data (%d): %s\n",
  435.                     rpend-rp, cooked);
  436.                 return;
  437.             }
  438.  
  439.             tv.tv_sec = 0;
  440.             for (i = 0; i < 4; i++) {
  441.                 tv.tv_sec <<= 8;
  442.                 tv.tv_sec |= ((long)*rp++) & 0xff;
  443.             }
  444.             tv.tv_usec = 0;
  445.             for (i = 0; i < 4; i++) {
  446.                 tv.tv_usec <<= 8;
  447.                 tv.tv_usec |= ((long)*rp++) & 0xff;
  448.             }
  449.  
  450.             tvd.tv_sec = tv.tv_sec - lasttv.tv_sec;
  451.             tvd.tv_usec = tv.tv_usec - lasttv.tv_usec;
  452.             if (tvd.tv_usec < 0) {
  453.                 tvd.tv_usec += 1000000;
  454.                 tvd.tv_sec--;
  455.             }
  456.  
  457.             (void)printf("%lu.%06lu %lu.%06lu %s\n",
  458.                 tv.tv_sec, tv.tv_usec, tvd.tv_sec, tvd.tv_usec,
  459.                 cooked);
  460.             lasttv = tv;
  461.         } else {
  462.             rp++;
  463.         }
  464.     }
  465.  
  466.     if (ind) {
  467.         *cp = '\0';
  468.         (void)printf("Incomplete data: %s\n", cooked);
  469.     }
  470. }
  471.  
  472.  
  473. /*
  474.  * doalarm - send a string out the port, if we have one.
  475.  */
  476. doalarm(fd)
  477.     int fd;
  478. {
  479.     int n;
  480.  
  481.     if (cmd == NULL || cmdlen <= 0)
  482.         return;
  483.  
  484.     n = write(fd, cmd, cmdlen);
  485.  
  486.     if (n < 0) {
  487.         (void) fprintf(stderr, "%s: write(): ", progname);
  488.         perror("");
  489.     } else if (n < cmdlen) {
  490.         (void) printf("Short write (%d bytes, should be %d)\n",
  491.             n, cmdlen);
  492.     }
  493. }
  494.  
  495.  
  496. /*
  497.  * alarming - receive alarm interupt
  498.  */
  499. alarming()
  500. {
  501.     wasalarmed = 1;
  502. }
  503.  
  504. /*
  505.  * ioready - handle SIGIO interrupt
  506.  */
  507. ioready()
  508. {
  509.     iosig = 1;
  510. }
  511.