1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 /*	from OpenSolaris "ta.c	1.10	05/06/08 SMI"	*/
32 
33 /*
34  * Portions Copyright (c) 2005 Gunnar Ritter, Freiburg i. Br., Germany
35  */
36 #if __GNUC__ >= 3 && __GNUC_MINOR__ >= 4 || __GNUC__ >= 4
37 #define	USED	__attribute__ ((used))
38 #elif defined __GNUC__
39 #define	USED	__attribute__ ((unused))
40 #else
41 #define	USED
42 #endif
43 static const char sccsid[] USED = "@(#)/usr/ucb/ta.sl	1.8 (gritter) 12/25/06";
44 
45 /*
46  * University Copyright- Copyright (c) 1982, 1986, 1988
47  * The Regents of the University of California
48  * All Rights Reserved
49  *
50  * University Acknowledgment- Portions of this document are derived from
51  * software developed by the University of California, Berkeley, and its
52  * contributors.
53  */
54 
55 /*
56  *	drive hp2621 terminal
57  *	just to see stuff quickly. like troff -a
58  */
59 
60 /*
61 output language from troff:
62 all numbers are character strings
63 
64 sn	size in points
65 fn	font as number from 1-n
66 cx	ascii character x
67 Cxyz	funny char xyz. terminated by white space
68 Hn	go to absolute horizontal position n
69 Vn	go to absolute vertical position n (down is positive)
70 hn	go n units horizontally (relative)
71 vn	ditto vertically
72 nnc	move right nn (exactly 2 digits!), then print c
73 		(this wart is an optimization that shrinks output file size
74 		 about 35% and run-time about 15% while preserving ascii-ness)
75 w	paddable word space - no action needed
76 nb a	end of line (information only -- no action needed)
77 	b = space before line, a = after
78 pn	begin page n
79 #...\n	comment
80 Dt ...\n	draw operation 't':
81 	Dl x y		line from here by x,y
82 	Dc d		circle of diameter d with left side here
83 	De x y		ellipse of axes x,y with left side here
84 	Da x y u v	arc counter-clockwise from here to u,v from center
85 				with center x,y from here
86 	D~ x y x y ...	wiggly line by x,y then x,y ...
87 x ...\n	device control functions:
88 	x i	init
89 	x T s	name of device is s
90 	x r n h v	resolution is n/inch
91 		h = min horizontal motion, v = min vert
92 	x p	pause (can restart)
93 	x s	stop -- done for ever
94 	x t	generate trailer
95 	x f n s	font position n contains font s
96 	x H n	set character height to n
97 	x S n	set character slant to n
98 
99 	Subcommands like "i" are often spelled out like "init".
100 */
101 
102 #include	<stdlib.h>
103 #include	<string.h>
104 #include	<unistd.h>
105 #include	<sys/wait.h>
106 #include	<stdio.h>
107 #include	<signal.h>
108 #include	<ctype.h>
109 #include	<stdarg.h>
110 
111 #include "dev.h"
112 #define	NFONT	10
113 
114 int	output	= 0;	/* do we do output at all? */
115 int	nolist	= 0;	/* output page list if > 0 */
116 int	olist[20];	/* pairs of page numbers */
117 
118 int	erase	= 1;
119 float	aspect	= 1.5;	/* default aspect ratio */
120 int	wflag	= 0;	/* wait, looping, for new input if on */
121 void	(*sigint)(int);
122 void	(*sigquit)(int);
123 void	done(void);
124 
125 struct dev dev;
126 struct font *fontbase[NFONT];
127 short	psizes[]	={ 11, 16, 22, 36, 0};	/* approx sizes available */
128 short	*pstab		= psizes;
129 int	nsizes	= 1;
130 int	nfonts;
131 int	smnt;	/* index of first special font */
132 int	nchtab;
133 char	*chname;
134 short	*chtab;
135 char	*fitab[NFONT];
136 char	*widthtab[NFONT];	/* widtab would be a better name */
137 char	*codetab[NFONT];	/* device codes */
138 
139 #define	FATAL	1
140 #define	BMASK	0377
141 int	dbg	= 0;
142 int	res	= 972;		/* input assumed computed according to this resolution */
143 				/* initial value to avoid 0 divide */
144 FILE	*tf;			/* output file */
145 char	*fontdir	= FNTDIR;
146 #define	devname	troff_devname
147 char	devname[20]	= "hp2621";
148 
149 FILE *fp;		/* input file pointer */
150 
151 int	nowait = 0;	/* 0 => wait at bottom of each page */
152 
153 
154 void drawline(int, int, char *);
155 void drawwig(char *);
156 void drawcirc(int);
157 void drawarc(int, int, int, int);
158 void drawellip(int, int);
159 
160 void outlist(char *);
161 int in_olist(int);
162 void conv(register FILE *);
163 void devcntrl(FILE *);
164 void fileinit(void);
165 void fontprint(int);
166 void loadcode(int, int);
167 void loadfont(int, char *);
168 void error(int, const char *, ...);
169 void t_init(int);
170 void t_push(void);
171 void t_pop(void);
172 void t_page(int);
173 void putpage(void);
174 void t_newline(void);
175 int t_size(int);
176 int t_font(char *);
177 void t_text(char *);
178 void t_reset(int);
179 void t_trailer(void);
180 void hgoto(int);
181 void hmot(int);
182 void hflush(void);
183 void vgoto(int);
184 void vmot(int);
185 void put1s(char *);
186 void put1(int);
187 void setsize(double);
188 void t_fp(int, char *);
189 void setfont(int);
190 void done(void);
191 void callunix(char []);
192 int readch(void);
193 
194 static int sget(char *, size_t, FILE *);
195 
196 int
main(int argc,char ** argv)197 main(int argc, char **argv)
198 {
199 	char buf[BUFSIZ];
200 
201 	fp = stdin;
202 	tf = stdout;
203 	setbuf(stdout, buf);
204 	while (argc > 1 && argv[1][0] == '-') {
205 		switch (argv[1][1]) {
206 		case 'a':
207 			aspect = atof(&argv[1][2]);
208 			break;
209 		case 'e':
210 			erase = 0;
211 			break;
212 		case 'o':
213 			outlist(&argv[1][2]);
214 			break;
215 		case 'd':
216 			dbg = atoi(&argv[1][2]);
217 			if (dbg == 0) dbg = 1;
218 			break;
219 		case 'w':	/* no wait at bottom of page */
220 			nowait = 1;
221 			break;
222 		}
223 		argc--;
224 		argv++;
225 	}
226 
227 	if (argc <= 1)
228 		conv(stdin);
229 	else
230 		while (--argc > 0) {
231 			if (strcmp(*++argv, "-") == 0)
232 				fp = stdin;
233 			else if ((fp = fopen(*argv, "r")) == NULL)
234 				error(FATAL, "can't open %s", *argv);
235 			conv(fp);
236 			fclose(fp);
237 		}
238 	done();
239 	/*NOTREACHED*/
240 	return 0;
241 }
242 
243 void
outlist(char * s)244 outlist(char *s)	/* process list of page numbers to be printed */
245 {
246 	int n1, n2, i;
247 
248 	nolist = 0;
249 	while (*s && nolist < sizeof olist/sizeof *olist - 1) {
250 		n1 = 0;
251 		if (isdigit((unsigned char)*s))
252 			do
253 				n1 = 10 * n1 + *s++ - '0';
254 			while (isdigit((unsigned char)*s));
255 		else
256 			n1 = -9999;
257 		n2 = n1;
258 		if (*s == '-') {
259 			s++;
260 			n2 = 0;
261 			if (isdigit((unsigned char)*s))
262 				do
263 					n2 = 10 * n2 + *s++ - '0';
264 				while (isdigit((unsigned char)*s));
265 			else
266 				n2 = 9999;
267 		}
268 		olist[nolist++] = n1;
269 		olist[nolist++] = n2;
270 		if (*s != '\0')
271 			s++;
272 	}
273 	olist[nolist] = 0;
274 	if (dbg)
275 		for (i=0; i<nolist; i += 2)
276 			printf("%3d %3d\n", olist[i], olist[i+1]);
277 }
278 
279 int
in_olist(int n)280 in_olist(int n)	/* is n in olist? */
281 {
282 	int i;
283 
284 	if (nolist == 0)
285 		return(1);	/* everything is included */
286 	for (i = 0; i < nolist; i += 2)
287 		if (n >= olist[i] && n <= olist[i+1])
288 			return(1);
289 	return(0);
290 }
291 
292 void
conv(register FILE * fp)293 conv(register FILE *fp)
294 {
295 	register int c, k;
296 	int m, n, n1, m1;
297 	char str[4096], buf[4096];
298 
299 	while ((c = getc(fp)) != EOF) {
300 		switch (c) {
301 		case '\n':	/* when input is text */
302 		case ' ':
303 		case 0:		/* occasional noise creeps in */
304 			break;
305 		case '{':	/* push down current environment */
306 			t_push();
307 			break;
308 		case '}':
309 			t_pop();
310 			break;
311 		case '0': case '1': case '2': case '3': case '4':
312 		case '5': case '6': case '7': case '8': case '9':
313 			/* two motion digits plus a character */
314 			hmot((c-'0')*10 + getc(fp)-'0');
315 			put1(getc(fp));
316 			break;
317 		case 'c':	/* single ascii character */
318 			put1(getc(fp));
319 			break;
320 		case 'C':
321 			sget(str, sizeof str, fp);
322 			put1s(str);
323 			break;
324 		case 't':	/* straight text */
325 			fgets(buf, sizeof(buf), fp);
326 			t_text(buf);
327 			break;
328 		case 'D':	/* draw function */
329 			fgets(buf, sizeof(buf), fp);
330 			switch (buf[0]) {
331 			case 'l':	/* draw a line */
332 				sscanf(buf+1, "%d %d", &n, &m);
333 				drawline(n, m, ".");
334 				break;
335 			case 'c':	/* circle */
336 				sscanf(buf+1, "%d", &n);
337 				drawcirc(n);
338 				break;
339 			case 'e':	/* ellipse */
340 				sscanf(buf+1, "%d %d", &m, &n);
341 				drawellip(m, n);
342 				break;
343 			case 'a':	/* arc */
344 				sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
345 				drawarc(n, m, n1, m1);
346 				break;
347 			case '~':	/* wiggly line */
348 				drawwig(buf+1);
349 				break;
350 			default:
351 				error(FATAL, "unknown drawing function %s\n", buf);
352 				break;
353 			}
354 			break;
355 		case 's':
356 			fscanf(fp, "%d", &n);
357 			if (n == -23) {
358 				float	f;
359 				fscanf(fp, "%f", &f);
360 				setsize(f);
361 			} else
362 				setsize(t_size(n));/* ignore fractional sizes */
363 			break;
364 		case 'f':
365 			sget(str, sizeof str, fp);
366 			setfont(t_font(str));
367 			break;
368 		case 'H':	/* absolute horizontal motion */
369 			/* fscanf(fp, "%d", &n); */
370 			while ((c = getc(fp)) == ' ')
371 				;
372 			k = 0;
373 			do {
374 				k = 10 * k + c - '0';
375 			} while (isdigit(c = getc(fp)));
376 			ungetc(c, fp);
377 			hgoto(k);
378 			break;
379 		case 'h':	/* relative horizontal motion */
380 			/* fscanf(fp, "%d", &n); */
381 			while ((c = getc(fp)) == ' ')
382 				;
383 			k = 0;
384 			do {
385 				k = 10 * k + c - '0';
386 			} while (isdigit(c = getc(fp)));
387 			ungetc(c, fp);
388 			hmot(k);
389 			break;
390 		case 'w':	/* word space */
391 			putc(' ', stdout);
392 			break;
393 		case 'V':
394 			fscanf(fp, "%d", &n);
395 			vgoto(n);
396 			break;
397 		case 'v':
398 			fscanf(fp, "%d", &n);
399 			vmot(n);
400 			break;
401 		case 'p':	/* new page */
402 			fscanf(fp, "%d", &n);
403 			t_page(n);
404 			break;
405 		case 'n':	/* end of line */
406 			while (getc(fp) != '\n')
407 				;
408 			t_newline();
409 			break;
410 		case '#':	/* comment */
411 			while (getc(fp) != '\n')
412 				;
413 			break;
414 		case 'x':	/* device control */
415 			devcntrl(fp);
416 			break;
417 		default:
418 			error(!FATAL, "unknown input character %o %c\n", c, c);
419 			done();
420 		}
421 	}
422 }
423 
424 void
devcntrl(FILE * fp)425 devcntrl(FILE *fp)	/* interpret device control functions */
426 {
427 	char str[4096];
428 	int n;
429 
430 	sget(str, sizeof str, fp);
431 	switch (str[0]) {	/* crude for now */
432 	case 'i':	/* initialize */
433 		fileinit();
434 		t_init(0);
435 		break;
436 	case 'T':	/* device name */
437 		sget(devname, sizeof devname, fp);
438 		break;
439 	case 't':	/* trailer */
440 		t_trailer();
441 		break;
442 	case 'p':	/* pause -- can restart */
443 		t_reset('p');
444 		break;
445 	case 's':	/* stop */
446 		t_reset('s');
447 		break;
448 	case 'r':	/* resolution assumed when prepared */
449 		fscanf(fp, "%d", &res);
450 		break;
451 	case 'f':	/* font used */
452 		fscanf(fp, "%d", &n);
453 		sget(str, sizeof str, fp);
454 		loadfont(n, str);
455 		break;
456 	}
457 	while (getc(fp) != '\n')	/* skip rest of input line */
458 		;
459 }
460 
461 void
fileinit(void)462 fileinit(void)	/* read in font and code files, etc. */
463 {
464 }
465 
466 void
fontprint(int i)467 fontprint(int i)	/* debugging print of font i (0,...) */
468 {
469 }
470 
471 void
loadcode(int n,int nw)472 loadcode(int n, int nw)	/* load codetab on position n (0...); #chars is nw */
473 {
474 }
475 
476 void
loadfont(int n,char * s)477 loadfont(int n, char *s)	/* load font info for font s on position n (1...) */
478 {
479 }
480 
481 void
error(int f,const char * s,...)482 error(int f, const char *s, ...)
483 {
484 	va_list ap;
485 
486 	fprintf(stderr, "ta: ");
487 	va_start(ap, s);
488 	vfprintf(stderr, s, ap);
489 	va_end(ap);
490 	fprintf(stderr, "\n");
491 	if (f)
492 		exit(1);
493 }
494 
495 
496 /*
497 	Here beginneth all the stuff that really depends
498 	on the 202 (we hope).
499 */
500 
501 
502 #define	ESC	033
503 #define	HOME	'H'
504 #define	CLEAR	'J'
505 #define	FF	014
506 
507 int	size	= 1;
508 int	font	= 1;		/* current font */
509 int	hpos;		/* horizontal position where we are supposed to be next (left = 0) */
510 int	vpos;		/* current vertical position (down positive) */
511 
512 int	horig;		/* h origin of current block; hpos rel to this */
513 int	vorig;		/* v origin of current block; vpos rel to this */
514 
515 int	DX	= 10;	/* step size in x for drawing */
516 int	DY	= 10;	/* step size in y for drawing */
517 int	drawdot	= '.';	/* draw with this character */
518 int	drawsize = 1;	/* shrink by this factor when drawing */
519 
520 void
t_init(int reinit)521 t_init(int reinit)	/* initialize device */
522 {
523 	fflush(stdout);
524 	hpos = vpos = 0;
525 }
526 
527 #define	MAXSTATE	5
528 
529 struct state {
530 	int	ssize;
531 	int	sfont;
532 	int	shpos;
533 	int	svpos;
534 	int	shorig;
535 	int	svorig;
536 };
537 struct	state	state[MAXSTATE];
538 struct	state	*statep = state;
539 
540 void
t_push(void)541 t_push(void)	/* begin a new block */
542 {
543 	hflush();
544 	statep->ssize = size;
545 	statep->sfont = font;
546 	statep->shorig = horig;
547 	statep->svorig = vorig;
548 	statep->shpos = hpos;
549 	statep->svpos = vpos;
550 	horig = hpos;
551 	vorig = vpos;
552 	hpos = vpos = 0;
553 	if (statep++ >= state+MAXSTATE)
554 		error(FATAL, "{ nested too deep");
555 	hpos = vpos = 0;
556 }
557 
558 void
t_pop(void)559 t_pop(void)	/* pop to previous state */
560 {
561 	if (--statep < state)
562 		error(FATAL, "extra }");
563 	size = statep->ssize;
564 	font = statep->sfont;
565 	hpos = statep->shpos;
566 	vpos = statep->svpos;
567 	horig = statep->shorig;
568 	vorig = statep->svorig;
569 }
570 
571 int	np;	/* number of pages seen */
572 int	npmax;	/* high-water mark of np */
573 int	pgnum[40];	/* their actual numbers */
574 long	pgadr[40];	/* their seek addresses */
575 
576 void
t_page(int n)577 t_page(int n)	/* do whatever new page functions */
578 {
579 	int m, i;
580 	char buf[1024], *bp;
581 
582 	pgnum[np++] = n;
583 	pgadr[np] = ftell(fp);
584 	if (np > npmax)
585 		npmax = np;
586 	if (output == 0) {
587 		output = in_olist(n);
588 		t_init(1);
589 		return;
590 	}
591 	/* have just printed something, and seen p<n> for next one */
592 	putpage();
593 	fflush(stdout);
594 	if (nowait)
595 		return;
596 
597   next:
598 	for (bp = buf; (*bp = readch()); )
599 		if (*bp++ == '\n' || bp >= &buf[sizeof buf - 1])
600 			break;
601 	*bp = 0;
602 	switch (buf[0]) {
603 	case 0:
604 		done();
605 		break;
606 	case '\n':
607 		output = in_olist(n);
608 		t_init(1);
609 		return;
610 	case '!':
611 		callunix(&buf[1]);
612 		fputs("!\n", stderr);
613 		break;
614 	case 'e':
615 		erase = 1 - erase;
616 		break;
617 	case 'w':
618 		wflag = 1 - wflag;
619 		break;
620 	case 'a':
621 		aspect = atof(&buf[1]);
622 		break;
623 	case '-':
624 	case 'p':
625 		m = atoi(&buf[1]) + 1;
626 		if (fp == stdin) {
627 			fputs("you can't; it's not a file\n", stderr);
628 			break;
629 		}
630 		if (np - m <= 0) {
631 			fputs("too far back\n", stderr);
632 			break;
633 		}
634 		np -= m;
635 		fseek(fp, pgadr[np], 0);
636 		output = 1;
637 		t_init(1);
638 		return;
639 	case '0': case '1': case '2': case '3': case '4':
640 	case '5': case '6': case '7': case '8': case '9':
641 		m = atoi(&buf[0]);
642 		for (i = 0; i < npmax; i++)
643 			if (m == pgnum[i])
644 				break;
645 		if (i >= npmax || fp == stdin) {
646 			fputs("you can't\n", stderr);
647 			break;
648 		}
649 		np = i + 1;
650 		fseek(fp, pgadr[np], 0);
651 		output = 1;
652 		t_init(1);
653 		return;
654 	case 'o':
655 		outlist(&buf[1]);
656 		output = 0;
657 		t_init(1);
658 		return;
659 	case '?':
660 		fputs("!cmd	unix cmd\n", stderr);
661 		fputs("p	print this page again\n", stderr);
662 		fputs("-n	go back n pages\n", stderr);
663 		fputs("n	print page n (previously printed)\n", stderr);
664 		fputs("o...	set the -o output list to ...\n", stderr);
665 		fputs("en	n=0 -> don't erase; n=1 -> erase\n", stderr);
666 		fputs("an	sets aspect ratio to n\n", stderr);
667 		break;
668 	default:
669 		fputs("?\n", stderr);
670 		break;
671 	}
672 	goto next;
673 }
674 
675 void
putpage(void)676 putpage(void)
677 {
678 	fflush(stdout);
679 }
680 
681 void
t_newline(void)682 t_newline(void)	/* do whatever for the end of a line */
683 {
684 	printf("\n");
685 	hpos = 0;
686 }
687 
688 int
t_size(int n)689 t_size(int n)	/* convert integer to internal size number*/
690 {
691 	return 0;
692 }
693 
694 int
t_font(char * s)695 t_font(char *s)	/* convert string to internal font number */
696 {
697 	return 0;
698 }
699 
700 void
t_text(char * s)701 t_text(char *s)	/* print string s as text */
702 {
703 	int c, w=0;
704 	char str[100];
705 
706 	if (!output)
707 		return;
708 	while ((c = *s++) != '\n') {
709 		if (c == '\\') {
710 			switch (c = *s++) {
711 			case '\\':
712 			case 'e':
713 				put1('\\');
714 				break;
715 			case '(':
716 				str[0] = *s++;
717 				str[1] = *s++;
718 				str[2] = '\0';
719 				put1s(str);
720 				break;
721 			}
722 		} else {
723 			put1(c);
724 		}
725 		hmot(w);
726 	}
727 }
728 
729 void
t_reset(int c)730 t_reset(int c)
731 {
732 	output = 1;
733 	fflush(stdout);
734 	if (c == 's')
735 		t_page(9999);
736 }
737 
738 void
t_trailer(void)739 t_trailer(void)
740 {
741 }
742 
743 void
hgoto(int n)744 hgoto(int n)
745 {
746 	hpos = n;	/* this is where we want to be */
747 			/* before printing a character, */
748 			/* have to make sure it's true */
749 }
750 
751 void
hmot(int n)752 hmot(int n)	/* generate n units of horizontal motion */
753 {
754 	hgoto(hpos + n);
755 }
756 
757 void
hflush(void)758 hflush(void)	/* actual horizontal output occurs here */
759 {
760 }
761 
762 void
vgoto(int n)763 vgoto(int n)
764 {
765 	vpos = n;
766 }
767 
768 void
vmot(int n)769 vmot(int n)	/* generate n units of vertical motion */
770 {
771 	vgoto(vpos + n);	/* ignores rounding */
772 }
773 
774 void
put1s(char * s)775 put1s(char *s)	/* s is a funny char name */
776 {
777 	int i;
778 	char *p;
779 	extern char *spectab[];
780 	static char prev[10] = "";
781 	static int previ;
782 
783 	if (!output)
784 		return;
785 	if (strcmp(s, prev) != 0) {
786 		previ = -1;
787 		for (i = 0; spectab[i] != 0; i += 2)
788 			if (strcmp(spectab[i], s) == 0) {
789 				n_strcpy(prev, s, sizeof(prev));
790 				previ = i;
791 				break;
792 			}
793 	}
794 	if (previ >= 0) {
795 		for (p = spectab[previ+1]; *p; p++)
796 			putc(*p, stdout);
797 	} else
798 		prev[0] = 0;
799 }
800 
801 void
put1(int c)802 put1(int c)	/* output char c */
803 {
804 	if (!output)
805 		return;
806 	putc(c, stdout);
807 }
808 
809 void
setsize(double n)810 setsize(double n)	/* set point size to n (internal) */
811 {
812 }
813 
814 void
t_fp(int n,char * s)815 t_fp(int n, char *s)	/* font position n now contains font s */
816 {
817 }
818 
819 void
setfont(int n)820 setfont(int n)	/* set font to n */
821 {
822 }
823 
done(void)824 void done(void)
825 {
826 	output = 1;
827 	putpage();
828 	fflush(stdout);
829 	exit(0);
830 }
831 
832 void
callunix(char line[])833 callunix(char line[])
834 {
835 	int rc, status, unixpid;
836 	if( (unixpid=fork())==0 ) {
837 		signal(SIGINT,sigint); signal(SIGQUIT,sigquit);
838 		close(0); dup(2);
839 		execl("/bin/sh", "-sh", "-c", line, NULL);
840 		exit(255);
841 	}
842 	else if(unixpid == -1)
843 		return;
844 	else{	signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN);
845 		while( (rc = wait(&status)) != unixpid && rc != -1 ) ;
846 		signal(SIGINT,(void(*)(int))done); signal(SIGQUIT,(void(*)(int))sigquit);
847 	}
848 }
849 
850 int
readch(void)851 readch(void){
852 	char c;
853 	if (read(2,&c,1)<1) c=0;
854 	return(c);
855 }
856 
857 char *spectab[] ={
858 	"em", "-",
859 	"hy", "-",
860 	"en", "-",
861 	"ru", "_",
862 	"l.", ".",
863 	"br", "|",
864 	"vr", "|",
865 	"fm", "'",
866 	"or", "|",
867 	0, 0,
868 };
869 
870 static int
sget(char * buf,size_t size,FILE * fp)871 sget(char *buf, size_t size, FILE *fp)
872 {
873 	int	c, n = 0;
874 
875 	do
876 		c = getc(fp);
877 	while (isspace(c));
878 	if (c != EOF) do {
879 		if (n+1 < size)
880 			buf[n++] = c;
881 		c = getc(fp);
882 	} while (c != EOF && !isspace(c));
883 	ungetc(c, fp);
884 	buf[n] = 0;
885 	return n > 1 ? 1 : c == EOF ? EOF : 0;
886 }
887