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
9 #include "clktest-opts.h"
11 #define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
13 #if defined(ULT_2_0_SUCKS)
15 #define sigmask(m) (1<<(m))
21 CLOCK_LINE_DISCIPLINE_NEEDED_BY_THIS_PROGRAM
;
25 ONLY_ONE_CLOCK_LINE_DISCIPLINE_FOR_THIS_PROGRAM
;
30 * Mask for blocking SIGIO and SIGALRM
32 #define BLOCKSIGMASK (sigmask(SIGIO)|sigmask(SIGALRM))
34 #define progname clktestOptions.pzProgName
36 struct timeval timeout
= { 0 };
41 u_long magic1
= DEFMAGIC
;
42 u_long magic2
= DEFMAGIC
;
46 int ttflags
= RAW
|EVENP
|ODDP
;
48 volatile int wasalarmed
;
51 struct timeval lasttv
;
53 extern u_long ustotslo
[];
54 extern u_long ustotsmid
[];
55 extern u_long ustotshi
[];
61 * main - parse arguments and handle options
71 struct itimerval itimer
;
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
);
92 strcpy(magic
,DEFMAGIC
);
95 fd
= open(*argv
, HAVE_OPT(TIMEOUT
) ? O_RDWR
: O_RDONLY
, 0777);
97 fprintf(stderr
, "%s: open(%s): ", progname
, *argv
);
102 if (ioctl(fd
, TIOCEXCL
, (char *)0) < 0) {
103 (void) fprintf(stderr
, "%s: ioctl(TIOCEXCL): ", progname
);
109 * If we have the clock discipline, set the port to raw. Otherwise
112 ttyb
.sg_ispeed
= ttyb
.sg_ospeed
= speed
;
114 ttyb
.sg_erase
= (char)magic1
;
115 ttyb
.sg_kill
= (char)magic2
;
117 ttyb
.sg_flags
= (short)ttflags
;
118 if (ioctl(fd
, TIOCSETP
, (char *)&ttyb
) < 0) {
119 (void) fprintf(stderr
, "%s: ioctl(TIOCSETP): ", progname
);
124 if (fcntl(fd
, F_SETOWN
, getpid()) == -1) {
125 (void) fprintf(stderr
, "%s: fcntl(F_SETOWN): ", progname
);
134 if (ioctl(fd
, TIOCSETD
, (char *)&ldisc
) < 0) {
135 (void) fprintf(stderr
, "%s: ioctl(TIOCSETD): ", progname
);
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
);
148 if (ioctl(fd
, CLK_SETSTR
, magic
) < 0) {
149 (void) fprintf(stderr
, "%s: ioctl(CLK_SETSTR): ", progname
);
156 (void) gettimeofday(&lasttv
, (struct timezone
*)0);
157 if (HAVE_OPT(TIMEOUT
)) {
159 * set non-blocking, async I/O on the descriptor
162 (void) signal(SIGIO
, ioready
);
163 if (fcntl(fd
, F_SETFL
, FNDELAY
|FASYNC
) < 0) {
164 (void) fprintf(stderr
, "%s: fcntl(F_SETFL): ",
171 * Set up the alarm interrupt.
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);
185 * doboth - handle both I/O and alarms via SIGIO
197 struct timeval tvzero
;
203 omask
= sigblock(BLOCKSIGMASK
);
204 if (wasalarmed
) { /* alarmed? */
213 if (!sawalarm
&& !sawiosig
) {
215 * Nothing to do. Wait for something.
218 if (wasalarmed
) { /* alarmed? */
227 (void)sigsetmask(omask
);
232 tvzero
.tv_sec
= tvzero
.tv_usec
= 0;
234 n
= select(fd
+1, &fds
, (fd_set
*)0,
235 (fd_set
*)0, &tvzero
);
241 (void) fprintf(stderr
, "%s: select: ",
257 * doioonly - do I/O. This avoids the use of signals
270 n
= select(fd
+1, &fds
, (fd_set
*)0, (fd_set
*)0,
271 (struct timeval
*)0);
279 * doio - read a buffer full of stuff and print it out
286 register char *rp
, *rpend
;
290 struct timeval tv
, tvd
;
294 static char *digits
= "0123456789abcdef";
296 rlen
= read(fd
, raw
, sizeof(raw
));
298 (void) fprintf(stderr
, "%s: read(): ", progname
);
303 (void) printf("Zero length read\n");
318 *cp
++ = digits
[((*rp
)>>4) & 0xf];
319 *cp
++ = digits
[*rp
& 0xf];
324 (*rp
== (char)magic1
|| *rp
== (char)magic2
)
326 ( strchr( magic
, *rp
) != NULL
)
332 if ((rpend
- rp
) < sizeof(struct timeval
)) {
334 "Too little data (%d): %s\n",
340 for (i
= 0; i
< 4; i
++) {
342 tv
.tv_sec
|= ((long)*rp
++) & 0xff;
345 for (i
= 0; i
< 4; i
++) {
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;
357 (void)printf("%lu.%06lu %lu.%06lu %s\n",
358 tv
.tv_sec
, tv
.tv_usec
, tvd
.tv_sec
, tvd
.tv_usec
,
368 (void)printf("Incomplete data: %s\n", cooked
);
374 * doalarm - send a string out the port, if we have one.
383 if (! HAVE_OPT(COMMAND
))
386 n
= write(fd
, cmd
, cmdlen
);
389 (void) fprintf(stderr
, "%s: write(): ", progname
);
391 } else if (n
< cmdlen
) {
392 (void) printf("Short write (%d bytes, should be %d)\n",
399 * alarming - receive alarm interupt
408 * ioready - handle SIGIO interrupt