|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.