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