Annotation of researchv10no/cmd/post.src/postio/ifdef.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.