Annotation of researchv10no/cmd/postscript/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: /*****************************************************************************/
                     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: 

unix.superglobalmegacorp.com

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