Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / ntp / clockstuff / clktest.c
blob82f0daf0f4964d2fc64c71f1df91a5071f613123
1 /* $NetBSD: clktest.c,v 1.2 2003/12/04 16:23:34 drochner Exp $ */
3 /* clktest.c,v 3.1 1993/07/06 01:05:23 jbj Exp
4 * clktest - test the clock line discipline
6 * usage: clktest -b bps -f -t timeo -s cmd -c char1 -a char2 /dev/whatever
7 */
9 #include "clktest-opts.h"
11 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
13 #if defined(ULT_2_0_SUCKS)
14 #ifndef sigmask
15 #define sigmask(m) (1<<(m))
16 #endif
17 #endif
19 #ifndef STREAM
20 # ifndef CLKLDISC
21 CLOCK_LINE_DISCIPLINE_NEEDED_BY_THIS_PROGRAM;
22 # endif
23 #else
24 # ifdef CLKLDISC
25 ONLY_ONE_CLOCK_LINE_DISCIPLINE_FOR_THIS_PROGRAM;
26 # endif
27 #endif
30 * Mask for blocking SIGIO and SIGALRM
32 #define BLOCKSIGMASK (sigmask(SIGIO)|sigmask(SIGALRM))
34 #define progname clktestOptions.pzProgName
36 struct timeval timeout = { 0 };
37 char *cmd = NULL;
38 int cmdlen;
40 #ifdef CLKLDISC
41 u_long magic1 = DEFMAGIC;
42 u_long magic2 = DEFMAGIC;
43 #endif
45 int speed = B9600;
46 int ttflags = RAW|EVENP|ODDP;
48 volatile int wasalarmed;
49 volatile int iosig;
51 struct timeval lasttv;
53 extern u_long ustotslo[];
54 extern u_long ustotsmid[];
55 extern u_long ustotshi[];
57 int alarming();
58 int ioready();
61 * main - parse arguments and handle options
63 int
64 main(
65 int argc,
66 char *argv[]
69 int fd;
70 struct sgttyb ttyb;
71 struct itimerval itimer;
73 #ifdef STREAM
74 magic[0] = 0;
75 #endif
78 int ct = optionProcess( &clktestOptions, argc, argv );
79 if (HAVE_OPT(COMMAND) && (strlen(OPT_ARG(COMMAND)) == 0)) {
80 fputs( "The command option string must not be empty\n", stderr );
81 USAGE( EXIT_FAILURE );
84 if ((argc -= ct) != 1) {
85 fputs( "Missing tty device name\n", stderr );
86 USAGE( EXIT_FAILURE );
88 argv += ct;
90 #ifdef STREAM
91 if (!strlen(magic))
92 strcpy(magic,DEFMAGIC);
93 #endif
95 fd = open(*argv, HAVE_OPT(TIMEOUT) ? O_RDWR : O_RDONLY, 0777);
96 if (fd == -1) {
97 fprintf(stderr, "%s: open(%s): ", progname, *argv);
98 perror("");
99 exit(1);
102 if (ioctl(fd, TIOCEXCL, (char *)0) < 0) {
103 (void) fprintf(stderr, "%s: ioctl(TIOCEXCL): ", progname);
104 perror("");
105 exit(1);
109 * If we have the clock discipline, set the port to raw. Otherwise
110 * we run cooked.
112 ttyb.sg_ispeed = ttyb.sg_ospeed = speed;
113 #ifdef CLKLDISC
114 ttyb.sg_erase = (char)magic1;
115 ttyb.sg_kill = (char)magic2;
116 #endif
117 ttyb.sg_flags = (short)ttflags;
118 if (ioctl(fd, TIOCSETP, (char *)&ttyb) < 0) {
119 (void) fprintf(stderr, "%s: ioctl(TIOCSETP): ", progname);
120 perror("");
121 exit(1);
124 if (fcntl(fd, F_SETOWN, getpid()) == -1) {
125 (void) fprintf(stderr, "%s: fcntl(F_SETOWN): ", progname);
126 perror("");
127 exit(1);
130 #ifdef CLKLDISC
132 int ldisc;
133 ldisc = CLKLDISC;
134 if (ioctl(fd, TIOCSETD, (char *)&ldisc) < 0) {
135 (void) fprintf(stderr, "%s: ioctl(TIOCSETD): ", progname);
136 perror("");
137 exit(1);
140 #endif
141 #ifdef STREAM
142 if (ioctl(fd, I_POP, 0) >=0 ) ;
143 if (ioctl(fd, I_PUSH, "clk") < 0) {
144 (void) fprintf(stderr, "%s: ioctl(I_PUSH): ", progname);
145 perror("");
146 exit(1);
148 if (ioctl(fd, CLK_SETSTR, magic) < 0) {
149 (void) fprintf(stderr, "%s: ioctl(CLK_SETSTR): ", progname);
150 perror("");
151 exit(1);
153 #endif
156 (void) gettimeofday(&lasttv, (struct timezone *)0);
157 if (HAVE_OPT(TIMEOUT)) {
159 * set non-blocking, async I/O on the descriptor
161 iosig = 0;
162 (void) signal(SIGIO, ioready);
163 if (fcntl(fd, F_SETFL, FNDELAY|FASYNC) < 0) {
164 (void) fprintf(stderr, "%s: fcntl(F_SETFL): ",
165 progname);
166 perror("");
167 exit(1);
171 * Set up the alarm interrupt.
173 wasalarmed = 0;
174 (void) signal(SIGALRM, alarming);
175 timeout.tv_sec = OPT_VALUE_TIMEOUT;
176 itimer.it_interval = itimer.it_value = timeout;
177 setitimer(ITIMER_REAL, &itimer, (struct itimerval *)0);
178 doboth(fd);
180 doioonly(fd);
185 * doboth - handle both I/O and alarms via SIGIO
188 doboth(
189 int fd
192 int n;
193 int sawalarm;
194 int sawiosig;
195 int omask;
196 fd_set fds;
197 struct timeval tvzero;
199 sawalarm = 0;
200 sawiosig = 0;
201 FD_ZERO(&fds);
202 for (;;) {
203 omask = sigblock(BLOCKSIGMASK);
204 if (wasalarmed) { /* alarmed? */
205 sawalarm = 1;
206 wasalarmed = 0;
208 if (iosig) {
209 sawiosig = 1;
210 iosig = 0;
213 if (!sawalarm && !sawiosig) {
215 * Nothing to do. Wait for something.
217 sigpause(omask);
218 if (wasalarmed) { /* alarmed? */
219 sawalarm = 1;
220 wasalarmed = 0;
222 if (iosig) {
223 sawiosig = 1;
224 iosig = 0;
227 (void)sigsetmask(omask);
229 if (sawiosig) {
231 do {
232 tvzero.tv_sec = tvzero.tv_usec = 0;
233 FD_SET(fd, &fds);
234 n = select(fd+1, &fds, (fd_set *)0,
235 (fd_set *)0, &tvzero);
236 if (n > 0)
237 doio(fd);
238 } while (n > 0);
240 if (n == -1) {
241 (void) fprintf(stderr, "%s: select: ",
242 progname);
243 perror("");
244 exit(1);
246 sawiosig = 0;
248 if (sawalarm) {
249 doalarm(fd);
250 sawalarm = 0;
257 * doioonly - do I/O. This avoids the use of signals
260 doioonly(
261 int fd
264 int n;
265 fd_set fds;
267 FD_ZERO(&fds);
268 for (;;) {
269 FD_SET(fd, &fds);
270 n = select(fd+1, &fds, (fd_set *)0, (fd_set *)0,
271 (struct timeval *)0);
272 if (n > 0)
273 doio(fd);
279 * doio - read a buffer full of stuff and print it out
282 doio(
283 int fd
286 register char *rp, *rpend;
287 register char *cp;
288 register int i;
289 char raw[512];
290 struct timeval tv, tvd;
291 int rlen;
292 int ind;
293 char cooked[2049];
294 static char *digits = "0123456789abcdef";
296 rlen = read(fd, raw, sizeof(raw));
297 if (rlen < 0) {
298 (void) fprintf(stderr, "%s: read(): ", progname);
299 perror("");
300 return;
302 if (rlen == 0) {
303 (void) printf("Zero length read\n");
304 return;
307 cp = cooked;
308 rp = raw;
309 rpend = &raw[rlen];
310 ind = 0;
312 while (rp < rpend) {
313 ind = 1;
314 if (isprint(*rp))
315 *cp++ = *rp;
316 else {
317 *cp++ = '<';
318 *cp++ = digits[((*rp)>>4) & 0xf];
319 *cp++ = digits[*rp & 0xf];
320 *cp++ = '>';
322 if (
323 #ifdef CLKLDISC
324 (*rp == (char)magic1 || *rp == (char)magic2)
325 #else
326 ( strchr( magic, *rp) != NULL )
327 #endif
329 rp++;
330 ind = 0;
331 *cp = '\0';
332 if ((rpend - rp) < sizeof(struct timeval)) {
333 (void)printf(
334 "Too little data (%d): %s\n",
335 rpend-rp, cooked);
336 return;
339 tv.tv_sec = 0;
340 for (i = 0; i < 4; i++) {
341 tv.tv_sec <<= 8;
342 tv.tv_sec |= ((long)*rp++) & 0xff;
344 tv.tv_usec = 0;
345 for (i = 0; i < 4; i++) {
346 tv.tv_usec <<= 8;
347 tv.tv_usec |= ((long)*rp++) & 0xff;
350 tvd.tv_sec = tv.tv_sec - lasttv.tv_sec;
351 tvd.tv_usec = tv.tv_usec - lasttv.tv_usec;
352 if (tvd.tv_usec < 0) {
353 tvd.tv_usec += 1000000;
354 tvd.tv_sec--;
357 (void)printf("%lu.%06lu %lu.%06lu %s\n",
358 tv.tv_sec, tv.tv_usec, tvd.tv_sec, tvd.tv_usec,
359 cooked);
360 lasttv = tv;
361 } else {
362 rp++;
366 if (ind) {
367 *cp = '\0';
368 (void)printf("Incomplete data: %s\n", cooked);
374 * doalarm - send a string out the port, if we have one.
377 doalarm(
378 int fd
381 int n;
383 if (! HAVE_OPT(COMMAND))
384 return;
386 n = write(fd, cmd, cmdlen);
388 if (n < 0) {
389 (void) fprintf(stderr, "%s: write(): ", progname);
390 perror("");
391 } else if (n < cmdlen) {
392 (void) printf("Short write (%d bytes, should be %d)\n",
393 n, cmdlen);
399 * alarming - receive alarm interupt
401 void
402 alarming(void)
404 wasalarmed = 1;
408 * ioready - handle SIGIO interrupt
410 void
411 ioready(void)
413 iosig = 1;