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