Annotation of coherent/g/usr/bin/vi/vmsio.c, revision 1.1.1.1

1.1       root        1: /*
                      2:    VMSIO.C -- replacements for lseek(), read() and close() to allow
                      3:               arbitrary byte seeks with non-stream-lf files.
                      4:              
                      5:    (The original version (file routines) were written to port the
                      6:     unix ``less'' program.  This version helps with the elvis port.
                      7:     It may be useful elsewhere to port other utilities.)
                      8: 
                      9:    Written by John Campbell  [email protected].   Use as you
                     10:    wish, but leave me some credit for killing myself on this when
                     11:    I was sick one weekend, ok?
                     12: 
                     13:    Also, added vms_rename as a weak replacment for link().  4/2/91
                     14:    ...and because there was a routine named delete, created a vms_delete.
                     15: 
                     16:    Sigh, Steve wanted pipe stuff, so vms_rpipe(), vms_pread() and
                     17:    vms_pclose() was born.                                   8/2/91
                     18: 
                     19:    Moved the tty i/o routines into this module as well.  vms_open_tty()
                     20:    and vms_ttyread()  (ttread)                              8/2/91
                     21: */
                     22: 
                     23: /*
                     24: Entry points:
                     25: 
                     26: FILE I/O
                     27: vms_close (fd)
                     28: long vms_lseek (fd, offset, direction)
                     29: int vms_read (fd, buf, len)
                     30: int vms_rename (from, to)
                     31: vms_delete (file)
                     32: 
                     33: PIPE I/O
                     34: int vms_rpipe (cmd, fd, input_file)
                     35: int vms_pread (pfile, buffer, size)
                     36: int vms_rpclose(pfile)
                     37: 
                     38: TERMINAL I/O
                     39: vms_open_tty()
                     40: vms_ttyread(buf, len, time)
                     41: */
                     42: static char *version = "VMSIO, version 1.0";
                     43: 
                     44: #include <stdio.h>
                     45: #include <errno.h>
                     46: #include <perror.h>
                     47: #define BUFSIZE 4096
                     48: 
                     49: /* Data and buffers used to implement vms_lseek() and vms_read() */
                     50:    static struct {
                     51:       int type, cur_loc, size, lastbin, maxbin, offset, eob;
                     52:    } fdints[_NFILE] =
                     53:       {{0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},
                     54:        {0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},
                     55:        {0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},
                     56:        {0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},
                     57:        {0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1},{0,0,0,0,0,0,-1}};
                     58:    static char **fdbufs[_NFILE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
                     59: typedef struct {
                     60:         int loc, bstart, bend;
                     61: } seeks;
                     62:    static seeks *fdseeks[_NFILE] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
                     63: 
                     64: /* Intended use for fdseeks:  fdseeks[fd][i] for i'th triple */
                     65: 
                     66: #define G_cur_loc  fdints[fd].cur_loc
                     67: #define G_size     fdints[fd].size
                     68: #define G_eof_seen fdints[fd].eof_seen
                     69: #define G_offset   fdints[fd].offset
                     70: #define G_eob      fdints[fd].eob
                     71: 
                     72: 
                     73: vms_close (fd)
                     74: int fd;
                     75: {
                     76:    if (fd >= 0) {
                     77:    /* Reset fdints[fd] and free any buffers we were using. */
                     78:       fdints[fd].type    = 0;
                     79:       fdints[fd].cur_loc = 0;
                     80:       fdints[fd].size    = 0;
                     81:       fdints[fd].lastbin = 0;
                     82:       fdints[fd].maxbin  = 0;
                     83:       fdints[fd].offset  = 0;
                     84:       fdints[fd].eob     = -1;
                     85: 
                     86:       if (fdseeks[fd])
                     87:          fdseeks[fd] = free (fdseeks[fd]);
                     88:       if (fdbufs[fd])
                     89:          fdbufs[fd]  = free (fdbufs[fd]);
                     90:    }
                     91:    return (close(fd));
                     92: }
                     93: 
                     94: long vms_lseek (fd, offset, direction)
                     95: int fd, offset, direction;
                     96: {
                     97:    int tmp;
                     98: 
                     99:    if (fd > _NFILE) {
                    100:       fprintf (stderr,"Too many files for vms_lseek\n");
                    101:       exit(2);
                    102:    }
                    103:    if (fd < 0) {
                    104:       return lseek (fd, offset, direction);
                    105:    }
                    106:    if (fdints[fd].type == 0)
                    107:       _init(fd);
                    108:    if (fdints[fd].type == 1)
                    109:       return lseek (fd, offset, direction);
                    110: 
                    111: /* Convert the possibly relative `offset' to an absolute offset. */
                    112:    if (direction == 1) {
                    113:       offset = G_cur_loc + offset + G_offset;
                    114:    }
                    115:    else if (direction == 2) {
                    116:       if (G_eob == -1)
                    117:          _refill (fd, -1);   /* Figure out the correct eob byte count */
                    118:       offset = G_eob + offset;
                    119:    }
                    120:    if (offset < 0)
                    121:       return -1;
                    122: 
                    123: /* Limitation of this implementation--only seeks to end of file. */
                    124:    if (G_eob > -1 && offset > G_eob)
                    125:       offset = G_eob;
                    126: 
                    127:    if (G_offset > offset || offset >= G_offset + G_size) {
                    128:       if (_refill (fd, offset) == -1)
                    129:          return -1;
                    130:    }
                    131: 
                    132: /* Byte we want is now in our current buffer. */
                    133:    G_cur_loc = offset - G_offset;
                    134: 
                    135: /* Sanity check. */
                    136:    if (G_cur_loc < 0 || G_cur_loc > BUFSIZE)
                    137:       _error ("G_cur_loc error in vms_lseek\n", 1);
                    138: 
                    139:    return G_cur_loc + G_offset;   /* Byte location in current buffer */
                    140: }
                    141: 
                    142: 
                    143: int vms_read (fd, buf, len)
                    144: int fd, len;
                    145: char *buf;
                    146: {
                    147: /* Buffer the read as the unix system would do. */
                    148:    int  fill = 0, n, num = 0,tmp;
                    149:    char *buffer;
                    150: 
                    151:    if (fd > _NFILE) {
                    152:       fprintf (stderr,"Too many files for vms_read\n");
                    153:       exit(2);
                    154:    }
                    155: 
                    156:    if (fdints[fd].type == 0)
                    157:       _init(fd);
                    158:    if (fdints[fd].type == 1)
                    159:       return read (fd, buf, len);
                    160: 
                    161:    buffer = fdbufs[fd];
                    162: 
                    163:    if (G_eob != -1 && G_cur_loc + G_offset >= G_eob)
                    164:       return 0;   /* EOF */
                    165: 
                    166: /* Move any buffered data into place. */
                    167:    while (len && G_cur_loc < G_size)  {
                    168:       *buf++ = buffer[G_cur_loc++];
                    169:       --len;
                    170:       ++num;
                    171:    }
                    172: /* Refill as many buffers as necessary to put len bytes into buf. */
                    173:    do {
                    174:    /* Don't refill when asked to read beyond the end of the file. */
                    175:       if (G_cur_loc == G_size && (G_eob == -1 || G_offset + G_size < G_eob)) {
                    176:          if (_refill (fd, G_offset + G_size) == -1) return -1;
                    177:       }
                    178:       while (len && G_cur_loc < G_size)  {
                    179:          *buf++ = buffer[G_cur_loc++];
                    180:          --len;
                    181:          ++num;
                    182:       }
                    183:    } while (len && (G_eob == -1 || G_offset + G_size < G_eob));
                    184: /* Sanity check. */
                    185:    if (G_cur_loc < 0 || G_cur_loc > BUFSIZE)
                    186:       _error ("G_cur_loc bad in vms_read", 1);
                    187: 
                    188:    return num;
                    189: }
                    190: 
                    191: /*
                    192:    Fill from the appropriate buffer.  Note that offset is a true byte
                    193:    offset and needs to be converted to fdseeks[fd][i].loc before seeking.
                    194:    This technique may, in fact, generalize to other machines.
                    195: */
                    196: static int _refill (fd, offset)
                    197: int fd, offset;
                    198: {
                    199:    int n, seekbin, tmp;
                    200:    char *buffer = fdbufs[fd];
                    201: 
                    202: /* See if the offset is in our current buffer (eob offset is a pain). */
                    203:    if (offset > 0 && G_eob > -1 && offset >= G_eob)
                    204:       offset = G_eob - 1;
                    205: 
                    206:    if (offset > 0 && G_offset <= offset && offset < G_offset + G_size)
                    207:       return G_offset;
                    208: 
                    209:    seekbin = fdints[fd].lastbin;
                    210: 
                    211: /* Now see if the offset is known (already been read once). */
                    212:    if (offset >= 0 && offset < fdseeks[fd][seekbin].bstart) {
                    213:    /* Yes!  We can seek to a known point to pick up this offset. */
                    214:       while (seekbin > 0) {
                    215:          if (offset >= fdseeks[fd][seekbin].bstart)
                    216:            break;
                    217:          --seekbin;
                    218:       }
                    219:    }
                    220: /* Position ourselves for the read (even if we are already there?) */
                    221: /* We can avoid this lseek if G_offset == [seekbin-1].bstart */
                    222:    if (lseek (fd, fdseeks[fd][seekbin].loc, 0) == -1)
                    223:       _error ("bad seek in _refill");
                    224: 
                    225: /* Ok, fill this buffer. */
                    226: more:
                    227:    G_cur_loc = 0;
                    228:    G_size = 0;
                    229:    G_offset = fdseeks[fd][seekbin].bstart;
                    230: 
                    231: /*
                    232:    Don't want to be left with a partial record.  Choices are to shrink
                    233:    down the read size or to keep seeking so we can backup to just before
                    234:    n == read size.  Which seems faster?  Which puts an arbitrary limit
                    235:    on the record size?
                    236: */
                    237:    /* Some lines longer than 512 may be truncated. */
                    238:       while (G_size < BUFSIZE - 512 &&
                    239:                 (n = read (fd, &buffer[G_size], BUFSIZE - G_size)) > 0) {
                    240: #ifdef OTHERMETHOD
                    241:          if (n == BUFSIZE - G_size)
                    242:             break;   /* Don't count last line (it may be a partial line) */
                    243: #endif
                    244:          G_size += n;
                    245:       }
                    246:       if (n == 0) {
                    247:          if (G_size == 0)
                    248:             ++G_size;
                    249:          G_eob = G_offset + G_size;
                    250:          offset = G_eob;
                    251:       }
                    252:       else if (n == -1) {
                    253:          _error ("vms_read (_refill) error", 0);
                    254:          return -1;
                    255:       }
                    256: 
                    257: /* Update the seek array.  Finish current bin and start next bin. */
                    258:    if (G_size == 0)
                    259:       ++G_size;
                    260:    tmp = G_offset + G_size - 1;
                    261:    if (seekbin < fdints[fd].lastbin && fdseeks[fd][seekbin].bend != tmp) {
                    262:       fprintf (stderr, "Consistency failure in _refill\n");
                    263:       exit(2);
                    264:    }
                    265:    fdseeks[fd][seekbin].bend = tmp;
                    266:    if (G_eob == -1 || G_offset + G_size < G_eob) {
                    267:    /* Set up the next seek bin */
                    268:       if (++seekbin > fdints[fd].maxbin) {
                    269:       /* Make more room. */
                    270:          fdints[fd].maxbin = 2*fdints[fd].maxbin;
                    271:          fdseeks[fd] = (void *)realloc (fdseeks[fd], fdints[fd].maxbin);
                    272:       }
                    273: 
                    274:    /* Make sure that lastbin is up to date. */
                    275:       if (seekbin > fdints[fd].lastbin) fdints[fd].lastbin = seekbin;
                    276: 
                    277:       if ((tmp = lseek(fd,0,1)) == -1)
                    278:          _error ("Seek error in vms_read (refill)");
                    279:       if (seekbin < fdints[fd].lastbin && fdseeks[fd][seekbin].loc != tmp) {
                    280:          fprintf (stderr, "Consistency failure in _refill\n");
                    281:          exit(2);
                    282:       }
                    283:       fdseeks[fd][seekbin].loc = tmp;
                    284: 
                    285:       if (seekbin >= fdints[fd].lastbin) {
                    286:          fdseeks[fd][seekbin].bstart = G_offset + G_size;
                    287:          fdseeks[fd][seekbin].bend = 0;
                    288:       }
                    289:       else {
                    290:       /* Consistency check */
                    291:          tmp = G_offset + G_size;
                    292:          if (fdseeks[fd][seekbin].bstart != tmp) {
                    293:             fprintf (stderr, "Consistency failure in _refill\n");
                    294:             exit(1);
                    295:          }
                    296:       }
                    297:    }
                    298: /* Well, it's either a big do-while loop or this goto... */
                    299:    if (offset == -1 ||
                    300:      (offset >= G_offset + G_size && (offset < G_eob || G_eob == -1)))
                    301:       goto more;
                    302: 
                    303:    return G_offset;
                    304: }
                    305: 
                    306: #include <types.h>
                    307: #include <stat.h>
                    308: /*
                    309:    Note: may want to store a pointer to the statbuf in place of type.
                    310:    For one thing, this would give you the maximum record size.
                    311: 
                    312:    Ok, there are some problems when we don't control open and close.
                    313:    For instance, switching fd's in midstream can throw us.  We could
                    314:    store a statbuf pointer to detect this and it may turn out to be
                    315:    necessary later.  (statbuf has the fid for the file in it.)
                    316: */
                    317: static _init(fd)
                    318: int fd;
                    319: {
                    320: /* Check the file type; allocate a buffer. */
                    321:    struct stat statbuf;
                    322:    int tmp;
                    323: 
                    324:    if (fstat(fd, &statbuf) < 0)
                    325:       _error ("Can't stat\n", 1);
                    326: /*
                    327:    Some possible file types (from fab.h):
                    328: 
                    329:    rat: FTN - 0      rfm: UDF   0  undefined
                    330:         CR  - 1           FIX   1
                    331:         PRN - 2           VAR   2  default type
                    332:         BLK - 3           VFC   3
                    333:                           STM   4
                    334:                           STMLF 5
                    335:                           STMCR 6
                    336: Also, st_size == 0 seems to indicate a non-file device (mailbox, terminal).
                    337: */
                    338:    if (statbuf.st_fab_rfm == 5 || statbuf.st_fab_rfm == 0
                    339:                                         || statbuf.st_size == 0)
                    340:       fdints[fd].type = 1;  /* Use 'C' rtl routines directly */
                    341:    else
                    342:       fdints[fd].type = 2;  /* Use these routines. */
                    343: 
                    344: /* Get a buffer for our buffered I/O */
                    345:    fdbufs[fd] = malloc (BUFSIZE);
                    346: 
                    347: /* Get an array to use for seeking (initial guess). */
                    348:    tmp = (statbuf.st_size + BUFSIZE)/BUFSIZE * sizeof(seeks) + sizeof(seeks);
                    349:    fdseeks[fd] = (void *)malloc (tmp);
                    350:    fdints[fd].maxbin = tmp/sizeof(seeks);
                    351: 
                    352: /* Fill in the 0'th (first) seeks triplet. */
                    353:    fdseeks[fd][0].loc    = 0;
                    354:    fdseeks[fd][0].bstart = 0;
                    355:    fdseeks[fd][0].bend   = 0;
                    356: }
                    357: 
                    358: #include <descrip.h>
                    359: static _error (string, leave)
                    360: char *string;
                    361: int leave;
                    362: {
                    363:    char errstr[81];
                    364:    $DESCRIPTOR(errdesc,errstr);
                    365:    short int length;
                    366: 
                    367:    perror (string);
                    368:    if (errno == EVMSERR) {
                    369:       if (SYS$GETMSG(vaxc$errno, &length, &errdesc, 1, 0) == 1) {
                    370:           errstr[length] = '\0';
                    371:           fprintf (stderr, "%s\n", errstr);
                    372:       }
                    373:    }
                    374:    if (leave)
                    375:       exit (44);  /* SS_ABORT */
                    376: }
                    377: #include <ssdef>
                    378: #include <iodef>
                    379: #include <rms>
                    380: #include <fibdef>
                    381: #include <atrdef>
                    382: 
                    383: /* Simply need a trick to hide a global called 'delete' elsewhere. */
                    384: vms_delete (file)
                    385: char *file;
                    386: {
                    387:    delete (file);
                    388: }
                    389: 
                    390: /* Pipe routines modified from Chris Janton's (chj) VMS Icon port. */
                    391: /*
                    392:    Here we fudge to help the "elvis" program implement rpipe.  The
                    393:    routine essentially does an popen using fd as stdin--except that
                    394:    few VMS utilities use the 'C' library.  So we pass in the standard
                    395:    input file name and use it if fd is non-zero.
                    396: */
                    397: #include <dvidef>
                    398: #include <file>
                    399: 
                    400: typedef struct _descr {
                    401:    int length;
                    402:    char *ptr;
                    403: } descriptor;
                    404: 
                    405: typedef struct _pipe {
                    406:    long pid;                    /* process id of child */
                    407:    long status;                 /* exit status of child */
                    408:    long flags;                  /* LIB$SPAWN flags */
                    409:    int ichan;                 /* MBX channel number */
                    410:    int ochan;
                    411:    int efn;
                    412:    unsigned running : 1;        /* 1 if child is running */
                    413: } Pipe;
                    414: 
                    415: Pipe _pipes[_NFILE];            /* one for every open file */
                    416: 
                    417: #define NOWAIT          1
                    418: #define NOCLISYM        2
                    419: #define NOLOGNAM        4
                    420: #define NOKEYPAD        8
                    421: #define NOTIFY          16
                    422: #define NOCONTROL       32
                    423: #define SFLAGS  (NOWAIT|NOKEYPAD|NOCONTROL)
                    424: 
                    425: int vms_rpipe (cmd, fd, input_file)
                    426: char *cmd, *input_file;
                    427: int fd;
                    428: {
                    429:    int pfile;                   /* the Pfile */
                    430:    Pipe *pd;                    /* _pipe database */
                    431:    descriptor inmbxname;        /* name of input mailbox */
                    432:    descriptor outmbxname;          /* name of mailbox */
                    433:    char inmname[65];
                    434:    char outmname[65];              /* mailbox name string */
                    435:    int ochan;                    /* mailbox channel number */
                    436:    int ichan;                  /* Input mailbox channel number */
                    437:    int status;                  /* system service status */
                    438:    int efn;
                    439:    struct {
                    440:       short len;
                    441:       short code;
                    442:       char *address;
                    443:       char *retlen;
                    444:       int last;
                    445:    } itmlst;
                    446: 
                    447:    if (!cmd || cmd[0] == '\0')
                    448:       return (-1);
                    449:    LIB$GET_EF(&efn);
                    450:    if (efn == -1)
                    451:       return (-1);
                    452: 
                    453:    /* create and open the input mailbox */
                    454:    status = SYS$CREMBX(0, &ichan, 0, 0, 0, 0, 0);
                    455:    if (!(status & 1)) {
                    456:       LIB$FREE_EF(&efn);
                    457:       return (-1);
                    458:    }
                    459:    itmlst.last = inmbxname.length = 0;
                    460:    itmlst.address = inmbxname.ptr = inmname;
                    461:    itmlst.retlen = &inmbxname.length;
                    462:    itmlst.code = DVI$_DEVNAM;
                    463:    itmlst.len = 64;
                    464:    status = SYS$GETDVIW(0, ichan, 0, &itmlst, 0, 0, 0, 0);
                    465:    if (!(status & 1)) {
                    466:       LIB$FREE_EF(&efn);
                    467:       return (-1);
                    468:    }
                    469:    inmname[inmbxname.length] = '\0';
                    470: 
                    471:    /* create and open the output mailbox */
                    472:    status = SYS$CREMBX(0, &ochan, 0, 0, 0, 0, 0);
                    473:    if (!(status & 1)) {
                    474:       LIB$FREE_EF(&efn);
                    475:       return (-1);
                    476:    }
                    477:    itmlst.last = outmbxname.length = 0;
                    478:    itmlst.address = outmbxname.ptr = outmname;
                    479:    itmlst.retlen = &outmbxname.length;
                    480:    status = SYS$GETDVIW(0, ochan, 0, &itmlst, 0, 0, 0, 0);
                    481:    if (!(status & 1)) {
                    482:       LIB$FREE_EF(&efn);
                    483:       return (-1);
                    484:    }
                    485:    outmname[outmbxname.length] = '\0';
                    486:    pfile = open(outmname, O_RDONLY);
                    487:    if (pfile < 0) {
                    488:       LIB$FREE_EF(&efn);
                    489:       SYS$DASSGN(ichan);
                    490:       SYS$DASSGN(ochan);
                    491:       return (-1);
                    492:    }
                    493:    /* Save file information now */
                    494:    pd = &_pipes[pfile]; /* get Pipe pointer */
                    495:    pd->pid = pd->status = pd->running = 0;
                    496:    pd->flags = SFLAGS;
                    497:    pd->ichan = ichan;
                    498:    pd->ochan = ochan;
                    499:    pd->efn = efn;
                    500: 
                    501:    /* Initiate the command by writing down the input mailbox (SYS$INPUT). */
                    502:    if (fd > 0) {
                    503:       char *pre_command[132+12];
                    504:       strcpy (pre_command, "DEFINE/USER SYS$INPUT ");
                    505:       strcat (pre_command, input_file);
                    506:       status = sys$qiow(0, ichan, IO$_WRITEVBLK | IO$M_NOW, 0, 0, 0,
                    507:                         pre_command, strlen(pre_command), 0, 0, 0, 0);
                    508:       if (!(status & 1)) {
                    509:          LIB$FREE_EF(&efn);
                    510:          SYS$DASSGN(ichan);
                    511:          SYS$DASSGN(ochan);
                    512:          return (-1);
                    513:       }
                    514:    }
                    515:    status = sys$qiow(0, ichan, IO$_WRITEVBLK | IO$M_NOW,
                    516:                                 0, 0, 0, cmd, strlen(cmd), 0, 0, 0, 0);
                    517:    if (!(status & 1)) {
                    518:       LIB$FREE_EF(&efn);
                    519:       SYS$DASSGN(ichan);
                    520:       SYS$DASSGN(ochan);
                    521:       return (-1);
                    522:    }
                    523:    status = sys$qiow(0, ichan, IO$_WRITEOF | IO$M_NOW, 0, 0, 0,
                    524:                                                           0, 0, 0, 0, 0, 0);
                    525:    if (!(status & 1)) {
                    526:       LIB$FREE_EF(&efn);
                    527:       SYS$DASSGN(ichan);
                    528:       SYS$DASSGN(ochan);
                    529:       return (-1);
                    530:    }
                    531: 
                    532:    status = LIB$SPAWN(0,
                    533:       &inmbxname,                          /* input file */
                    534:       &outmbxname,                         /* output file */
                    535:       &pd->flags, 0, &pd->pid, &pd->status, &pd->efn, 0, 0, 0, 0);
                    536:    if (!(status & 1)) {
                    537:       LIB$FREE_EF(&efn);
                    538:       SYS$DASSGN(ichan);
                    539:       SYS$DASSGN(ochan);
                    540:       return (-1);
                    541:    } else {
                    542:       pd->running = 1;
                    543:    }
                    544:    return (pfile);
                    545: }
                    546: 
                    547: int vms_pread (pfile, buffer, size)
                    548: int pfile, size;
                    549: char *buffer;
                    550: /* Be compatible when we read data in (handle newlines). */
                    551: {
                    552:    Pipe *pd;
                    553:    int status, request;
                    554:    struct {
                    555:       short  status,
                    556:              count;
                    557:       int       :16;
                    558:    } iosb;
                    559: 
                    560:    pd = pfile >= 0 ? &_pipes[pfile] : 0;
                    561:    if (pd == NULL) return -1;
                    562: 
                    563: /*
                    564:    This is sort of nasty.  The default mailbox size is 256 maxmsg
                    565:    and 1056 bufquo if your sysgen parameters are standard.  Asking
                    566:    for more on the CREMBX command (in rpipe) might be a bad idea as
                    567:    that could cause an "exceeded quota" error.  Since we only return
                    568:    -1 on error, there's no hope that the poor user would ever know
                    569:    what went wrong.
                    570: */
                    571:    request = size > 256 ? 256 : size - 1;
                    572:    status = sys$qiow(0, pd->ochan, IO$_READVBLK, &iosb, 0, 0,
                    573:                                       buffer, request, 0, 0, 0, 0);
                    574:    if (!(status & 1)) return -1;
                    575:    if (iosb.status == SS$_ENDOFFILE)
                    576:       return 0;
                    577:    buffer[iosb.count] = '\n';
                    578:    return iosb.count+1;
                    579: }
                    580: 
                    581: /*
                    582:  * Taken from pclose - close a pipe
                    583:  * Last modified 2-Apr-86/chj
                    584:  *
                    585:  */
                    586: int vms_rpclose(pfile)
                    587: int pfile;
                    588: {
                    589:    Pipe *pd;
                    590:    int status;
                    591:    int fstatus;
                    592: 
                    593:    pd = pfile >= 0 ? &_pipes[pfile] : 0;
                    594:    if (pd == NULL)
                    595:       return (-1);
                    596:    fstatus = close(pfile);
                    597:    SYS$DASSGN(pd->ichan);
                    598:    SYS$DASSGN(pd->ochan);
                    599:    LIB$FREE_EF(&pd->efn);
                    600:    pd->running = 0;
                    601:    return (fstatus);
                    602: }
                    603: 
                    604: /* Terminal routines. */
                    605: 
                    606: static int tty;
                    607: static int VMS_term_chan;
                    608: int VMS_read_raw;   /* Set by curses.c in elvis. */
                    609: 
                    610: #define VMSCheck(a) {int _s; if (~(_s = (a)) & 1) vms_sys$exit (_s);}
                    611: 
                    612: vms_open_tty()
                    613: {
                    614:    int c;
                    615: 
                    616:    $DESCRIPTOR(_terminal,"SYS$INPUT");
                    617:    if (VMS_term_chan == 0) {
                    618:       VMSCheck(SYS$ASSIGN (&_terminal, &VMS_term_chan, 0, 0));
                    619:    }
                    620: /* Was 2 -- jdc */
                    621:    tty = 0;
                    622: 
                    623: /* Could reset the scrolling region, setup LINES, COLS, etc. */
                    624: 
                    625:    read(tty,&c,0);   /* Flush the tty buffer. */
                    626: }
                    627: 
                    628: /*
                    629:  * Get a character from the keyboard.
                    630:  */
                    631: /*ARGSUSED*/
                    632: vms_ttyread(buf, len, time)
                    633:         char *buf;
                    634:         int len;
                    635:         int time;
                    636: {
                    637:         char c;
                    638:         int result, terminat[2] = {0,0};
                    639:    struct {
                    640:       short int status;              /* I/O completion status */
                    641:       short int bcount;              /* byte transfer count   */
                    642:       int dev_dep_data;              /* device dependant data */
                    643:    } iosb;                  /* This is a QIO I/O Status Block */
                    644: 
                    645: 
                    646:    if (VMS_read_raw) {
                    647: /*      read(tty,&c,0);  */ /* Flush the tty buffer. (needed?) */
                    648:       if (time == 0) {
                    649:          VMSCheck(sys$qiow(0, VMS_term_chan,
                    650:            IO$_READVBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TRMNOECHO,
                    651:                  &iosb, 0, 0, buf, 1, 0, terminat, 0, 0));
                    652:       }
                    653:       else {
                    654:          VMSCheck(sys$qiow(0, VMS_term_chan,
                    655:         IO$_READVBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TRMNOECHO | IO$M_TIMED,
                    656:                  &iosb, 0, 0, buf, 1, time, terminat, 0, 0));
                    657:       }
                    658:       if (iosb.status == SS$_ENDOFFILE)
                    659:          vms_sys$exit(SS$_ABORT);
                    660:       else if (iosb.status == SS$_TIMEOUT)
                    661:          return 0; /* Timeout */
                    662:       return 1;  /* iosb.bcount; */
                    663:    }
                    664:    else {
                    665: /* I don't believe we ever use ttyread to read in non-raw mode... */
                    666: #undef read
                    667:       return read (0, buf, len);
                    668:    }
                    669: }
                    670: 
                    671: vms_sys$exit(val)
                    672: {
                    673:    sys$exit(val);   /* Debugger entry point. */
                    674: }

unix.superglobalmegacorp.com

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