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 868