xref: /plan9/sys/src/cmd/postscript/postio/ifdef.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
1*7dd7cddfSDavid du Colombier /*
2*7dd7cddfSDavid du Colombier  *
3*7dd7cddfSDavid du Colombier  * Conditionally compiled routines for setting up and reading the line. Things
4*7dd7cddfSDavid du Colombier  * were getting out of hand with all the ifdefs, and even though this defeats
5*7dd7cddfSDavid du Colombier  * part of the purpose of conditional complilation directives, I think it's easier
6*7dd7cddfSDavid du Colombier  * to follow this way. Thanks to Alan Buckwalter for the System V DKHOST code.
7*7dd7cddfSDavid du Colombier  *
8*7dd7cddfSDavid du Colombier  * postio now can be run as separate read and write processes, but requires that
9*7dd7cddfSDavid du Colombier  * you write a procedure called resetline() and perhaps modify readline() some.
10*7dd7cddfSDavid du Colombier  * I've already tested the code on System V and it seems to work. Ninth Edition
11*7dd7cddfSDavid du Colombier  * and BSD code may be missing.
12*7dd7cddfSDavid du Colombier  *
13*7dd7cddfSDavid du Colombier  * By request I've changed the way some of the setupline() procedures (eg. in the
14*7dd7cddfSDavid du Colombier  * System V implementation) handle things when no line has been given. If line is
15*7dd7cddfSDavid du Colombier  * NULL the new setupline() procedures try to continue, assuming whoever called
16*7dd7cddfSDavid du Colombier  * postio connected stdout to the printer. Things will only work if we can read
17*7dd7cddfSDavid du Colombier  * and write stdout!
18*7dd7cddfSDavid du Colombier  *
19*7dd7cddfSDavid du Colombier  */
20*7dd7cddfSDavid du Colombier 
21*7dd7cddfSDavid du Colombier #include <stdio.h>
22*7dd7cddfSDavid du Colombier #include <ctype.h>
23*7dd7cddfSDavid du Colombier #include <fcntl.h>
24*7dd7cddfSDavid du Colombier #include <signal.h>
25*7dd7cddfSDavid du Colombier #include <sys/types.h>
26*7dd7cddfSDavid du Colombier #include <errno.h>
27*7dd7cddfSDavid du Colombier 
28*7dd7cddfSDavid du Colombier #include "ifdef.h"			/* conditional header file inclusion */
29*7dd7cddfSDavid du Colombier #include "gen.h"			/* general purpose definitions */
30*7dd7cddfSDavid du Colombier 
31*7dd7cddfSDavid du Colombier FILE	*fp_ttyi, *fp_ttyo;
32*7dd7cddfSDavid du Colombier char	*ptr = mesg;
33*7dd7cddfSDavid du Colombier 
34*7dd7cddfSDavid du Colombier extern int	window_size;
35*7dd7cddfSDavid du Colombier 
36*7dd7cddfSDavid du Colombier /*****************************************************************************/
37*7dd7cddfSDavid du Colombier 
38*7dd7cddfSDavid du Colombier #ifdef SYSV
setupline()39*7dd7cddfSDavid du Colombier setupline()
40*7dd7cddfSDavid du Colombier 
41*7dd7cddfSDavid du Colombier {
42*7dd7cddfSDavid du Colombier 
43*7dd7cddfSDavid du Colombier     struct termio	termio;
44*7dd7cddfSDavid du Colombier 
45*7dd7cddfSDavid du Colombier /*
46*7dd7cddfSDavid du Colombier  *
47*7dd7cddfSDavid du Colombier  * Line initialization for SYSV. For now if no line is given (ie. line == NULL )
48*7dd7cddfSDavid du Colombier  * we continue on as before using stdout as ttyi and ttyo. Doesn't work when we're
49*7dd7cddfSDavid du Colombier  * running in interactive mode or forcing stuff that comes back from the printer
50*7dd7cddfSDavid du Colombier  * to stdout. Both cases are now caught by a test that's been added to routine
51*7dd7cddfSDavid du Colombier  * initialize(). The change is primarily for the version of lp that's available
52*7dd7cddfSDavid du Colombier  * with SVR3.2.
53*7dd7cddfSDavid du Colombier  *
54*7dd7cddfSDavid du Colombier  */
55*7dd7cddfSDavid du Colombier 
56*7dd7cddfSDavid du Colombier #ifdef DKHOST
57*7dd7cddfSDavid du Colombier     if ( line != NULL && *line != '/' )  {
58*7dd7cddfSDavid du Colombier 	if ( strncmp(line, "DK:", 3) == 0 )
59*7dd7cddfSDavid du Colombier 	    line += 3;
60*7dd7cddfSDavid du Colombier 	dkhost_connect();
61*7dd7cddfSDavid du Colombier #ifdef DKSTREAMS
62*7dd7cddfSDavid du Colombier 	if ( ioctl(ttyi, I_PUSH, DKSTREAMS) == -1 )
63*7dd7cddfSDavid du Colombier 	    error(FATAL, "ioctl error - %s", DKSTREAMS);
64*7dd7cddfSDavid du Colombier 	if ( ioctl(ttyi, I_PUSH, "ldterm") == -1 )
65*7dd7cddfSDavid du Colombier 	    error(FATAL, "ioctl error - ldterm");
66*7dd7cddfSDavid du Colombier #endif
67*7dd7cddfSDavid du Colombier     } else
68*7dd7cddfSDavid du Colombier #endif
69*7dd7cddfSDavid du Colombier 
70*7dd7cddfSDavid du Colombier     if ( line == NULL )
71*7dd7cddfSDavid du Colombier 	ttyi = fileno(stdout);
72*7dd7cddfSDavid du Colombier     else if ( (ttyi = open(line, O_RDWR)) == -1 )
73*7dd7cddfSDavid du Colombier 	error(FATAL, "can't open %s", line);
74*7dd7cddfSDavid du Colombier 
75*7dd7cddfSDavid du Colombier     if ( (ttyo = dup(ttyi)) == -1 )
76*7dd7cddfSDavid du Colombier 	error(FATAL, "can't dup file descriptor for %s", line);
77*7dd7cddfSDavid du Colombier 
78*7dd7cddfSDavid du Colombier     if ( stopbits == 1 )
79*7dd7cddfSDavid du Colombier 	stopbits = 0;
80*7dd7cddfSDavid du Colombier     else stopbits = CSTOPB;
81*7dd7cddfSDavid du Colombier 
82*7dd7cddfSDavid du Colombier     if ( fcntl(ttyi, F_SETFL, O_NDELAY) == -1 )
83*7dd7cddfSDavid du Colombier 	error(FATAL, "fcntl error - F_SETFL");
84*7dd7cddfSDavid du Colombier 
85*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TCGETA, &termio) == -1 )
86*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TCGETA");
87*7dd7cddfSDavid du Colombier 
88*7dd7cddfSDavid du Colombier     termio.c_iflag = IXON | IGNCR;
89*7dd7cddfSDavid du Colombier     termio.c_oflag = 0;
90*7dd7cddfSDavid du Colombier     termio.c_cflag = HUPCL | CREAD | CS8 | stopbits | baudrate;
91*7dd7cddfSDavid du Colombier     termio.c_lflag = 0;
92*7dd7cddfSDavid du Colombier     termio.c_cc[VMIN] = termio.c_cc[VTIME] = 0;
93*7dd7cddfSDavid du Colombier 
94*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TCSETA, &termio) == -1 )
95*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TCSETA");
96*7dd7cddfSDavid du Colombier 
97*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TCFLSH, 2) == -1 )
98*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TCFLSH");
99*7dd7cddfSDavid du Colombier 
100*7dd7cddfSDavid du Colombier     fp_ttyi = fdopen(ttyi, "r");
101*7dd7cddfSDavid du Colombier 
102*7dd7cddfSDavid du Colombier }   /* End of setupline */
103*7dd7cddfSDavid du Colombier 
104*7dd7cddfSDavid du Colombier /*****************************************************************************/
105*7dd7cddfSDavid du Colombier 
resetline()106*7dd7cddfSDavid du Colombier resetline()
107*7dd7cddfSDavid du Colombier 
108*7dd7cddfSDavid du Colombier {
109*7dd7cddfSDavid du Colombier 
110*7dd7cddfSDavid du Colombier     int			flags;		/* for turning O_NDELAY off */
111*7dd7cddfSDavid du Colombier     struct termio	termio;		/* so we can reset flow control */
112*7dd7cddfSDavid du Colombier 
113*7dd7cddfSDavid du Colombier /*
114*7dd7cddfSDavid du Colombier  *
115*7dd7cddfSDavid du Colombier  * Only used if we're running the program as separate read and write processes.
116*7dd7cddfSDavid du Colombier  * Called from split() after the initial connection has been made and returns
117*7dd7cddfSDavid du Colombier  * TRUE if two processes should work. Don't know if the O_NDELAY stuff is really
118*7dd7cddfSDavid du Colombier  * needed, but setting c_cc[VMIN] to 1 definitely is. If we leave it be (as a 0)
119*7dd7cddfSDavid du Colombier  * the read in readline() won't block!
120*7dd7cddfSDavid du Colombier  *
121*7dd7cddfSDavid du Colombier  */
122*7dd7cddfSDavid du Colombier 
123*7dd7cddfSDavid du Colombier     if ( (flags = fcntl(ttyi, F_GETFL, 0)) == -1 )
124*7dd7cddfSDavid du Colombier 	error(FATAL, "fcntl error - F_GETFL");
125*7dd7cddfSDavid du Colombier 
126*7dd7cddfSDavid du Colombier     flags &= ~O_NDELAY;
127*7dd7cddfSDavid du Colombier 
128*7dd7cddfSDavid du Colombier     if ( fcntl(ttyi, F_SETFL, flags) == -1 )
129*7dd7cddfSDavid du Colombier 	error(FATAL, "fcntl error - F_SETFL");
130*7dd7cddfSDavid du Colombier 
131*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TCGETA, &termio) == -1 )
132*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TCGETA");
133*7dd7cddfSDavid du Colombier 
134*7dd7cddfSDavid du Colombier     termio.c_iflag &= ~IXANY;
135*7dd7cddfSDavid du Colombier     termio.c_iflag |= IXON | IXOFF;
136*7dd7cddfSDavid du Colombier     termio.c_cc[VMIN] = 1;
137*7dd7cddfSDavid du Colombier     termio.c_cc[VTIME] = 0;
138*7dd7cddfSDavid du Colombier 
139*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TCSETA, &termio) == -1 )
140*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TCSETA");
141*7dd7cddfSDavid du Colombier 
142*7dd7cddfSDavid du Colombier     return(TRUE);
143*7dd7cddfSDavid du Colombier 
144*7dd7cddfSDavid du Colombier }   /* End of resetline */
145*7dd7cddfSDavid du Colombier 
146*7dd7cddfSDavid du Colombier /*****************************************************************************/
147*7dd7cddfSDavid du Colombier 
setupstdin(mode)148*7dd7cddfSDavid du Colombier setupstdin(mode)
149*7dd7cddfSDavid du Colombier 
150*7dd7cddfSDavid du Colombier     int		mode;			/* what to do with stdin settings */
151*7dd7cddfSDavid du Colombier 
152*7dd7cddfSDavid du Colombier {
153*7dd7cddfSDavid du Colombier 
154*7dd7cddfSDavid du Colombier     struct termio		termio;
155*7dd7cddfSDavid du Colombier 
156*7dd7cddfSDavid du Colombier     static int			saved = FALSE;
157*7dd7cddfSDavid du Colombier     static struct termio	oldtermio;
158*7dd7cddfSDavid du Colombier 
159*7dd7cddfSDavid du Colombier /*
160*7dd7cddfSDavid du Colombier  *
161*7dd7cddfSDavid du Colombier  * Save (mode = 0), reset (mode = 1), or restore (mode = 2) the tty settings for
162*7dd7cddfSDavid du Colombier  * stdin. Expect something like raw mode with no echo will be set up. Explicit
163*7dd7cddfSDavid du Colombier  * code to ensure blocking reads probably isn't needed because blocksize is set
164*7dd7cddfSDavid du Colombier  * to 1 when we're in interactive mode, but I've included it anyway.
165*7dd7cddfSDavid du Colombier  *
166*7dd7cddfSDavid du Colombier  */
167*7dd7cddfSDavid du Colombier 
168*7dd7cddfSDavid du Colombier     if ( interactive == TRUE )
169*7dd7cddfSDavid du Colombier 	switch ( mode )  {
170*7dd7cddfSDavid du Colombier 	    case 0:
171*7dd7cddfSDavid du Colombier 		if ( isatty(0) != 1 )
172*7dd7cddfSDavid du Colombier 		    error(FATAL, "stdin not a terminal - can't run interactive mode");
173*7dd7cddfSDavid du Colombier 		if ( ioctl(0, TCGETA, &oldtermio) == -1 )
174*7dd7cddfSDavid du Colombier 		    error(FATAL, "can't save terminal settings");
175*7dd7cddfSDavid du Colombier 		saved = TRUE;
176*7dd7cddfSDavid du Colombier 		break;
177*7dd7cddfSDavid du Colombier 
178*7dd7cddfSDavid du Colombier 	    case 1:
179*7dd7cddfSDavid du Colombier 		termio = oldtermio;
180*7dd7cddfSDavid du Colombier 		termio.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL);
181*7dd7cddfSDavid du Colombier 		termio.c_cc[VMIN] = 1;
182*7dd7cddfSDavid du Colombier 		termio.c_cc[VTIME] = 0;
183*7dd7cddfSDavid du Colombier 		ioctl(0, TCSETA, &termio);
184*7dd7cddfSDavid du Colombier 		break;
185*7dd7cddfSDavid du Colombier 
186*7dd7cddfSDavid du Colombier 	    case 2:
187*7dd7cddfSDavid du Colombier 		if ( saved == TRUE )
188*7dd7cddfSDavid du Colombier 		    ioctl(0, TCSETA, &oldtermio);
189*7dd7cddfSDavid du Colombier 		break;
190*7dd7cddfSDavid du Colombier 	}   /* End switch */
191*7dd7cddfSDavid du Colombier 
192*7dd7cddfSDavid du Colombier }   /* End of setupstdin */
193*7dd7cddfSDavid du Colombier 
194*7dd7cddfSDavid du Colombier /*****************************************************************************/
195*7dd7cddfSDavid du Colombier 
readline()196*7dd7cddfSDavid du Colombier readline()
197*7dd7cddfSDavid du Colombier 
198*7dd7cddfSDavid du Colombier {
199*7dd7cddfSDavid du Colombier 
200*7dd7cddfSDavid du Colombier     int		n;			/* read() return value */
201*7dd7cddfSDavid du Colombier     int		ch;			/* for interactive mode */
202*7dd7cddfSDavid du Colombier 
203*7dd7cddfSDavid du Colombier     static int	tries = 0;		/* consecutive times read returned 0 */
204*7dd7cddfSDavid du Colombier 
205*7dd7cddfSDavid du Colombier /*
206*7dd7cddfSDavid du Colombier  *
207*7dd7cddfSDavid du Colombier  * Reads characters coming back from the printer on ttyi up to a newline (or EOF)
208*7dd7cddfSDavid du Colombier  * or until no more characters are available. Characters are put in mesg[], the
209*7dd7cddfSDavid du Colombier  * string is terminated with '\0' when we're done with a line and TRUE is returned
210*7dd7cddfSDavid du Colombier  * to the caller. If complete line wasn't available FALSE is returned. Interactive
211*7dd7cddfSDavid du Colombier  * mode should loop here forever, except during start(), echoing characters to
212*7dd7cddfSDavid du Colombier  * stdout. If it happens to leave FALSE should be returned. The non-blocking read
213*7dd7cddfSDavid du Colombier  * gets us out until split() is called.
214*7dd7cddfSDavid du Colombier  *
215*7dd7cddfSDavid du Colombier  * Some users (apparently just on 3B2 DKHOST systems) have had problems with the
216*7dd7cddfSDavid du Colombier  * two process implementation that's forced me to kludge things up some. When a
217*7dd7cddfSDavid du Colombier  * printer (on those systems) is turned off while postio is transmitting files
218*7dd7cddfSDavid du Colombier  * the write process hangs in writeblock() (postio.c) - it's typically in the
219*7dd7cddfSDavid du Colombier  * middle of a write() call, while the read() call (below) continually returns 0.
220*7dd7cddfSDavid du Colombier  * In the original code readline() returned FALSE when read() returned 0 and we
221*7dd7cddfSDavid du Colombier  * get into a loop that never ends - because the write process is hung. In the
222*7dd7cddfSDavid du Colombier  * one process implementation having read return 0 is legitimate because the line
223*7dd7cddfSDavid du Colombier  * is opened for no delay, but with two processes the read() blocks and a return
224*7dd7cddfSDavid du Colombier  * value of 0 should never occur. From my point of view the real problem is that
225*7dd7cddfSDavid du Colombier  * the write() call hangs on 3B2 DKHOST systems and apparently doesn't anywhere
226*7dd7cddfSDavid du Colombier  * else. If the write returned anything less than or equal to 0 writeblock() would
227*7dd7cddfSDavid du Colombier  * shut things down. The kludge I've implemented counts the number of consecutive
228*7dd7cddfSDavid du Colombier  * times read() returns a 0 and if it exceeds a limit (100) the read process will
229*7dd7cddfSDavid du Colombier  * shut things down. In fact one return of 0 from read() when we're in the two
230*7dd7cddfSDavid du Colombier  * process mode is undoubtedly sufficient and no counting should be necessary!!!
231*7dd7cddfSDavid du Colombier  * Moving the check to getstatus() should also work and is probably where things
232*7dd7cddfSDavid du Colombier  * belong.
233*7dd7cddfSDavid du Colombier  *
234*7dd7cddfSDavid du Colombier  */
235*7dd7cddfSDavid du Colombier 
236*7dd7cddfSDavid du Colombier     if ( interactive == FALSE )  {
237*7dd7cddfSDavid du Colombier 	while ( (n = read(ttyi, ptr, 1)) != 0 )  {
238*7dd7cddfSDavid du Colombier 	    if ( n < 0 )
239*7dd7cddfSDavid du Colombier 		if ( errno == EINTR )
240*7dd7cddfSDavid du Colombier 		    continue;
241*7dd7cddfSDavid du Colombier 		else error(FATAL, "error reading %s", line);
242*7dd7cddfSDavid du Colombier 	    tries = 0;
243*7dd7cddfSDavid du Colombier 	    if ( *ptr == '\n' || *ptr == '\004' || ptr >= endmesg )  {
244*7dd7cddfSDavid du Colombier 		*(ptr+1) = '\0';
245*7dd7cddfSDavid du Colombier 		if ( *ptr == '\004' )
246*7dd7cddfSDavid du Colombier 		    strcpy(ptr, "%%[ status: endofjob ]%%\n");
247*7dd7cddfSDavid du Colombier 		ptr = mesg;
248*7dd7cddfSDavid du Colombier 		return(TRUE);
249*7dd7cddfSDavid du Colombier 	    }   /* End if */
250*7dd7cddfSDavid du Colombier 	    ptr++;
251*7dd7cddfSDavid du Colombier 	}   /* End while */
252*7dd7cddfSDavid du Colombier 	if ( canread == TRUE && canwrite == FALSE )	/* read process kludge */
253*7dd7cddfSDavid du Colombier 	    if ( ++tries > 100 )
254*7dd7cddfSDavid du Colombier 		error(FATAL, "printer appears to be offline - shutting down");
255*7dd7cddfSDavid du Colombier 	return(FALSE);
256*7dd7cddfSDavid du Colombier     }	/* End if */
257*7dd7cddfSDavid du Colombier 
258*7dd7cddfSDavid du Colombier     if ( canwrite == TRUE )		/* don't block during start() */
259*7dd7cddfSDavid du Colombier 	return(FALSE);
260*7dd7cddfSDavid du Colombier 
261*7dd7cddfSDavid du Colombier     while ( (ch = getc(fp_ttyi)) != EOF )
262*7dd7cddfSDavid du Colombier 	putc(ch, stdout);
263*7dd7cddfSDavid du Colombier     return(FALSE);
264*7dd7cddfSDavid du Colombier 
265*7dd7cddfSDavid du Colombier }   /* End of readline */
266*7dd7cddfSDavid du Colombier #endif
267*7dd7cddfSDavid du Colombier 
268*7dd7cddfSDavid du Colombier /*****************************************************************************/
269*7dd7cddfSDavid du Colombier 
270*7dd7cddfSDavid du Colombier #ifdef V9
271*7dd7cddfSDavid du Colombier #include <ipc.h>
272*7dd7cddfSDavid du Colombier 
273*7dd7cddfSDavid du Colombier char	tbuf[256];			/* temporary input buffer */
274*7dd7cddfSDavid du Colombier char	*nptr = tbuf;			/* next character comes from here */
275*7dd7cddfSDavid du Colombier char	*eptr = tbuf;			/* one past the last character in tbuf */
276*7dd7cddfSDavid du Colombier 
setupline()277*7dd7cddfSDavid du Colombier setupline()
278*7dd7cddfSDavid du Colombier 
279*7dd7cddfSDavid du Colombier {
280*7dd7cddfSDavid du Colombier 
281*7dd7cddfSDavid du Colombier     struct sgttyb	sgtty;
282*7dd7cddfSDavid du Colombier     struct ttydevb	ttydev;		/* for setting up the line */
283*7dd7cddfSDavid du Colombier     static struct tchars	tchar = { '\377',	/* interrupt */
284*7dd7cddfSDavid du Colombier 					  '\377',	/* quit */
285*7dd7cddfSDavid du Colombier 					  '\021',	/* start output */
286*7dd7cddfSDavid du Colombier 					  '\023',	/* stop output */
287*7dd7cddfSDavid du Colombier 					  '\377',	/* end-of-file */
288*7dd7cddfSDavid du Colombier 					  '\377'	/* input delimiter */
289*7dd7cddfSDavid du Colombier 					};
290*7dd7cddfSDavid du Colombier 
291*7dd7cddfSDavid du Colombier /*
292*7dd7cddfSDavid du Colombier  *
293*7dd7cddfSDavid du Colombier  * Line initialization for V9.
294*7dd7cddfSDavid du Colombier  *
295*7dd7cddfSDavid du Colombier  */
296*7dd7cddfSDavid du Colombier 
297*7dd7cddfSDavid du Colombier     if ( line == NULL )  {
298*7dd7cddfSDavid du Colombier 	ttyi = ttyo = 1;
299*7dd7cddfSDavid du Colombier 	return;
300*7dd7cddfSDavid du Colombier     }	/* End if */
301*7dd7cddfSDavid du Colombier     alarm(120);			/* watch for hanging opens */
302*7dd7cddfSDavid du Colombier     if ( line[0] == '/' ) {
303*7dd7cddfSDavid du Colombier 	if ( (ttyi = open(line, O_RDWR)) == -1 )
304*7dd7cddfSDavid du Colombier 	error(FATAL, "can't open %s", line);
305*7dd7cddfSDavid du Colombier     } else if ((ttyi = ipcopen(ipcpath(line, "dk", 0), "")) < 0) {
306*7dd7cddfSDavid du Colombier 		sleep(5);	/* wait for Datakit to hangup */
307*7dd7cddfSDavid du Colombier 		if ((ttyi = ipcopen(ipcpath(line, "dk", 0), "")) < 0) {
308*7dd7cddfSDavid du Colombier 			fprintf(stderr, "%s", errstr);
309*7dd7cddfSDavid du Colombier 			error(FATAL, "can't ipcopen %s", line);
310*7dd7cddfSDavid du Colombier 		}
311*7dd7cddfSDavid du Colombier     }
312*7dd7cddfSDavid du Colombier     alarm(0);
313*7dd7cddfSDavid du Colombier 
314*7dd7cddfSDavid du Colombier     if ( (ttyo = dup(ttyi)) == -1 )
315*7dd7cddfSDavid du Colombier 	error(FATAL, "can't dup file descriptor for %s", line);
316*7dd7cddfSDavid du Colombier 
317*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, FIOPUSHLD, &tty_ld) == -1 )
318*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - FIOPUSHLD");
319*7dd7cddfSDavid du Colombier 
320*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCGDEV, &ttydev) == -1 )
321*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCGDEV");
322*7dd7cddfSDavid du Colombier 
323*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCGETP, &sgtty) == -1 )
324*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCGETP");
325*7dd7cddfSDavid du Colombier 
326*7dd7cddfSDavid du Colombier     sgtty.sg_flags &= ~ECHO;
327*7dd7cddfSDavid du Colombier     sgtty.sg_flags &= ~CRMOD;
328*7dd7cddfSDavid du Colombier     sgtty.sg_flags |= CBREAK;
329*7dd7cddfSDavid du Colombier     ttydev.ispeed = baudrate;
330*7dd7cddfSDavid du Colombier     ttydev.ospeed = baudrate;
331*7dd7cddfSDavid du Colombier 
332*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCSDEV, &ttydev) == -1 )
333*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCSDEV");
334*7dd7cddfSDavid du Colombier 
335*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCSETP, &sgtty) == -1 )
336*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCSETP");
337*7dd7cddfSDavid du Colombier 
338*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCSETC, &tchar) == -1 )
339*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCSETC");
340*7dd7cddfSDavid du Colombier 
341*7dd7cddfSDavid du Colombier     fp_ttyi = fdopen(ttyi, "r");
342*7dd7cddfSDavid du Colombier 
343*7dd7cddfSDavid du Colombier }   /* End of setupline */
344*7dd7cddfSDavid du Colombier 
345*7dd7cddfSDavid du Colombier /*****************************************************************************/
346*7dd7cddfSDavid du Colombier 
resetline()347*7dd7cddfSDavid du Colombier resetline()
348*7dd7cddfSDavid du Colombier 
349*7dd7cddfSDavid du Colombier {
350*7dd7cddfSDavid du Colombier 
351*7dd7cddfSDavid du Colombier     struct sgttyb	sgtty;
352*7dd7cddfSDavid du Colombier 
353*7dd7cddfSDavid du Colombier /*
354*7dd7cddfSDavid du Colombier  *
355*7dd7cddfSDavid du Colombier  * Only used if we're running the program as separate read and write processes.
356*7dd7cddfSDavid du Colombier  * Called from split() after the initial connection has been made and returns
357*7dd7cddfSDavid du Colombier  * TRUE if two processes should work. Haven't tested or even compiled the stuff
358*7dd7cddfSDavid du Colombier  * for separate read and write processes on Ninth Edition systems - no guarantees
359*7dd7cddfSDavid du Colombier  * even though we return TRUE!
360*7dd7cddfSDavid du Colombier  *
361*7dd7cddfSDavid du Colombier  */
362*7dd7cddfSDavid du Colombier 
363*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCGETP, &sgtty) == -1 )
364*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCGETP");
365*7dd7cddfSDavid du Colombier 
366*7dd7cddfSDavid du Colombier     sgtty.sg_flags |= TANDEM;
367*7dd7cddfSDavid du Colombier 
368*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCSETP, &sgtty) == -1 )
369*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCSETP");
370*7dd7cddfSDavid du Colombier 
371*7dd7cddfSDavid du Colombier     return(TRUE);
372*7dd7cddfSDavid du Colombier 
373*7dd7cddfSDavid du Colombier }   /* End of resetline */
374*7dd7cddfSDavid du Colombier 
375*7dd7cddfSDavid du Colombier /*****************************************************************************/
376*7dd7cddfSDavid du Colombier 
setupstdin(mode)377*7dd7cddfSDavid du Colombier setupstdin(mode)
378*7dd7cddfSDavid du Colombier 
379*7dd7cddfSDavid du Colombier     int		mode;			/* what to do with stdin settings */
380*7dd7cddfSDavid du Colombier 
381*7dd7cddfSDavid du Colombier {
382*7dd7cddfSDavid du Colombier 
383*7dd7cddfSDavid du Colombier     struct sgttyb		sgtty;
384*7dd7cddfSDavid du Colombier 
385*7dd7cddfSDavid du Colombier     static int			saved = FALSE;
386*7dd7cddfSDavid du Colombier     static struct sgttyb	oldsgtty;
387*7dd7cddfSDavid du Colombier 
388*7dd7cddfSDavid du Colombier /*
389*7dd7cddfSDavid du Colombier  *
390*7dd7cddfSDavid du Colombier  * Save (mode = 0), reset (mode = 1), or restore (mode = 2) the tty settings for
391*7dd7cddfSDavid du Colombier  * stdin. Expect something like raw mode with no echo will be set up. Need to make
392*7dd7cddfSDavid du Colombier  * sure interrupt and quit still work - they're the only good way to exit when
393*7dd7cddfSDavid du Colombier  * we're running interactive mode. I haven't tested or even compiled this code
394*7dd7cddfSDavid du Colombier  * so there are no guarantees.
395*7dd7cddfSDavid du Colombier  *
396*7dd7cddfSDavid du Colombier  */
397*7dd7cddfSDavid du Colombier 
398*7dd7cddfSDavid du Colombier     if ( interactive == TRUE )
399*7dd7cddfSDavid du Colombier 	switch ( mode )  {
400*7dd7cddfSDavid du Colombier 	    case 0:
401*7dd7cddfSDavid du Colombier 		if ( ioctl(0, TIOCGETP, &oldsgtty) == -1 )
402*7dd7cddfSDavid du Colombier 		    error(FATAL, "can't save terminal settings");
403*7dd7cddfSDavid du Colombier 		saved = TRUE;
404*7dd7cddfSDavid du Colombier 		break;
405*7dd7cddfSDavid du Colombier 
406*7dd7cddfSDavid du Colombier 	    case 1:
407*7dd7cddfSDavid du Colombier 		sgtty = oldsgtty;
408*7dd7cddfSDavid du Colombier 		sgtty.sg_flags &= ~ECHO;
409*7dd7cddfSDavid du Colombier 		sgtty.sg_flags |= CBREAK;
410*7dd7cddfSDavid du Colombier 		ioctl(0, TIOCSETP, &sgtty);
411*7dd7cddfSDavid du Colombier 		break;
412*7dd7cddfSDavid du Colombier 
413*7dd7cddfSDavid du Colombier 	    case 2:
414*7dd7cddfSDavid du Colombier 		if ( saved == TRUE )
415*7dd7cddfSDavid du Colombier 		    ioctl(0, TIOCSETP, &oldsgtty);
416*7dd7cddfSDavid du Colombier 		break;
417*7dd7cddfSDavid du Colombier 	}   /* End switch */
418*7dd7cddfSDavid du Colombier 
419*7dd7cddfSDavid du Colombier }   /* End of setupstdin */
420*7dd7cddfSDavid du Colombier 
421*7dd7cddfSDavid du Colombier /*****************************************************************************/
422*7dd7cddfSDavid du Colombier 
readline()423*7dd7cddfSDavid du Colombier readline()
424*7dd7cddfSDavid du Colombier 
425*7dd7cddfSDavid du Colombier {
426*7dd7cddfSDavid du Colombier 
427*7dd7cddfSDavid du Colombier     int		n;			/* read() return value */
428*7dd7cddfSDavid du Colombier     int		ch;			/* for interactive mode */
429*7dd7cddfSDavid du Colombier 
430*7dd7cddfSDavid du Colombier /*
431*7dd7cddfSDavid du Colombier  *
432*7dd7cddfSDavid du Colombier  * Reads characters coming back from the printer on ttyi up to a newline (or EOF)
433*7dd7cddfSDavid du Colombier  * and transfers each line to the mesg[] array. Everything available on ttyi is
434*7dd7cddfSDavid du Colombier  * initially stored in tbuf[] and a line at a time is transferred from there to
435*7dd7cddfSDavid du Colombier  * mesg[]. The string in mesg[] is terminated with a '\0' and TRUE is returned to
436*7dd7cddfSDavid du Colombier  * the caller when we find a newline, EOF, or reach the end of the mesg[] array.
437*7dd7cddfSDavid du Colombier  * If nothing is available on ttyi we return FALSE if a single process is being
438*7dd7cddfSDavid du Colombier  * used for reads and writes, while in the two process implementation we force a
439*7dd7cddfSDavid du Colombier  * one character read. Interactive mode loops here forever, except during start(),
440*7dd7cddfSDavid du Colombier  * echoing everything that comes back on ttyi to stdout. The performance of a
441*7dd7cddfSDavid du Colombier  * simple getc/putc loop for interactive mode was unacceptable when run under mux
442*7dd7cddfSDavid du Colombier  * and has been replaced by more complicated code. When layers wasn't involved
443*7dd7cddfSDavid du Colombier  * the getc/putc loop worked well.
444*7dd7cddfSDavid du Colombier  *
445*7dd7cddfSDavid du Colombier  */
446*7dd7cddfSDavid du Colombier 
447*7dd7cddfSDavid du Colombier     if ( interactive == FALSE )  {
448*7dd7cddfSDavid du Colombier 	while ( 1 )  {
449*7dd7cddfSDavid du Colombier 	    while ( nptr < eptr )  {	/* grab characters from tbuf */
450*7dd7cddfSDavid du Colombier 		*ptr = *nptr++;
451*7dd7cddfSDavid du Colombier 		if ( *ptr == '\r' ) continue;
452*7dd7cddfSDavid du Colombier 		if ( *ptr == '\n' || *ptr == '\004' || ptr >= endmesg )  {
453*7dd7cddfSDavid du Colombier 		    *(ptr+1) = '\0';
454*7dd7cddfSDavid du Colombier 		    if ( *ptr == '\004' )
455*7dd7cddfSDavid du Colombier 			strcpy(ptr, "%%[ status: endofjob ]%%\n");
456*7dd7cddfSDavid du Colombier 		    ptr = mesg;
457*7dd7cddfSDavid du Colombier 		    return(TRUE);
458*7dd7cddfSDavid du Colombier 		}   /* End if */
459*7dd7cddfSDavid du Colombier 		++ptr;
460*7dd7cddfSDavid du Colombier 	    }	/* End for */
461*7dd7cddfSDavid du Colombier 
462*7dd7cddfSDavid du Colombier 	    nptr = eptr = tbuf;
463*7dd7cddfSDavid du Colombier 	    if ( ioctl(ttyi, FIONREAD, &n) < 0 )
464*7dd7cddfSDavid du Colombier 		if ( errno == EINTR )
465*7dd7cddfSDavid du Colombier 		    continue;
466*7dd7cddfSDavid du Colombier 		else error(FATAL, "ioctl error - FIONREAD");
467*7dd7cddfSDavid du Colombier 	    if ( n <= 0 )
468*7dd7cddfSDavid du Colombier 		if ( canwrite == TRUE )
469*7dd7cddfSDavid du Colombier 		    return(FALSE);
470*7dd7cddfSDavid du Colombier 	    n = ((n < 1) ? 1 : ((n < sizeof(tbuf)) ? n : sizeof(tbuf)));
471*7dd7cddfSDavid du Colombier 	    if ( (n = read(ttyi, tbuf, n)) < 0 )
472*7dd7cddfSDavid du Colombier 		if ( errno == EINTR )
473*7dd7cddfSDavid du Colombier 		    continue;
474*7dd7cddfSDavid du Colombier 		else error(FATAL, "error reading line %s", line);
475*7dd7cddfSDavid du Colombier 	    else eptr = nptr + n;
476*7dd7cddfSDavid du Colombier 	}   /* End while */
477*7dd7cddfSDavid du Colombier     }	/* End if */
478*7dd7cddfSDavid du Colombier 
479*7dd7cddfSDavid du Colombier     if ( canwrite == TRUE )		/* don't block during start() */
480*7dd7cddfSDavid du Colombier 	return(FALSE);
481*7dd7cddfSDavid du Colombier 
482*7dd7cddfSDavid du Colombier     while ( 1 )  {			/* only interactive mode gets here */
483*7dd7cddfSDavid du Colombier 	if ( ioctl(ttyi, FIONREAD, &n) < 0 )
484*7dd7cddfSDavid du Colombier 	    error(FATAL, "ioctl error - FIONREAD");
485*7dd7cddfSDavid du Colombier 	n = ((n < 1) ? 1 : ((n < sizeof(tbuf)) ? n : sizeof(tbuf)));
486*7dd7cddfSDavid du Colombier 	if ( (n = read(ttyi, tbuf, n)) < 0 )
487*7dd7cddfSDavid du Colombier 	    error(FATAL, "error reading line %s", line);
488*7dd7cddfSDavid du Colombier 	else if ( n == 0 )		/* should not happen */
489*7dd7cddfSDavid du Colombier 	    error(FATAL, "end of file in interactive mode");
490*7dd7cddfSDavid du Colombier 	if ( write(1, tbuf, n) != n )
491*7dd7cddfSDavid du Colombier 	    error(FATAL, "error writing to stdout");
492*7dd7cddfSDavid du Colombier     }	/* End while */
493*7dd7cddfSDavid du Colombier 
494*7dd7cddfSDavid du Colombier     return(FALSE);
495*7dd7cddfSDavid du Colombier 
496*7dd7cddfSDavid du Colombier }   /* End of readline */
497*7dd7cddfSDavid du Colombier #endif
498*7dd7cddfSDavid du Colombier 
499*7dd7cddfSDavid du Colombier /*****************************************************************************/
500*7dd7cddfSDavid du Colombier 
501*7dd7cddfSDavid du Colombier #ifdef BSD4_2
setupline()502*7dd7cddfSDavid du Colombier setupline()
503*7dd7cddfSDavid du Colombier 
504*7dd7cddfSDavid du Colombier {
505*7dd7cddfSDavid du Colombier 
506*7dd7cddfSDavid du Colombier     struct sgttyb	sgtty;
507*7dd7cddfSDavid du Colombier     static struct tchars	tchar = { '\377',	/* interrupt */
508*7dd7cddfSDavid du Colombier 					  '\377',	/* quit */
509*7dd7cddfSDavid du Colombier 					  '\021',	/* start output */
510*7dd7cddfSDavid du Colombier 					  '\023',	/* stop output */
511*7dd7cddfSDavid du Colombier 					  '\377',	/* end-of-file */
512*7dd7cddfSDavid du Colombier 					  '\377'	/* input delimiter */
513*7dd7cddfSDavid du Colombier 					};
514*7dd7cddfSDavid du Colombier     long	lmodes;
515*7dd7cddfSDavid du Colombier     int		disc = NTTYDISC;
516*7dd7cddfSDavid du Colombier 
517*7dd7cddfSDavid du Colombier /*
518*7dd7cddfSDavid du Colombier  *
519*7dd7cddfSDavid du Colombier  * Line initialization for BSD4_2. As in the System V code, if no line is given
520*7dd7cddfSDavid du Colombier  * (ie. line == NULL) we continue on as before using stdout as ttyi and ttyo.
521*7dd7cddfSDavid du Colombier  *
522*7dd7cddfSDavid du Colombier  */
523*7dd7cddfSDavid du Colombier 
524*7dd7cddfSDavid du Colombier     if ( line == NULL )
525*7dd7cddfSDavid du Colombier 	ttyi = fileno(stdout);
526*7dd7cddfSDavid du Colombier     else if ( (ttyi = open(line, O_RDWR)) == -1 )
527*7dd7cddfSDavid du Colombier 	error(FATAL, "can't open %s", line);
528*7dd7cddfSDavid du Colombier 
529*7dd7cddfSDavid du Colombier     if ( (ttyo = dup(ttyi)) == -1 )
530*7dd7cddfSDavid du Colombier 	error(FATAL, "can't dup file descriptor for %s", line);
531*7dd7cddfSDavid du Colombier 
532*7dd7cddfSDavid du Colombier     if (ioctl(ttyi, TIOCSETD, &disc) == -1 )
533*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCSETD");
534*7dd7cddfSDavid du Colombier 
535*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCGETP, &sgtty) == -1 )
536*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCGETP");
537*7dd7cddfSDavid du Colombier 
538*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCLGET, &lmodes) == -1 )
539*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCLGET");
540*7dd7cddfSDavid du Colombier 
541*7dd7cddfSDavid du Colombier     sgtty.sg_flags &= ~ECHO;
542*7dd7cddfSDavid du Colombier     sgtty.sg_flags &= ~CRMOD;
543*7dd7cddfSDavid du Colombier     sgtty.sg_flags |= CBREAK;
544*7dd7cddfSDavid du Colombier     sgtty.sg_ispeed = baudrate;
545*7dd7cddfSDavid du Colombier     sgtty.sg_ospeed = baudrate;
546*7dd7cddfSDavid du Colombier     lmodes |= LDECCTQ;
547*7dd7cddfSDavid du Colombier 
548*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCSETP, &sgtty) == -1 )
549*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCSETP");
550*7dd7cddfSDavid du Colombier 
551*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCSETC, &tchar) == -1 )
552*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCSETC");
553*7dd7cddfSDavid du Colombier 
554*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCLSET, &lmodes) == -1 )
555*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCLSET");
556*7dd7cddfSDavid du Colombier 
557*7dd7cddfSDavid du Colombier     fp_ttyi = fdopen(ttyi, "r");
558*7dd7cddfSDavid du Colombier 
559*7dd7cddfSDavid du Colombier }   /* End of setupline */
560*7dd7cddfSDavid du Colombier 
561*7dd7cddfSDavid du Colombier /*****************************************************************************/
562*7dd7cddfSDavid du Colombier 
resetline()563*7dd7cddfSDavid du Colombier resetline()
564*7dd7cddfSDavid du Colombier 
565*7dd7cddfSDavid du Colombier {
566*7dd7cddfSDavid du Colombier 
567*7dd7cddfSDavid du Colombier     struct sgttyb	sgtty;
568*7dd7cddfSDavid du Colombier 
569*7dd7cddfSDavid du Colombier /*
570*7dd7cddfSDavid du Colombier  *
571*7dd7cddfSDavid du Colombier  * Only used if we're running the program as separate read and write processes.
572*7dd7cddfSDavid du Colombier  * Called from split() after the initial connection has been made and returns
573*7dd7cddfSDavid du Colombier  * TRUE if two processes should work. Haven't tested or even compiled the stuff
574*7dd7cddfSDavid du Colombier  * for separate read and write processes on Berkeley systems - no guarantees
575*7dd7cddfSDavid du Colombier  * even though we return TRUE!
576*7dd7cddfSDavid du Colombier  *
577*7dd7cddfSDavid du Colombier  */
578*7dd7cddfSDavid du Colombier 
579*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCGETP, &sgtty) == -1 )
580*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCGETP");
581*7dd7cddfSDavid du Colombier 
582*7dd7cddfSDavid du Colombier     sgtty.sg_flags |= TANDEM;
583*7dd7cddfSDavid du Colombier 
584*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, TIOCSETP, &sgtty) == -1 )
585*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - TIOCSETP");
586*7dd7cddfSDavid du Colombier 
587*7dd7cddfSDavid du Colombier     return(TRUE);
588*7dd7cddfSDavid du Colombier 
589*7dd7cddfSDavid du Colombier }   /* End of resetline */
590*7dd7cddfSDavid du Colombier 
591*7dd7cddfSDavid du Colombier /*****************************************************************************/
592*7dd7cddfSDavid du Colombier 
setupstdin(mode)593*7dd7cddfSDavid du Colombier setupstdin(mode)
594*7dd7cddfSDavid du Colombier 
595*7dd7cddfSDavid du Colombier     int		mode;			/* what to do with stdin settings */
596*7dd7cddfSDavid du Colombier 
597*7dd7cddfSDavid du Colombier {
598*7dd7cddfSDavid du Colombier 
599*7dd7cddfSDavid du Colombier     struct sgttyb		sgtty;
600*7dd7cddfSDavid du Colombier 
601*7dd7cddfSDavid du Colombier     static int			saved = FALSE;
602*7dd7cddfSDavid du Colombier     static struct sgttyb	oldsgtty;
603*7dd7cddfSDavid du Colombier 
604*7dd7cddfSDavid du Colombier /*
605*7dd7cddfSDavid du Colombier  *
606*7dd7cddfSDavid du Colombier  * Save (mode = 0), reset (mode = 1), or restore (mode = 2) the tty settings for
607*7dd7cddfSDavid du Colombier  * stdin. Expect something like raw mode with no echo will be set up. Need to make
608*7dd7cddfSDavid du Colombier  * sure interrupt and quit still work - they're the only good way to exit when
609*7dd7cddfSDavid du Colombier  * we're running interactive mode. I haven't tested or even compiled this code
610*7dd7cddfSDavid du Colombier  * so there are no guarantees.
611*7dd7cddfSDavid du Colombier  *
612*7dd7cddfSDavid du Colombier  */
613*7dd7cddfSDavid du Colombier 
614*7dd7cddfSDavid du Colombier     if ( interactive == TRUE )
615*7dd7cddfSDavid du Colombier 	switch ( mode )  {
616*7dd7cddfSDavid du Colombier 	    case 0:
617*7dd7cddfSDavid du Colombier 		if ( isatty(0) != 1 )
618*7dd7cddfSDavid du Colombier 		    error(FATAL, "stdin not a terminal - can't run interactive mode");
619*7dd7cddfSDavid du Colombier 		if ( ioctl(0, TIOCGETP, &oldsgtty) == -1 )
620*7dd7cddfSDavid du Colombier 		    error(FATAL, "can't save terminal settings");
621*7dd7cddfSDavid du Colombier 		saved = TRUE;
622*7dd7cddfSDavid du Colombier 		break;
623*7dd7cddfSDavid du Colombier 
624*7dd7cddfSDavid du Colombier 	    case 1:
625*7dd7cddfSDavid du Colombier 		sgtty = oldsgtty;
626*7dd7cddfSDavid du Colombier 		sgtty.sg_flags &= ~ECHO;
627*7dd7cddfSDavid du Colombier 		sgtty.sg_flags |= CBREAK;
628*7dd7cddfSDavid du Colombier 		ioctl(0, TIOCSETP, &sgtty);
629*7dd7cddfSDavid du Colombier 		break;
630*7dd7cddfSDavid du Colombier 
631*7dd7cddfSDavid du Colombier 	    case 2:
632*7dd7cddfSDavid du Colombier 		if ( saved == TRUE )
633*7dd7cddfSDavid du Colombier 		    ioctl(0, TIOCSETP, &oldsgtty);
634*7dd7cddfSDavid du Colombier 		break;
635*7dd7cddfSDavid du Colombier 	}   /* End switch */
636*7dd7cddfSDavid du Colombier 
637*7dd7cddfSDavid du Colombier }   /* End of setupstdin */
638*7dd7cddfSDavid du Colombier 
639*7dd7cddfSDavid du Colombier /*****************************************************************************/
640*7dd7cddfSDavid du Colombier 
readline()641*7dd7cddfSDavid du Colombier readline()
642*7dd7cddfSDavid du Colombier 
643*7dd7cddfSDavid du Colombier {
644*7dd7cddfSDavid du Colombier 
645*7dd7cddfSDavid du Colombier     int		n;			/* read() return value */
646*7dd7cddfSDavid du Colombier     int		ch;			/* for interactive mode */
647*7dd7cddfSDavid du Colombier 
648*7dd7cddfSDavid du Colombier /*
649*7dd7cddfSDavid du Colombier  *
650*7dd7cddfSDavid du Colombier  * Reads characters coming back from the printer on ttyo up to a newline (or EOF)
651*7dd7cddfSDavid du Colombier  * or until no more characters are available. Characters are put in mesg[], the
652*7dd7cddfSDavid du Colombier  * string is terminated with '\0' when we're done with a line and TRUE is returned
653*7dd7cddfSDavid du Colombier  * to the caller. If complete line wasn't available FALSE is returned. Interactive
654*7dd7cddfSDavid du Colombier  * mode should loop here forever, except during start(), echoing characters to
655*7dd7cddfSDavid du Colombier  * stdout. If it happens to leave FALSE should be returned. Probably should read
656*7dd7cddfSDavid du Colombier  * everything available on ttyi into a temporary buffer and work from there rather
657*7dd7cddfSDavid du Colombier  * than reading one character at a time.
658*7dd7cddfSDavid du Colombier  *
659*7dd7cddfSDavid du Colombier  */
660*7dd7cddfSDavid du Colombier 
661*7dd7cddfSDavid du Colombier     if ( interactive == FALSE )  {
662*7dd7cddfSDavid du Colombier 	while ( 1 )  {
663*7dd7cddfSDavid du Colombier 	    if ( ioctl(ttyi, FIONREAD, &n) < 0 )
664*7dd7cddfSDavid du Colombier 		if ( errno == EINTR )
665*7dd7cddfSDavid du Colombier 		    continue;
666*7dd7cddfSDavid du Colombier 		else error(FATAL, "ioctl error - FIONREAD");
667*7dd7cddfSDavid du Colombier 	    if ( n <= 0 )
668*7dd7cddfSDavid du Colombier 		if ( canwrite == TRUE )
669*7dd7cddfSDavid du Colombier 		    return(FALSE);
670*7dd7cddfSDavid du Colombier 		else n = 1;
671*7dd7cddfSDavid du Colombier 	    for ( ; n > 0; n-- )  {
672*7dd7cddfSDavid du Colombier 		/*if ( read(ttyi, ptr, 1) < 0 )*/
673*7dd7cddfSDavid du Colombier 		if ( (*ptr = getc(fp_ttyi)) == EOF )
674*7dd7cddfSDavid du Colombier 		    if ( errno == EINTR )
675*7dd7cddfSDavid du Colombier 			continue;
676*7dd7cddfSDavid du Colombier 		    else error(FATAL, "error reading %s", line);
677*7dd7cddfSDavid du Colombier 		if ( *ptr == '\r' ) continue;
678*7dd7cddfSDavid du Colombier 		if ( *ptr == '\n' || *ptr == '\004' || ptr >= endmesg )  {
679*7dd7cddfSDavid du Colombier 		    *(ptr+1) = '\0';
680*7dd7cddfSDavid du Colombier 		    if ( *ptr == '\004' )
681*7dd7cddfSDavid du Colombier 			strcpy(ptr, "%%[ status: endofjob ]%%\n");
682*7dd7cddfSDavid du Colombier 		    ptr = mesg;
683*7dd7cddfSDavid du Colombier 		    return(TRUE);
684*7dd7cddfSDavid du Colombier 		}   /* End if */
685*7dd7cddfSDavid du Colombier 		++ptr;
686*7dd7cddfSDavid du Colombier 	    }	/* End for */
687*7dd7cddfSDavid du Colombier 	}   /* End while */
688*7dd7cddfSDavid du Colombier     }	/* End if */
689*7dd7cddfSDavid du Colombier 
690*7dd7cddfSDavid du Colombier     if ( canwrite == TRUE )		/* don't block during start() */
691*7dd7cddfSDavid du Colombier 	return(FALSE);
692*7dd7cddfSDavid du Colombier 
693*7dd7cddfSDavid du Colombier     while ( (ch = getc(fp_ttyi)) != EOF )
694*7dd7cddfSDavid du Colombier 	putc(ch, stdout);
695*7dd7cddfSDavid du Colombier     return(FALSE);
696*7dd7cddfSDavid du Colombier 
697*7dd7cddfSDavid du Colombier }   /* End of readline */
698*7dd7cddfSDavid du Colombier 
699*7dd7cddfSDavid du Colombier /*****************************************************************************/
700*7dd7cddfSDavid du Colombier 
701*7dd7cddfSDavid du Colombier /*	@(#)strspn.c	1.2	*/
702*7dd7cddfSDavid du Colombier /*LINTLIBRARY*/
703*7dd7cddfSDavid du Colombier /*
704*7dd7cddfSDavid du Colombier  * Return the number of characters in the maximum leading segment
705*7dd7cddfSDavid du Colombier  * of string which consists solely of characters from charset.
706*7dd7cddfSDavid du Colombier  */
707*7dd7cddfSDavid du Colombier int
strspn(string,charset)708*7dd7cddfSDavid du Colombier strspn(string, charset)
709*7dd7cddfSDavid du Colombier char	*string;
710*7dd7cddfSDavid du Colombier register char	*charset;
711*7dd7cddfSDavid du Colombier {
712*7dd7cddfSDavid du Colombier 	register char *p, *q;
713*7dd7cddfSDavid du Colombier 
714*7dd7cddfSDavid du Colombier 	for(q=string; *q != '\0'; ++q) {
715*7dd7cddfSDavid du Colombier 		for(p=charset; *p != '\0' && *p != *q; ++p)
716*7dd7cddfSDavid du Colombier 			;
717*7dd7cddfSDavid du Colombier 		if(*p == '\0')
718*7dd7cddfSDavid du Colombier 			break;
719*7dd7cddfSDavid du Colombier 	}
720*7dd7cddfSDavid du Colombier 	return(q-string);
721*7dd7cddfSDavid du Colombier }
722*7dd7cddfSDavid du Colombier 
723*7dd7cddfSDavid du Colombier /*	@(#)strpbrk.c	1.2	*/
724*7dd7cddfSDavid du Colombier /*LINTLIBRARY*/
725*7dd7cddfSDavid du Colombier /*
726*7dd7cddfSDavid du Colombier  * Return ptr to first occurance of any character from `brkset'
727*7dd7cddfSDavid du Colombier  * in the character string `string'; NULL if none exists.
728*7dd7cddfSDavid du Colombier  */
729*7dd7cddfSDavid du Colombier 
730*7dd7cddfSDavid du Colombier char *
strpbrk(string,brkset)731*7dd7cddfSDavid du Colombier strpbrk(string, brkset)
732*7dd7cddfSDavid du Colombier register char *string, *brkset;
733*7dd7cddfSDavid du Colombier {
734*7dd7cddfSDavid du Colombier 	register char *p;
735*7dd7cddfSDavid du Colombier 
736*7dd7cddfSDavid du Colombier 	do {
737*7dd7cddfSDavid du Colombier 		for(p=brkset; *p != '\0' && *p != *string; ++p)
738*7dd7cddfSDavid du Colombier 			;
739*7dd7cddfSDavid du Colombier 		if(*p != '\0')
740*7dd7cddfSDavid du Colombier 			return(string);
741*7dd7cddfSDavid du Colombier 	}
742*7dd7cddfSDavid du Colombier 	while(*string++);
743*7dd7cddfSDavid du Colombier 	return((char*)0);
744*7dd7cddfSDavid du Colombier }
745*7dd7cddfSDavid du Colombier 
746*7dd7cddfSDavid du Colombier /*	@(#)strtok.c	1.2	*/
747*7dd7cddfSDavid du Colombier /*	3.0 SID #	1.2	*/
748*7dd7cddfSDavid du Colombier /*LINTLIBRARY*/
749*7dd7cddfSDavid du Colombier /*
750*7dd7cddfSDavid du Colombier  * uses strpbrk and strspn to break string into tokens on
751*7dd7cddfSDavid du Colombier  * sequentially subsequent calls.  returns NULL when no
752*7dd7cddfSDavid du Colombier  * non-separator characters remain.
753*7dd7cddfSDavid du Colombier  * `subsequent' calls are calls with first argument NULL.
754*7dd7cddfSDavid du Colombier  */
755*7dd7cddfSDavid du Colombier 
756*7dd7cddfSDavid du Colombier 
757*7dd7cddfSDavid du Colombier extern int strspn();
758*7dd7cddfSDavid du Colombier extern char *strpbrk();
759*7dd7cddfSDavid du Colombier 
760*7dd7cddfSDavid du Colombier char *
strtok(string,sepset)761*7dd7cddfSDavid du Colombier strtok(string, sepset)
762*7dd7cddfSDavid du Colombier char	*string, *sepset;
763*7dd7cddfSDavid du Colombier {
764*7dd7cddfSDavid du Colombier 	register char	*p, *q, *r;
765*7dd7cddfSDavid du Colombier 	static char	*savept;
766*7dd7cddfSDavid du Colombier 
767*7dd7cddfSDavid du Colombier 	/*first or subsequent call*/
768*7dd7cddfSDavid du Colombier 	p = (string == (char*)0)? savept: string;
769*7dd7cddfSDavid du Colombier 
770*7dd7cddfSDavid du Colombier 	if(p == 0)		/* return if no tokens remaining */
771*7dd7cddfSDavid du Colombier 		return((char*)0);
772*7dd7cddfSDavid du Colombier 
773*7dd7cddfSDavid du Colombier 	q = p + strspn(p, sepset);	/* skip leading separators */
774*7dd7cddfSDavid du Colombier 
775*7dd7cddfSDavid du Colombier 	if(*q == '\0')		/* return if no tokens remaining */
776*7dd7cddfSDavid du Colombier 		return((char*)0);
777*7dd7cddfSDavid du Colombier 
778*7dd7cddfSDavid du Colombier 	if((r = strpbrk(q, sepset)) == (char*)0)	/* move past token */
779*7dd7cddfSDavid du Colombier 		savept = 0;	/* indicate this is last token */
780*7dd7cddfSDavid du Colombier 	else {
781*7dd7cddfSDavid du Colombier 		*r = '\0';
782*7dd7cddfSDavid du Colombier 		savept = ++r;
783*7dd7cddfSDavid du Colombier 	}
784*7dd7cddfSDavid du Colombier 	return(q);
785*7dd7cddfSDavid du Colombier }
786*7dd7cddfSDavid du Colombier #endif
787*7dd7cddfSDavid du Colombier 
788*7dd7cddfSDavid du Colombier /*****************************************************************************/
789*7dd7cddfSDavid du Colombier 
790*7dd7cddfSDavid du Colombier #ifdef DKHOST
791*7dd7cddfSDavid du Colombier 
792*7dd7cddfSDavid du Colombier #ifndef DKSTREAMS
793*7dd7cddfSDavid du Colombier short	dkrmode[3] = {DKR_TIME, 0, 0};
794*7dd7cddfSDavid du Colombier #endif
795*7dd7cddfSDavid du Colombier 
dkhost_connect()796*7dd7cddfSDavid du Colombier dkhost_connect()
797*7dd7cddfSDavid du Colombier 
798*7dd7cddfSDavid du Colombier {
799*7dd7cddfSDavid du Colombier 
800*7dd7cddfSDavid du Colombier     int		ofd;			/* for saving and restoring stderr */
801*7dd7cddfSDavid du Colombier     int		dfd;
802*7dd7cddfSDavid du Colombier     int		retrytime = 5;
803*7dd7cddfSDavid du Colombier 
804*7dd7cddfSDavid du Colombier /*
805*7dd7cddfSDavid du Colombier  *
806*7dd7cddfSDavid du Colombier  * Tries to connect to a Datakit destination. The extra stuff I've added to save
807*7dd7cddfSDavid du Colombier  * and later restore stderr is primarily for our spooling setup at Murray Hill.
808*7dd7cddfSDavid du Colombier  * postio is usually called with stderr directed to a file that will be returned
809*7dd7cddfSDavid du Colombier  * to the user when the job finishes printing. Problems encountered by dkdial(),
810*7dd7cddfSDavid du Colombier  * like busy messages, go to stderr but don't belong in the user's mail. They'll
811*7dd7cddfSDavid du Colombier  * be temporarily directed to the log file. After we've connected stderr will be
812*7dd7cddfSDavid du Colombier  * restored.
813*7dd7cddfSDavid du Colombier  *
814*7dd7cddfSDavid du Colombier  */
815*7dd7cddfSDavid du Colombier 
816*7dd7cddfSDavid du Colombier     if ( *line == '\0' )
817*7dd7cddfSDavid du Colombier 	error(FATAL, "incomplete Datakit line");
818*7dd7cddfSDavid du Colombier 
819*7dd7cddfSDavid du Colombier     if ( fp_log != NULL && fp_log != stderr )  {	/* redirect dkdial errors */
820*7dd7cddfSDavid du Colombier 	ofd = dup(2);
821*7dd7cddfSDavid du Colombier 	close(2);
822*7dd7cddfSDavid du Colombier 	dup(fileno(fp_log));
823*7dd7cddfSDavid du Colombier     }	/* End if */
824*7dd7cddfSDavid du Colombier 
825*7dd7cddfSDavid du Colombier     while ( (dfd = ttyi = dkdial(line)) < 0 )  {
826*7dd7cddfSDavid du Colombier 	if ( retrytime < 0 )
827*7dd7cddfSDavid du Colombier 	    error(FATAL, "can't connect to %s", line);
828*7dd7cddfSDavid du Colombier 	sleep(retrytime++);
829*7dd7cddfSDavid du Colombier 	if ( retrytime > 60 )
830*7dd7cddfSDavid du Colombier 	    retrytime = 60;
831*7dd7cddfSDavid du Colombier     }	/* End while */
832*7dd7cddfSDavid du Colombier 
833*7dd7cddfSDavid du Colombier     if ( fp_log != NULL && fp_log != stderr )  {	/* restore stderr */
834*7dd7cddfSDavid du Colombier 	close(2);
835*7dd7cddfSDavid du Colombier 	dup(ofd);
836*7dd7cddfSDavid du Colombier 	close(ofd);
837*7dd7cddfSDavid du Colombier     }	/* End if */
838*7dd7cddfSDavid du Colombier 
839*7dd7cddfSDavid du Colombier #ifndef DKSTREAMS
840*7dd7cddfSDavid du Colombier     if ( ioctl(ttyi, DIOCRMODE, dkrmode) == -1 )
841*7dd7cddfSDavid du Colombier 	error(FATAL, "ioctl error - DIOCRMODE");
842*7dd7cddfSDavid du Colombier 
843*7dd7cddfSDavid du Colombier #ifdef DIOURPWD
844*7dd7cddfSDavid du Colombier     if ( window_size > 0 ) {
845*7dd7cddfSDavid du Colombier 	short	dkparm[3];
846*7dd7cddfSDavid du Colombier 
847*7dd7cddfSDavid du Colombier 	dkparm[0] = dkminor(ttyi);
848*7dd7cddfSDavid du Colombier 	dkparm[1] = 1;
849*7dd7cddfSDavid du Colombier 	dkparm[2] = window_size;
850*7dd7cddfSDavid du Colombier 	if ( ioctl(ttyi, DIOURPWD, dkparm) < 0 || ioctl(ttyi, DIOCFLUSH, 0) < 0 )
851*7dd7cddfSDavid du Colombier 	    error(NON_FATAL, "WSA failed");
852*7dd7cddfSDavid du Colombier     }	/* End if */
853*7dd7cddfSDavid du Colombier #endif
854*7dd7cddfSDavid du Colombier 
855*7dd7cddfSDavid du Colombier     line = dtnamer(dkminor(ttyi));
856*7dd7cddfSDavid du Colombier 
857*7dd7cddfSDavid du Colombier     if ( (ttyi = open(line, O_RDWR)) == -1 )
858*7dd7cddfSDavid du Colombier 	error(FATAL, "can't open %s", line);
859*7dd7cddfSDavid du Colombier 
860*7dd7cddfSDavid du Colombier     close(dfd);
861*7dd7cddfSDavid du Colombier #endif
862*7dd7cddfSDavid du Colombier 
863*7dd7cddfSDavid du Colombier }   /* End of dkhost_connect */
864*7dd7cddfSDavid du Colombier #endif
865*7dd7cddfSDavid du Colombier 
866*7dd7cddfSDavid du Colombier /*****************************************************************************/
867*7dd7cddfSDavid du Colombier 
868