home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************
- * *
- * Copyright (C) 1992 Igor Mandrichenko. *
- * Permission is granted to any individual or institution to use, copy, *
- * or redistribute this software so long as all of the original files *
- * are included unmodified, that it is not sold for profit, and that *
- * this copyright notice is retained. *
- * *
- *************************************************************************/
-
- /*
- * vms.c by Igor Mandrichenko
- * version 1.1-2
- *
- * This module contains routines to extract VMS file attributes
- * from extra field and create file with these attributes. This
- * source is mainly based on sources of file_io.c from UNZIP 4.1
- * by Info-ZIP. [Info-ZIP note: very little of this code is from
- * file_io.c; it has virtually been written from the ground up.
- * Of the few lines which are from the older code, most are mine
- * (G. Roelofs) and I make no claims upon them. On the contrary,
- * my/our thanks to Igor for his contributions!]
- */
-
- /*
- * Revision history:
- * 1.0-1 Mandrichenko 16-feb-1992
- * Recognize -c option
- * 1.0-2 Mandrichenko 17-feb-1992
- * Do not use ASYnchroneous mode.
- * 1.0-3 Mandrichenko 2-mar-1992
- * Make code more standard
- * Use lrec instead of crec -- unzip4.2p do not provide
- * crec now.
- * 1.1 Mandrichenko 5-mar-1992
- * Make use of asynchronous output.
- * Be ready to extract RMS blocks of invalid size (because diff
- * VMS version used to compress).
- * 1.1-1 Mandrichenko 11-mar-1992
- * Use internal file attributes saved in pInfo to decide
- * if the file is text. [GRR: temporarily disabled, since
- * no way to override and force binary extraction]
- * 1.1-2 Mandrichenko 13-mar-1992
- * Do not restore owner/protection info if -X not specified.
- */
-
- #ifdef VMS /* VMS only ! */
-
- /************************************/
- /* File_IO Includes, Defines, etc. */
- /************************************/
-
- #ifdef VAXC
- #include rms
- #include descrip
- #include syidef
- #else
- #include <rms.h>
- #include <descrip.h>
- #include <syidef.h>
- #endif
-
- #include "unzip.h"
-
- #define ERR(s) !((s) & 1)
-
- #define BUFS512 8192*2 /* Must be a multiple of 512 */
-
- static int WriteBuffer __((int fd, unsigned char *buf, int len));
- static int _flush_blocks __((void));
- static int _flush_records __((void));
- static byte *extract_block __((byte *));
-
- /*
- * Local static storage
- */
- static struct FAB *outfab = 0;
- static struct RAB *outrab = 0;
- static struct FAB fileblk;
- static struct XABFHC *xabfhc = 0;
- static struct XABDAT dattim, *xabdat = 0;
- static struct XABRDT *xabrdt = 0;
- static struct XABPRO *xabpro = 0;
- static struct XABKEY *xabkey = 0;
- static struct XABALL *xaball = 0;
- static struct RAB rab;
-
- static int text_file = 0;
-
- static char locbuf[BUFS512];
- static int loccnt = 0;
- static char *locptr;
-
-
- struct bufdsc
- { struct bufdsc *next;
- byte *buf;
- int bufcnt;
- };
-
- static struct bufdsc b1,b2,*curbuf;
- static byte buf1[BUFS512],buf2[BUFS512];
-
- int create_output_file()
- { /* return non-0 if sys$create failed */
- int ierr, yr, mo, dy, hh, mm, ss;
- char timbuf[24]; /* length = first entry in "stupid" + 1 */
- int attr_given = 0; /* =1 if VMS attributes are present in
- * extra_field */
-
- rab = cc$rms_rab; /* fill FAB & RAB with default values */
- fileblk = cc$rms_fab;
-
- text_file = /* pInfo->text || */ aflag || cflag;
-
- if (attr_given = find_vms_attrs())
- { text_file = 0;
- if( cflag )
- { printf("Can not put VMS file %s to stdout.\n",
- filename);
- return 50;
- }
- }
-
- if (!attr_given)
- {
- outfab = &fileblk;
- outfab->fab$l_xab = 0L;
- if (text_file)
- {
- outfab->fab$b_rfm = FAB$C_VAR; /* variable length records */
- outfab->fab$b_rat = FAB$M_CR; /* carriage-return carriage ctrl */
- }
- else
- {
- outfab->fab$b_rfm = FAB$C_STMLF; /* stream-LF record format */
- outfab->fab$b_rat = FAB$M_CR; /* carriage-return carriage ctrl */
- }
- }
-
- if(!cflag)
- outfab->fab$l_fna = filename;
- else
- outfab->fab$l_fna = "sys$output:";
-
- outfab->fab$b_fns = strlen(outfab->fab$l_fna);
-
- if (!attr_given || xabdat == 0)
- {
- static char *month[] =
- {"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
- "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
- /* fixed-length string descriptor (why not just a pointer to timbuf? sigh.) */
- struct dsc$descriptor stupid =
- {23, DSC$K_DTYPE_T, DSC$K_CLASS_S, timbuf};
-
- yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980; /* dissect date */
- mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
- dy = (lrec.last_mod_file_date & 0x1f);
- hh = (lrec.last_mod_file_time >> 11) & 0x1f; /* dissect time */
- mm = (lrec.last_mod_file_time >> 5) & 0x3f;
- ss = (lrec.last_mod_file_time & 0x1f) * 2;
-
- dattim = cc$rms_xabdat; /* fill XAB with default values */
- dattim.xab$l_nxt = outfab->fab$l_xab;
- outfab->fab$l_xab = (char*)(xabdat = &dattim);
-
- sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", dy, month[mo], yr,
- hh, mm, ss);
- sys$bintim(&stupid, &dattim.xab$q_cdt);
- }
-
- #ifdef DEBUG
- printf("XAB chain before CREATE dump:\n");
- dump_rms_block(outfab);
- {
- struct XABALL *x;
- for (x = outfab->fab$l_xab; x != 0L; x = x->xab$l_nxt)
- dump_rms_block(x);
- }
- #endif
-
- outfab->fab$w_ifi = 0; /* Clear IFI. It may be nonzero after ZIP */
-
- if ((ierr = sys$create(outfab)) != RMS$_NORMAL)
- {
- message("[ can not create output file ]\n", ierr);
- message("", outfab->fab$l_stv);
- fprintf(stderr, "Can't create output file: %s\n", filename);
- return (1);
- }
-
- if (!text_file && !cflag) /* Do not reopen text files and stdout
- * Just open them in right mode */
- {
- /*
- * Reopen file for Block I/O with no XABs.
- */
- if ((ierr = sys$close(outfab)) != RMS$_NORMAL)
- {
- #ifdef DEBUG
- message("[ create_output_file: sys$close failed ]\n", ierr);
- message("", outfab->fab$l_stv);
- #endif
- fprintf(stderr, "Can't create output file: %s\n", filename);
- return (1);
- }
-
-
- outfab->fab$b_fac = FAB$M_BIO | FAB$M_PUT; /* Get ready for block
- * output */
- outfab->fab$l_xab = 0L; /* Unlink all XABs */
-
- if ((ierr = sys$open(outfab)) != RMS$_NORMAL)
- {
- message("[ Can not open output file ]\n", ierr);
- message("", outfab->fab$l_stv);
- return (1);
- }
- }
-
- outrab = &rab;
- rab.rab$l_fab = outfab;
- if( !text_file ) rab.rab$l_rop |= RAB$M_BIO;
- if( !text_file ) rab.rab$l_rop |= RAB$M_ASY;
- rab.rab$b_rac = RAB$C_SEQ;
-
- if ((ierr = sys$connect(outrab)) != RMS$_NORMAL)
- {
- #ifdef DEBUG
- fprintf(stderr, "create_output_file: sys$connect failed on file %s\n",
- filename);
- fprintf(stderr, " status = %d\n", ierr);
- fprintf(stderr, " fab.sts = %d\n", outfab->fab$l_sts);
- fprintf(stderr, " fab.stv = %d\n", outfab->fab$l_stv);
- #endif
- fprintf(stderr, "Can't create output file: %s\n", filename);
- return (1);
- }
-
- locptr = &locbuf[0];
- loccnt = 0;
-
- b1.buf = &buf1[0];
- b1.bufcnt = 0;
- b1.next = &b2;
- b2.buf = &buf2[0];
- b2.bufcnt = 0;
- b2.next = &b1;
- curbuf = &b1;
-
- return (0);
- }
-
- /*
- * Extra record format
- * ===================
- * signature (2 bytes) = 'I','M'
- * size (2 bytes)
- * block signature (4 bytes)
- * flags (2 bytes)
- * uncomprssed size(2 bytes)
- * reserved (4 bytes)
- * data ((size-12) bytes)
- * ....
- */
-
- struct extra_block
- {
- UWORD sig; /* Extra field block header structure */
- UWORD size;
- ULONG bid;
- UWORD flags;
- UWORD length;
- ULONG reserved;
- byte body[1];
- };
-
- /*
- * Extra field signature and block signatures
- */
-
- #define SIGNATURE "IM"
- #define FABL (cc$rms_fab.fab$b_bln)
- #define RABL (cc$rms_rab.rab$b_bln)
- #define XALLL (cc$rms_xaball.xab$b_bln)
- #define XDATL (cc$rms_xabdat.xab$b_bln)
- #define XFHCL (cc$rms_xabfhc.xab$b_bln)
- #define XKEYL (cc$rms_xabkey.xab$b_bln)
- #define XPROL (cc$rms_xabpro.xab$b_bln)
- #define XRDTL (cc$rms_xabrdt.xab$b_bln)
- #define XSUML (cc$rms_xabsum.xab$b_bln)
- #define EXTBSL 4 /* Block signature length */
- #define RESL 8 /* Rserved 8 bytes */
- #define EXTHL (4+EXTBSL)
- #define FABSIG "VFAB"
- #define XALLSIG "VALL"
- #define XFHCSIG "VFHC"
- #define XDATSIG "VDAT"
- #define XRDTSIG "VRDT"
- #define XPROSIG "VPRO"
- #define XKEYSIG "VKEY"
- #define XNAMSIG "VNAM"
- #define VERSIG "VMSV"
-
-
-
- #define W(p) (*(unsigned short*)(p))
- #define L(p) (*(unsigned long*)(p))
- #define EQL_L(a,b) ( L(a) == L(b) )
- #define EQL_W(a,b) ( W(a) == W(b) )
-
- /****************************************************************
- * Function find_vms_attrs scans ZIP entry extra field if any *
- * and looks for VMS attribute records. Returns 0 if either no *
- * attributes found or no fab given. *
- ****************************************************************/
- int find_vms_attrs()
- {
- byte *scan = extra_field;
- struct extra_block *blk;
- struct XABALL *first_xab = 0L, *last_xab = 0L;
- int len;
-
- outfab = xabfhc = xabdat = xabrdt = xabpro = 0L;
-
- if (scan == NULL)
- return 0;
- /*
- if (crec.extra_field_length)
- len = crec.extra_field_length;
- else
- */
- len = lrec.extra_field_length;
-
- #define LINK(p) { \
- if( first_xab == 0L ) \
- first_xab = p; \
- if( last_xab != 0L ) \
- last_xab -> xab$l_nxt = p; \
- last_xab = p; \
- p -> xab$l_nxt = 0; \
- }
- /* End of macro LINK */
-
- while (len > 0)
- {
- blk = (struct block *)scan;
- if (EQL_W(&blk->sig, SIGNATURE))
- {
- byte *block_id;
- block_id = &blk->bid;
- if (EQL_L(block_id, FABSIG))
- {
- outfab = (struct FAB *) extract_block(blk, 0,
- &cc$rms_fab, FABL);
- }
- else if (EQL_L(block_id, XALLSIG))
- {
- xaball = (struct XABALL *) extract_block(blk, 0,
- &cc$rms_xaball, XALLL);
- LINK(xaball);
- }
- else if (EQL_L(block_id, XKEYSIG))
- {
- xabkey = (struct XABKEY *) extract_block(blk, 0,
- &cc$rms_xabkey, XKEYL);
- LINK(xabkey);
- }
- else if (EQL_L(block_id, XFHCSIG))
- {
- xabfhc = (struct XABFHC *) extract_block(blk, 0,
- &cc$rms_xabfhc, XFHCL);
- LINK(xabfhc);
- }
- else if (EQL_L(block_id, XDATSIG))
- {
- xabdat = (struct XABDAT *) extract_block(blk, 0,
- &cc$rms_xabdat, XDATL);
- LINK(xabdat);
- }
- else if (EQL_L(block_id, XRDTSIG))
- {
- xabrdt = (struct XABRDT *) extract_block(blk, 0,
- &cc$rms_xabrdt, XRDTL);
- /* LINK(xabrdt); -- Do not link xabrdt */
- }
- else if (EQL_L(block_id, XPROSIG))
- {
- xabpro = (struct XABPRO *) extract_block(blk, 0,
- &cc$rms_xabpro, XPROL);
- /* LINK(xabpro); -- Do not link xabpro
- until close */
- }
- else if (EQL_L(block_id, VERSIG))
- {
- char verbuf[80];
- int verlen = 0;
- int vl = 0;
- int item = SYI$_VERSION;
- $DESCRIPTOR(version, verbuf);
- byte *vers;
-
- lib$getsyi(&item, 0, &version, &verlen, 0, 0);
- verbuf[verlen] = 0;
- vers = extract_block(blk, &vl, 0, 0);
- if (strncmp(verbuf, vers, verlen))
- {
- printf("[ Warning: VMS version mismatch.");
-
- printf(" This version %s --", verbuf);
- strncpy(verbuf, vers, vl);
- verbuf[vl] = 0;
- printf(" version made by %s ]\n", verbuf);
- }
- free(vers);
- }
- else
- fprintf(stderr, "[ Warning: Unknown block signature %s ]\n",
- block_id);
- }
- len -= blk->size + 4;
- scan += blk->size + 4;
- }
- if (outfab != 0)
- {
- outfab->fab$l_xab = first_xab;
- return 1;
- }
- else
- return 0;
- }
-
- /******************************
- * Function extract_block *
- ******************************/
- /*
- * Simple uncompression routne. The compression uses bit stream.
- * Compression scheme:
- *
- * if(byte!=0)
- * putbit(1),putyte(byte)
- * else
- * putbit(0)
- */
- static byte *extract_block(p, retlen, init, needlen)
- int *retlen;
- struct extra_block *p;
- byte *init;
- int needlen;
- {
- byte *block; /* Pointer to block allocated */
- byte *bitptr; /* Pointer into compressed data */
- byte *outptr; /* Pointer into output block */
- UWORD length;
- ULONG bitbuf = 0;
- int bitcnt = 0;
-
- #define _FILL if(bitcnt+8 <= 32) \
- { bitbuf |= (*bitptr++) << bitcnt;\
- bitcnt += 8; \
- }
-
-
- if( p->flags & 1 )
- length = p->length; /* Block is compressed */
- else
- length = p->size - EXTBSL - RESL; /* Simple case, uncompressed */
-
- if( needlen == 0 )
- needlen = length;
-
- if(retlen)
- *retlen = needlen;
-
- if( (p->flags & 1) || (needlen > length) )
- { if ((block = (byte*)malloc(needlen)) == NULL)
- return NULL;
- }
- /*
- else if( needlen > length )
- { if ((block = (byte*)malloc(needlen)) == NULL)
- return NULL;
- }
- */
- else outptr = block = &p->body[0];
-
- if(init && (length < needlen))
- memcpy(block,init,needlen);
-
- if ((p->flags & 1) == 0)
- return block; /* Do nothing more if uncompressed */
-
- outptr = block;
- bitptr = &p->body[0];
-
- if(length > needlen)
- length = needlen;
-
- while (length--)
- {
- if (bitcnt <= 0)
- _FILL;
-
- if (bitbuf & 1)
- {
- bitbuf >>= 1;
- if ((bitcnt -= 1) < 8)
- _FILL;
- *outptr++ = (byte) bitbuf;
- bitcnt -= 8;
- bitbuf >>= 8;
- }
- else
- {
- *outptr++ = 0;
- bitcnt -= 1;
- bitbuf >>= 1;
- }
- }
- return block;
- }
-
- /***************************/
- /* Function FlushOutput() */
- /***************************/
-
- int FlushOutput()
- { /* return PK-type error code */
- /* flush contents of output buffer */
- if (tflag)
- { /* Do not output. Update CRC only */
- UpdateCRC(outbuf, outcnt);
- outpos += outcnt;
- outcnt = 0;
- outptr = outbuf;
- return 0;
- }
- else
- return text_file ? _flush_records(0) : _flush_blocks(0);
- }
-
- static int _flush_blocks(final_flag) /* Asynchronous version */
- int final_flag;
- /* 1 if this is the final flushout */
- {
- int round;
- int rest;
- int off = 0;
- int out_count = outcnt;
- int status;
-
- while(out_count > 0)
- { if( curbuf -> bufcnt < BUFS512 )
- { int ncpy;
- ncpy = out_count > (BUFS512-curbuf->bufcnt) ?
- BUFS512-curbuf->bufcnt :
- out_count;
- memcpy(curbuf->buf + curbuf->bufcnt, outbuf+off, ncpy);
- out_count -= ncpy;
- curbuf -> bufcnt += ncpy;
- off += ncpy;
- }
- if( curbuf -> bufcnt == BUFS512 )
- {
- status = WriteBuffer(curbuf->buf,curbuf->bufcnt);
- if(status)
- return status;
- curbuf = curbuf -> next;
- curbuf -> bufcnt = 0;
- }
- }
-
- UpdateCRC(outbuf, outcnt);
- outpos += outcnt;
- outcnt = 0;
- outptr = outbuf;
-
- return (final_flag && (curbuf->bufcnt > 0)) ?
- WriteBuffer(curbuf->buf,curbuf->bufcnt) :
- 0; /* 0: no error */
- }
-
- #define RECORD_END(c) ((c) == CR || (c) == LF)
-
- static int _flush_records(final_flag)
- int final_flag;
- /* 1 if this is the final flushout */
- {
- int rest;
- int end = 0, start = 0;
- int off = 0;
-
- if (outcnt == 0 && loccnt == 0)
- return 0; /* Nothing to do ... */
-
- if (loccnt)
- {
- for (end = 0; end < outcnt && !RECORD_END(outbuf[end]);)
- ++end;
- if (end >= outcnt)
- {
- fprintf(stderr, "[ Warning: Record too long (%d) ]\n",
- outcnt + loccnt);
- if (WriteRecord(locbuf, loccnt))
- return (50);
- memcpy(locbuf, outbuf, outcnt);
- locptr = &locbuf[loccnt = outcnt];
- }
- else
- {
- memcpy(locptr, outbuf, end);
- if (WriteRecord(locbuf, loccnt + end))
- return (50);
- loccnt = 0;
- locptr = &locbuf;
- }
- start = end + 1;
- }
-
- do
- {
- while (start < outcnt && outbuf[start] == CR) /* Skip CR's at the
- * beginning of rec. */
- ++start;
- /* Find record end */
- for (end = start; end < outcnt && !RECORD_END(outbuf[end]);)
- ++end;
-
- if (end < outcnt)
- { /* Record end found, write the record */
- if (WriteRecord(outbuf + start, end - start))
- return (50);
- /* Shift to the begining of the next record */
- start = end + 1;
- }
- } while (start < outcnt && end < outcnt);
-
- rest = outcnt - start;
-
- if (rest > 0)
- if (final_flag)
- {
- /* This is a final flush. Put out all remaining in
- * the buffer */
- if (loccnt && WriteRecord(locbuf, loccnt))
- return (50);
- }
- else
- {
- memcpy(locptr, outbuf + start, rest);
- locptr += rest;
- loccnt += rest;
- }
- UpdateCRC(outbuf, outcnt);
- outpos += outcnt;
- outcnt = 0;
- outptr = outbuf;
- return (0); /* 0: no error */
- }
-
- /***************************/
- /* Function WriteBuffer() */
- /***************************/
-
- static int WriteBuffer(buf, len)/* return 0 if successful, 1 if not */
- unsigned char *buf;
- int len;
- {
- int status;
-
- status = sys$wait(outrab);
- #ifdef DEBUG
- if(ERR(status))
- { message("[ Write buffer: sys$wait faled ]\n",status);
- message("",outrab->rab$l_sts);
- message("",outrab->rab$l_sts);
- }
- #endif
- outrab->rab$w_rsz = len;
- outrab->rab$l_rbf = buf;
-
- if (ERR(status = sys$write(outrab)))
- {
- fprintf(stderr, "WriteBuffer: sys$write failed.\n",
- filename);
- fprintf(stderr, " status = %d\n", status);
- fprintf(stderr, " rab->sts = %d\n", outrab->rab$l_sts);
- fprintf(stderr, " stv = %d\n", outrab->rab$l_stv);
- return 50;
- }
- return (0);
- }
-
- /***************************/
- /* Function WriteRecord() */
- /***************************/
-
- static int WriteRecord(rec, len)/* return 0 if successful, 1 if not */
- unsigned char *rec;
- int len;
- {
- int status;
-
- sys$wait(outrab);
- #ifdef DEBUG
- if(ERR(status))
- { message("[ Write buffer: sys$wait faled ]\n",status);
- message("",outrab->rab$l_sts);
- message("",outrab->rab$l_sts);
- }
- #endif
- outrab->rab$w_rsz = len;
- outrab->rab$l_rbf = rec;
-
- if (ERR(status = sys$put(outrab)))
- {
- fprintf(stderr, "WriteRecord: sys$put failed.\n",
- filename);
- fprintf(stderr, " status = %d\n", status);
- fprintf(stderr, " rab->sts = %d\n", outrab->rab$l_sts);
- fprintf(stderr, " stv = %d\n", outrab->rab$l_stv);
- return 50;
- }
- return (0);
- }
-
- /********************************/
- /* Function CloseOutputFile() */
- /********************************/
-
- int CloseOutputFile()
- {
- int status;
-
- if (text_file) _flush_records(1);
- else
- _flush_blocks(1);
-
- if ((outfab->fab$l_xab = xabrdt) != 0L) /* Link XABPRO and XABRDT */
- xabrdt->xab$l_nxt = (secinf ? xabpro : 0L);
- else
- outfab->fab$l_xab = (secinf ? xabpro : 0L);
-
- sys$wait(outrab);
-
- status = sys$close(outfab);
- #ifdef DEBUG
- if (ERR(status))
- {
- message("\r[ Warning: can not set owner/protection/time attributes ]\n", status);
- message("", outfab->fab$l_stv);
- }
- #endif
- }
-
- #ifdef DEBUG
- dump_rms_block(p)
- unsigned char *p;
- {
- unsigned char bid, len;
- int err;
- char *type;
- char buf[132];
- int i;
-
- err = 0;
- bid = p[0];
- len = p[1];
- switch (bid)
- {
- case FAB$C_BID:
- type = "FAB";
- break;
- case XAB$C_ALL:
- type = "xabALL";
- break;
- case XAB$C_KEY:
- type = "xabKEY";
- break;
- case XAB$C_DAT:
- type = "xabDAT";
- break;
- case XAB$C_RDT:
- type = "xabRDT";
- break;
- case XAB$C_FHC:
- type = "xabFHC";
- break;
- case XAB$C_PRO:
- type = "xabPRO";
- break;
- default:
- type = "Unknown";
- err = 1;
- break;
- }
- printf("Block @%08X of type %s (%d).", p, type, bid);
- if (err)
- {
- printf("\n");
- return;
- }
- printf(" Size = %d\n", len);
- printf(" Offset - Hex - Dec\n");
- for (i = 0; i < len; i += 8)
- {
- int j;
- printf("%3d - ", i);
- for (j = 0; j < 8; j++)
- if (i + j < len)
- printf("%02X ", p[i + j]);
- else
- printf(" ");
- printf(" - ");
- for (j = 0; j < 8; j++)
- if (i + j < len)
- printf("%03d ", p[i + j]);
- else
- printf(" ");
- printf("\n");
- }
- }
-
- #endif /* DEBUG */
-
- message(string, status)
- int status;
- char *string;
- {
- char msgbuf[256];
- $DESCRIPTOR(msgd, msgbuf);
- int msglen = 0;
-
- if (ERR(lib$sys_getmsg(&status, &msglen, &msgd, 0, 0)))
- fprintf(stderr, "%s[ VMS status = %d ]\n", string, status);
- else
- {
- msgbuf[msglen] = 0;
- fprintf(stderr, "%s[ %s ]\n", string, msgbuf);
- }
- }
-
-
- #endif /* !VMS */
-