Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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