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
setupline()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
resetline()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
setupstdin(mode)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
readline()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
setupline()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
resetline()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
setupstdin(mode)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
readline()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
setupline()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
resetline()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
setupstdin(mode)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
readline()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
strspn(string,charset)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 *
strpbrk(string,brkset)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 *
strtok(string,sepset)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
dkhost_connect()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
868