/contrib/ntp/clockstuff/clktest.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 412 lines · 318 code · 52 blank · 42 comment · 57 complexity · e5659509dd27fcc05c687e3280e971f4 MD5 · raw file

  1. /* clktest.c,v 3.1 1993/07/06 01:05:23 jbj Exp
  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. #include "clktest-opts.h"
  7. #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
  8. #if defined(ULT_2_0_SUCKS)
  9. #ifndef sigmask
  10. #define sigmask(m) (1<<(m))
  11. #endif
  12. #endif
  13. #ifndef STREAM
  14. # ifndef CLKLDISC
  15. CLOCK_LINE_DISCIPLINE_NEEDED_BY_THIS_PROGRAM;
  16. # endif
  17. #else
  18. # ifdef CLKLDISC
  19. ONLY_ONE_CLOCK_LINE_DISCIPLINE_FOR_THIS_PROGRAM;
  20. # endif
  21. #endif
  22. /*
  23. * Mask for blocking SIGIO and SIGALRM
  24. */
  25. #define BLOCKSIGMASK (sigmask(SIGIO)|sigmask(SIGALRM))
  26. #define progname clktestOptions.pzProgName
  27. struct timeval timeout = { 0 };
  28. char *cmd = NULL;
  29. int cmdlen;
  30. #ifdef CLKLDISC
  31. u_long magic1 = DEFMAGIC;
  32. u_long magic2 = DEFMAGIC;
  33. #endif
  34. int speed = B9600;
  35. int ttflags = RAW|EVENP|ODDP;
  36. volatile int wasalarmed;
  37. volatile int iosig;
  38. struct timeval lasttv;
  39. extern u_long ustotslo[];
  40. extern u_long ustotsmid[];
  41. extern u_long ustotshi[];
  42. int alarming();
  43. int ioready();
  44. /*
  45. * main - parse arguments and handle options
  46. */
  47. int
  48. main(
  49. int argc,
  50. char *argv[]
  51. )
  52. {
  53. int fd;
  54. struct sgttyb ttyb;
  55. struct itimerval itimer;
  56. #ifdef STREAM
  57. magic[0] = 0;
  58. #endif
  59. {
  60. int ct = optionProcess( &clktestOptions, argc, argv );
  61. if (HAVE_OPT(COMMAND) && (strlen(OPT_ARG(COMMAND)) == 0)) {
  62. fputs( "The command option string must not be empty\n", stderr );
  63. USAGE( EXIT_FAILURE );
  64. }
  65. if ((argc -= ct) != 1) {
  66. fputs( "Missing tty device name\n", stderr );
  67. USAGE( EXIT_FAILURE );
  68. }
  69. argv += ct;
  70. }
  71. #ifdef STREAM
  72. if (!strlen(magic))
  73. strcpy(magic,DEFMAGIC);
  74. #endif
  75. fd = open(*argv, HAVE_OPT(TIMEOUT) ? O_RDWR : O_RDONLY, 0777);
  76. if (fd == -1) {
  77. fprintf(stderr, "%s: open(%s): ", progname, *argv);
  78. perror("");
  79. exit(1);
  80. }
  81. if (ioctl(fd, TIOCEXCL, (char *)0) < 0) {
  82. (void) fprintf(stderr, "%s: ioctl(TIOCEXCL): ", progname);
  83. perror("");
  84. exit(1);
  85. }
  86. /*
  87. * If we have the clock discipline, set the port to raw. Otherwise
  88. * we run cooked.
  89. */
  90. ttyb.sg_ispeed = ttyb.sg_ospeed = speed;
  91. #ifdef CLKLDISC
  92. ttyb.sg_erase = (char)magic1;
  93. ttyb.sg_kill = (char)magic2;
  94. #endif
  95. ttyb.sg_flags = (short)ttflags;
  96. if (ioctl(fd, TIOCSETP, (char *)&ttyb) < 0) {
  97. (void) fprintf(stderr, "%s: ioctl(TIOCSETP): ", progname);
  98. perror("");
  99. exit(1);
  100. }
  101. if (fcntl(fd, F_SETOWN, getpid()) == -1) {
  102. (void) fprintf(stderr, "%s: fcntl(F_SETOWN): ", progname);
  103. perror("");
  104. exit(1);
  105. }
  106. #ifdef CLKLDISC
  107. {
  108. int ldisc;
  109. ldisc = CLKLDISC;
  110. if (ioctl(fd, TIOCSETD, (char *)&ldisc) < 0) {
  111. (void) fprintf(stderr, "%s: ioctl(TIOCSETD): ", progname);
  112. perror("");
  113. exit(1);
  114. }
  115. }
  116. #endif
  117. #ifdef STREAM
  118. if (ioctl(fd, I_POP, 0) >=0 ) ;
  119. if (ioctl(fd, I_PUSH, "clk") < 0) {
  120. (void) fprintf(stderr, "%s: ioctl(I_PUSH): ", progname);
  121. perror("");
  122. exit(1);
  123. }
  124. if (ioctl(fd, CLK_SETSTR, magic) < 0) {
  125. (void) fprintf(stderr, "%s: ioctl(CLK_SETSTR): ", progname);
  126. perror("");
  127. exit(1);
  128. }
  129. #endif
  130. (void) gettimeofday(&lasttv, (struct timezone *)0);
  131. if (HAVE_OPT(TIMEOUT)) {
  132. /*
  133. * set non-blocking, async I/O on the descriptor
  134. */
  135. iosig = 0;
  136. (void) signal(SIGIO, ioready);
  137. if (fcntl(fd, F_SETFL, FNDELAY|FASYNC) < 0) {
  138. (void) fprintf(stderr, "%s: fcntl(F_SETFL): ",
  139. progname);
  140. perror("");
  141. exit(1);
  142. }
  143. /*
  144. * Set up the alarm interrupt.
  145. */
  146. wasalarmed = 0;
  147. (void) signal(SIGALRM, alarming);
  148. timeout.tv_sec = OPT_VALUE_TIMEOUT;
  149. itimer.it_interval = itimer.it_value = timeout;
  150. setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
  151. doboth(fd);
  152. }
  153. doioonly(fd);
  154. }
  155. /*
  156. * doboth - handle both I/O and alarms via SIGIO
  157. */
  158. int
  159. doboth(
  160. int fd
  161. )
  162. {
  163. int n;
  164. int sawalarm;
  165. int sawiosig;
  166. int omask;
  167. fd_set fds;
  168. struct timeval tvzero;
  169. sawalarm = 0;
  170. sawiosig = 0;
  171. FD_ZERO(&fds);
  172. for (;;) {
  173. omask = sigblock(BLOCKSIGMASK);
  174. if (wasalarmed) { /* alarmed? */
  175. sawalarm = 1;
  176. wasalarmed = 0;
  177. }
  178. if (iosig) {
  179. sawiosig = 1;
  180. iosig = 0;
  181. }
  182. if (!sawalarm && !sawiosig) {
  183. /*
  184. * Nothing to do. Wait for something.
  185. */
  186. sigpause(omask);
  187. if (wasalarmed) { /* alarmed? */
  188. sawalarm = 1;
  189. wasalarmed = 0;
  190. }
  191. if (iosig) {
  192. sawiosig = 1;
  193. iosig = 0;
  194. }
  195. }
  196. (void)sigsetmask(omask);
  197. if (sawiosig) {
  198. do {
  199. tvzero.tv_sec = tvzero.tv_usec = 0;
  200. FD_SET(fd, &fds);
  201. n = select(fd+1, &fds, (fd_set *)0,
  202. (fd_set *)0, &tvzero);
  203. if (n > 0)
  204. doio(fd);
  205. } while (n > 0);
  206. if (n == -1) {
  207. (void) fprintf(stderr, "%s: select: ",
  208. progname);
  209. perror("");
  210. exit(1);
  211. }
  212. sawiosig = 0;
  213. }
  214. if (sawalarm) {
  215. doalarm(fd);
  216. sawalarm = 0;
  217. }
  218. }
  219. }
  220. /*
  221. * doioonly - do I/O. This avoids the use of signals
  222. */
  223. int
  224. doioonly(
  225. int fd
  226. )
  227. {
  228. int n;
  229. fd_set fds;
  230. FD_ZERO(&fds);
  231. for (;;) {
  232. FD_SET(fd, &fds);
  233. n = select(fd+1, &fds, (fd_set *)0, (fd_set *)0,
  234. (struct timeval *)0);
  235. if (n > 0)
  236. doio(fd);
  237. }
  238. }
  239. /*
  240. * doio - read a buffer full of stuff and print it out
  241. */
  242. int
  243. doio(
  244. int fd
  245. )
  246. {
  247. register char *rp, *rpend;
  248. register char *cp;
  249. register int i;
  250. char raw[512];
  251. struct timeval tv, tvd;
  252. int rlen;
  253. int ind;
  254. char cooked[2049];
  255. static char *digits = "0123456789abcdef";
  256. rlen = read(fd, raw, sizeof(raw));
  257. if (rlen < 0) {
  258. (void) fprintf(stderr, "%s: read(): ", progname);
  259. perror("");
  260. return;
  261. }
  262. if (rlen == 0) {
  263. (void) printf("Zero length read\n");
  264. return;
  265. }
  266. cp = cooked;
  267. rp = raw;
  268. rpend = &raw[rlen];
  269. ind = 0;
  270. while (rp < rpend) {
  271. ind = 1;
  272. if (isprint(*rp))
  273. *cp++ = *rp;
  274. else {
  275. *cp++ = '<';
  276. *cp++ = digits[((*rp)>>4) & 0xf];
  277. *cp++ = digits[*rp & 0xf];
  278. *cp++ = '>';
  279. }
  280. if (
  281. #ifdef CLKLDISC
  282. (*rp == (char)magic1 || *rp == (char)magic2)
  283. #else
  284. ( strchr( magic, *rp) != NULL )
  285. #endif
  286. ) {
  287. rp++;
  288. ind = 0;
  289. *cp = '\0';
  290. if ((rpend - rp) < sizeof(struct timeval)) {
  291. (void)printf(
  292. "Too little data (%d): %s\n",
  293. rpend-rp, cooked);
  294. return;
  295. }
  296. tv.tv_sec = 0;
  297. for (i = 0; i < 4; i++) {
  298. tv.tv_sec <<= 8;
  299. tv.tv_sec |= ((long)*rp++) & 0xff;
  300. }
  301. tv.tv_usec = 0;
  302. for (i = 0; i < 4; i++) {
  303. tv.tv_usec <<= 8;
  304. tv.tv_usec |= ((long)*rp++) & 0xff;
  305. }
  306. tvd.tv_sec = tv.tv_sec - lasttv.tv_sec;
  307. tvd.tv_usec = tv.tv_usec - lasttv.tv_usec;
  308. if (tvd.tv_usec < 0) {
  309. tvd.tv_usec += 1000000;
  310. tvd.tv_sec--;
  311. }
  312. (void)printf("%lu.%06lu %lu.%06lu %s\n",
  313. tv.tv_sec, tv.tv_usec, tvd.tv_sec, tvd.tv_usec,
  314. cooked);
  315. lasttv = tv;
  316. } else {
  317. rp++;
  318. }
  319. }
  320. if (ind) {
  321. *cp = '\0';
  322. (void)printf("Incomplete data: %s\n", cooked);
  323. }
  324. }
  325. /*
  326. * doalarm - send a string out the port, if we have one.
  327. */
  328. int
  329. doalarm(
  330. int fd
  331. )
  332. {
  333. int n;
  334. if (! HAVE_OPT(COMMAND))
  335. return;
  336. n = write(fd, cmd, cmdlen);
  337. if (n < 0) {
  338. (void) fprintf(stderr, "%s: write(): ", progname);
  339. perror("");
  340. } else if (n < cmdlen) {
  341. (void) printf("Short write (%d bytes, should be %d)\n",
  342. n, cmdlen);
  343. }
  344. }
  345. /*
  346. * alarming - receive alarm interupt
  347. */
  348. void
  349. alarming(void)
  350. {
  351. wasalarmed = 1;
  352. }
  353. /*
  354. * ioready - handle SIGIO interrupt
  355. */
  356. void
  357. ioready(void)
  358. {
  359. iosig = 1;
  360. }