PageRenderTime 25ms CodeModel.GetById 7ms app.highlight 14ms RepoModel.GetById 1ms app.codeStats 0ms

/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
  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
 34struct timeval timeout = { 0 };
 35char *cmd = NULL;
 36int cmdlen;
 37
 38#ifdef CLKLDISC
 39u_long magic1 = DEFMAGIC;
 40u_long magic2 = DEFMAGIC;
 41#endif
 42
 43int speed = B9600;
 44int ttflags = RAW|EVENP|ODDP;
 45
 46volatile int wasalarmed;
 47volatile int iosig;
 48
 49struct timeval lasttv;
 50
 51extern u_long ustotslo[];
 52extern u_long ustotsmid[];
 53extern u_long ustotshi[];
 54
 55int alarming();
 56int ioready();
 57
 58/*
 59 * main - parse arguments and handle options
 60 */
 61int
 62main(
 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 */
185int
186doboth(
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 */
257int
258doioonly(
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 */
279int
280doio(
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 */
374int
375doalarm(
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 */
399void
400alarming(void)
401{
402	wasalarmed = 1;
403}
404
405/*
406 * ioready - handle SIGIO interrupt
407 */
408void
409ioready(void)
410{
411	iosig = 1;
412}