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