Annotation of coherent/g/usr/bin/vi/vmsio.c, revision 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.