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