|
|
1.1 ! root 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.