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