[comp.os.vms] INDEX, Part 3 of 5

JOE@FHCRCVAX.BITNET.UUCP (09/13/87)

Here's part 3 of INDEX, part 1 was posted Friday, part 2 Saturday, and
this part on Sunday, the fourth and fifth parts will be posted on monday
and tuesday. See part 1 for details.

  Cheers,
  Joe Meadows Jr.
  VAX/VMS System Manager / guru in training
  Fred Hutchinson Cancer Research Center
  1124 Columbia St.
  Seattle Wa. 98104
     bitnet - JOE@FHCRCVAX
     arpa   - JOE%FHCRCVAX.BITNET@WISCVM.WISC.EDU
     voice  - (206) 467-4970

$ create/log DISPLAYDEF.H
$DECK
/* This header file was created by Joe Meadows, and is not copyrighted
   in any way. No guarantee is made as to the accuracy of the contents
   of this header file. This header file was last modified on Sep. 8th,
   1987. */
struct display_info {
  variant_union {
    variant_struct {
      long int di_l_dsplybits0;
      long int di_l_dsplybits1;
    } si_dummy_dsplybits_struct;
    variant_struct {
      unsigned di_v_credat : 1;
      unsigned di_v_revdat : 1;
      unsigned di_v_expdat : 1;
      unsigned di_v_bakdat : 1;
      unsigned di_v_revision : 1;
      unsigned di_v_extents : 1;
      unsigned di_v_headers : 1;
      unsigned di_v_lbn : 1;
      unsigned di_v_owner : 1;
      unsigned di_v_char : 1;
      unsigned di_v_journal : 1;
      unsigned di_v_prot : 1;
      unsigned di_v_fid : 1;
      unsigned di_v_backlink : 1;
      unsigned di_v_access : 1;
      unsigned di_v_highwater : 1;
      unsigned di_v_ru_active : 1;
      unsigned di_v_rectype : 1;
      unsigned di_v_fileorg : 1;
      unsigned di_v_attrib : 1;
      unsigned di_v_rsize : 1;
      unsigned di_v_alloc : 1;
      unsigned di_v_used : 1;
      unsigned di_v_wasted : 1;
      unsigned di_v_bktsize : 1;
      unsigned di_v_vfcsize : 1;
      unsigned di_v_maxrec : 1;
      unsigned di_v_defext : 1;
      unsigned di_v_gbc : 1;
      unsigned di_v_version_limit : 1;
      unsigned di_v_filename : 1;
      unsigned di_v_fullname : 1;
      unsigned di_v_acl : 1;
    } di_dummy_dsplybits;
  } di_dummy_dsply_union;
};
$EOD
$ create/log FATDEF.H
$DECK
/* This header file was created by Joe Meadows, and is not copyrighted
   in any way. No guarantee is made as to the accuracy of the contents
   of this header file. This header file was last modified on Sep. 8th,
   1987. */
#define FAT$K_LENGTH 32
#define FAT$C_LENGTH 32
#define FAT$S_FATDEF 32

struct FATDEF  {
  variant_union  {
    unsigned char fat$b_rtype;
    variant_struct  {
      unsigned fat$v_rtype : 4;
      unsigned fat$v_fileorg : 4;
    } fat$r_rtype_bits;
  } fat$r_rtype_overlay;
# define FAT$S_RTYPE 4
# define FAT$V_RTYPE 0
#   define FAT$C_UNDEFINED 0
#   define FAT$C_FIXED 1
#   define FAT$C_VARIABLE 2
#   define FAT$C_VFC 3
#   define FAT$C_STREAM 4
#   define FAT$C_STREAMLF 5
#   define FAT$C_STREAMCR 6
# define FAT$S_FILEORG 4
# define FAT$V_FILEORG 4
#   define FAT$C_SEQUENTIAL 0
#   define FAT$C_RELATIVE 1
#   define FAT$C_INDEXED 2
#   define FAT$C_DIRECT 3
  variant_union  {
    unsigned char fat$b_rattrib;
    variant_struct  {
      unsigned fat$v_fortrancc : 1;
      unsigned fat$v_impliedcc : 1;
      unsigned fat$v_printcc : 1;
      unsigned fat$v_nospan : 1;
    } fat$r_rattrib_bits;
  } fat$r_rattrib_overlay;
#   define FAT$V_FORTRANCC 0
#   define FAT$M_FORTRANCC 1
#   define FAT$V_IMPLIEDCC 1
#   define FAT$M_IMPLIEDCC 2
#   define FAT$V_PRINTCC 2
#   define FAT$M_PRINTCC 4
#   define FAT$V_NOSPAN 3
#   define FAT$M_NOSPAN 8
  unsigned short int fat$w_rsize;
  variant_union
  {
    unsigned long int fat$l_hiblk;
    variant_struct
    {
      unsigned short int fat$w_hiblkh;
      unsigned short int fat$w_hiblkl;
    } FATDEF$DUMMY_0;
  } FATDEF$DUMMY_1;
  variant_union
  {
    unsigned long int fat$l_efblk;
    variant_struct
    {
      unsigned short int fat$w_efblkh;
      unsigned short int fat$w_efblkl;
    } FATDEF$DUMMY_2;
  } FATDEF$DUMMY_3;
  unsigned short int fat$w_ffbyte;
  unsigned char fat$b_bktsize;
  unsigned char fat$b_vfcsize;
  unsigned short int fat$w_maxrec;
  unsigned short int fat$w_defext;
  unsigned short int fat$w_gbc;
  char fat$fill[8];
  unsigned short int fat$w_versions;
};
$EOD
$ create/log FID.C
$DECK
/* Modification History
   --------------------
   Sep. 8, 1987 JEM - Conversion from BETA to Release

*/
#include descrip
#include iodef
#include "fibdef.h"
#include "atrdef.h"

int fid_to_name(channel,fid,name)
  short int *channel;
  struct {short int w_fid[3];} *fid;
  struct dsc$descriptor *name;
{
  static struct fibdef Fib; /* short fib */
  static struct dsc$descriptor FibDesc =
    {FIB$K_ACCDATA,DSC$K_DTYPE_Z,DSC$K_CLASS_S,&Fib};
  static struct {
    short int len;
    char buff[ATR$S_FILE_SPEC-2];
  } filespec;
  static struct ATRDEF Atr[] = {
    ATR$S_FILE_SPEC,ATR$C_FILE_SPEC,&filespec,
    0,0,0
    };
  short int iosb[4];
  int status;

  Fib.fib$w_fid[0]=fid->w_fid[0];
  Fib.fib$w_fid[1]=fid->w_fid[1];
  Fib.fib$w_fid[2]=fid->w_fid[2];

  /* Use the IO$_ACCESS function to return info about the file */
  status = sys$qiow(0,*channel,IO$_ACCESS,&iosb,0,0,&FibDesc,0,0,0,&Atr,0);
  if (!(status & 1)) return(status);
  status = iosb[0];
  if (!(status & 1)) return(status);

  status = str$copy_r(name,&filespec.len,&filespec.buff);
  return(status);
}
$EOD
$ create/log FILEINFO.H
$DECK
/* This header file was created by Joe Meadows, and is not copyrighted
   in any way. No guarantee is made as to the accuracy of the contents
   of this header file. This header file was last modified on Sep. 8th,
   1987. */
#include fab
#include nam
#include xab

struct FileInfo {
  long int fi_l_begadr;
  long int fi_l_endadr;
  long int fi_l_offset;
  long int fi_l_pagcnt;
  long int fi_l_recoff;
  long int fi_l_recsiz;
  long int fi_l_blkoff;
  long int fi_l_blksiz;
  long int fi_l_filsiz;
  variant_union {
    long int fi_l_flag;
    variant_struct {
      unsigned fi_m_write : 1;
      unsigned fi_m_append : 1;
      } FileInfo$FlagBits;
    } FileInfo$FlagUnion;
  struct FAB fi_r_fab;
  struct NAM fi_r_nam;
  struct XABFHC fi_r_xabfhc;
};
$EOD
$ create/log FM2DEF.H
$DECK
/* This header file was created by Joe Meadows, and is not copyrighted
   in any way. No guarantee is made as to the accuracy of the contents
   of this header file. This header file was last modified on Sep. 8th,
   1987. */
#define FM2$C_PLACEMENT 0
#define FM2$C_FORMAT1   1
#define FM2$C_FORMAT2   2
#define FM2$C_FORMAT3   3
#define FM2$K_LENGTH0   2
#define FM2$C_LENGTH0   2
#define FM2$K_LENGTH1   4
#define FM2$C_LENGTH1   4
#define FM2$S_FM2DEF    4
#define FM2$K_LENGTH2   6
#define FM2$C_LENGTH2   6
#define FM2$S_FM2DEF1   6
#define FM2$K_LENGTH3   8
#define FM2$C_LENGTH3   8
#define FM2$S_FM2DEF2   8

struct fm2def {
  variant_union {
    unsigned short int fm2$w_word0;
    variant_struct {
      unsigned : 14;
      unsigned fm2$v_format : 2;
    } fm2$dummy_word0_format;
    variant_struct {
      unsigned fm2$v_exact : 1;
      unsigned fm2$v_oncyl : 1;
      unsigned : 10;
      unsigned fm2$v_lbn : 1;
      unsigned fm2$v_rvn : 1;
    } fm2$dummy_word0_placement;
    variant_struct {
      unsigned : 8;
      unsigned fm2$v_highlbn : 6;
    } fm2$dummy_word0_highlbn;
    variant_struct {
      unsigned fm2$v_count2 : 14;
    } fm2$dummy_word0_count2;
    unsigned char fm2$b_count1;
  } fm2$dummy_word0_union;
  variant_union {
    unsigned short int fm2$w_lowlbn;
    unsigned long int fm2$l_lbn2;
    variant_struct {
      unsigned short int fm2$w_lowcount;
      unsigned long int fm2$l_lbn3;
    } fm2$dummy_lbn_struct;
  } fm2$dummy_lbn_union;
};
$EOD
$ create/log FREPTECNT.C
$DECK
/* Modification History
   --------------------
   Sep. 8, 1987 JEM - Conversion from BETA to Release

*/
#include jpidef

int freptecnt()
{
  static int frep=0;
  static struct {
      short int buflen;
      short int itmcod;
      long int bufadr;
      long int retlen;
    } ItmLst[] = { 4,JPI$_FREPTECNT,&frep,0,
                   0,0,0,0 };

  if (SYS$GETJPIW(0,0,0,&ItmLst,0,0,0) & 1)
    return(frep);
  else
    return(0);
}
$EOD
$ create/log GETDVI.C
$DECK
/* Modification History
   --------------------
   Sep. 8, 1987 JEM - Conversion from BETA to Release

*/
#include descrip
#include dvidef

struct itmlstdef {
  short int buflen;
  short int itmcod;
  char *bufaddr;
  long int *retlen;
};
#define DEVLEN 64

int get_root_name(device,root)
  struct dsc$descriptor *device,*root;
{
  char devnam[DEVLEN];
  long int devnamlen;
  struct itmlstdef itmlst[] = {DEVLEN,DVI$_ROOTDEVNAM,0,0,0,0,0,0};
  long int status;

  itmlst[0].bufaddr = devnam;
  itmlst[0].retlen = &devnamlen;

  status = sys$getdvi(0,0,device,&itmlst,0,0,0,0);
  if (status & 1)
    str$copy_r(root,&devnamlen,devnam);
  return(status);
}

int get_next_device(device,next)
  struct dsc$descriptor *device,*next;
{
  char devnam[DEVLEN];
  long int devnamlen;
  struct itmlstdef itmlst[] = {DEVLEN,DVI$_NEXTDEVNAM,0,0,0,0,0,0};
  long int status;

  itmlst[0].bufaddr = devnam;
  itmlst[0].retlen = &devnamlen;

  status = sys$getdvi(0,0,device,&itmlst,0,0,0,0);
  if (status & 1)
    str$copy_r(next,&devnamlen,devnam);
  return(status);
}
$EOD
$ create/log GET_HEADER.C
$DECK
/* Modification History
   --------------------
   Sep. 8, 1987 JEM - Conversion from BETA to Release

*/
#include descrip
#include iodef
#include "fibdef.h"
#include "atrdef.h"
#include "fh2def.h"
#include "fileinfo.h"

char *get_header(fid,ofid,context,cached,chan)
  short int fid[3],ofid[3];
  struct FileInfo *context;
  int cached;
  short int chan;
{
  struct fh2def *fh2;
  static char *blockaddr=0;
  static long int block=512;
  long int blocknum,addr,i,j,status;

  static struct fibdef fib; /* short fib */
  static struct dsc$descriptor fibdesc =
    {FIB$K_ACCDATA,DSC$K_DTYPE_Z,DSC$K_CLASS_S,&fib};
  static struct ATRDEF atr[] = {
    ATR$S_HEADER,ATR$C_HEADER,0,
    0,0,0
    };
  short int iosb[4];

  if (fid[0] == 0) return(0);

  /* if cached and the fid is valid, just grab the header */
  /* this condition should mean they are doing a FULLNAME search */
  /* or asking for an extension header for FULLNAME or FILE_ID search */
  if ((cached && (fid[0] != 0) && (fid[1] != 0)) || fid[2] != 0) {
    if (blockaddr == 0) {
      status = lib$get_vm(&block,&blockaddr);
      if (!(status & 1)) return(0);
    };
    atr[0].atr$l_addr = blockaddr;
    for (i=0;i<3;i++)
      fib.fib$w_fid[i] = fid[i];
    /* Use the IO$_ACCESS function to return info about the file */
    status = sys$qiow(0,chan,IO$_ACCESS,
                      &iosb,0,0,&fibdesc,0,0,0,&atr,0);
    if ((status & 1) && (iosb[0] & 1))
      fh2 = blockaddr;
    else {
      fh2 = 0; /* assume this last ditch effort won't work */
      /* well, it didn't work for some reason.. Let's see if we can jog it's
         memory concerning this file by opening the darned thing. This seems
         to be a bug, but, heck, this seems to be a work around */
      /* Here we need to open the file pointed to by ofid.. Let's set the
         fib to NORECORD so we don't set dates.. */
      for (i=0;i<3;i++)
        fib.fib$w_fid[i] = ofid[i];
      fib.fib$l_acctl = FIB$M_NOLOCK | FIB$M_NORECORD;
      status = sys$qiow(0,chan,IO$_ACCESS|IO$M_ACCESS,
                        &iosb,0,0,&fibdesc,0,0,0,0,0);
      if ((status & 1) && (iosb[0] & 1)) {
        for (i=0;i<3;i++)
          fib.fib$w_fid[i] = fid[i];
/*        status = sys$qiow(0,context->fi_r_fab.fab$l_stv,IO$_ACCESS,
                          &iosb,0,0,&fibdesc,0,0,0,&atr,0); */
        status = sys$qiow(0,chan,IO$_ACCESS,&iosb,0,0,&fibdesc,0,0,0,&atr,0);
        if ((status & 1) && (iosb[0] & 1))
          fh2 = blockaddr;
      };
      for (i=0;i<3;i++)
        fib.fib$w_fid[i] = ofid[i];
      fib.fib$l_acctl = FIB$M_NORECORD;
      status = sys$qiow(0,chan,IO$_DEACCESS,&iosb,0,0,&fibdesc,0,0,0,0,0);
    };
    return(fh2);
  };

  /* get the header */
  if (fid[0]) {
    /* see if it is already mapped in */
    blocknum = fid[0] + context->fi_l_recoff;
    if ((blocknum > context->fi_l_offset)
       &(blocknum < context->fi_l_offset+context->fi_l_pagcnt+1)) {
      /* the header is already mapped into memory */
      addr = blocknum - context->fi_l_offset;
      addr = addr*512 + context->fi_l_begadr;
      j=1;
      for (i=0;i<3;i++)
        if ((fid[i] != (struct fh2 *)addr->fh2$w_fid[i]) && (fid[i] != 0))
          j=0;
      if (j)
        fh2 = addr;
      else
        fh2 = 0;
    }
    else {
      fh2 = 0;
      /* need to read the right block into memory */
      status = read_section_block(&context,&blocknum,&blockaddr);
      if (status & 1)
        fh2 = blockaddr;
    };
  }
  else
    fh2 = 0;

  /* if cached and we found a header, and the header fid isn't set to */
  /* zero, then get the real (possibly cached) header */
  /* these conditions should be met if they specified  a FILE_ID search */
  if (cached && fh2 && fh2->fh2$w_fid[0]) {
    if (blockaddr == 0) {
      status = lib$get_vm(&block,&blockaddr);
      if (!(status & 1)) return(0);
    };
    atr[0].atr$l_addr = blockaddr;
    for (i=0;i<3;i++)
      fib.fib$w_fid[i]=fh2->fh2$w_fid[i];
    /* Use the IO$_ACCESS function to return info about the file */
    status = sys$qiow(0,chan,IO$_ACCESS,&iosb,0,0,&fibdesc,0,0,0,&atr,0);
    if ((status & 1) && (iosb[0] & 1))
      fh2 = blockaddr;
    else
      fh2 = 0;
  };

  return(fh2);
}
$EOD
$ create/log HM2DEF.H
$DECK
/* This header file was created by Joe Meadows, and is not copyrighted
   in any way. No guarantee is made as to the accuracy of the contents
   of this header file. This header file was last modified on Sep. 8th,
   1987. */
#define HM2$C_LEVEL1    257
#define HM2$C_LEVEL2    512
#define HM2$M_READCHECK 1
#define HM2$M_WRITCHECK 2
#define HM2$M_ERASE     4
#define HM2$M_NOHIGHWATER       8
#define HM2$M_CLASS_PROT        16
#define HM2$S_HM2DEF    512
#define HM2$S_CREDATE   8
#define HM2$S_RETAINMIN 8
#define HM2$S_RETAINMAX 8
#define HM2$S_REVDATE   8
#define HM2$S_MIN_CLASS 20
#define HM2$S_MAX_CLASS 20
#define HM2$S_STRUCNAME 12
#define HM2$S_VOLNAME   12
#define HM2$S_OWNERNAME 12
#define HM2$S_FORMAT    12
#define DATE {unsigned : 32; unsigned : 32;}

struct hm2def {
  unsigned long int hm2$l_homelbn;
  unsigned long int hm2$l_alhomelbn;
  unsigned long int hm2$l_altidxlbn;
  variant_union {
    unsigned short int hm2$w_struclev;
    variant_struct {
      unsigned char hm2$b_strucver;
      unsigned char hm2$b_struclev;
    } hm2$dummy_w_struclev_struct;
  } hm2$dummy_w_struclev_union;
  unsigned short int hm2$w_cluster;
  unsigned short int hm2$w_homevbn;
  unsigned short int hm2$w_alhomevbn;
  unsigned short int hm2$w_altidxvbn;
  unsigned short int hm2$w_ibmapvbn;
  unsigned long int hm2$l_ibmaplbn;
  unsigned long int hm2$l_maxfiles;
  unsigned short int hm2$w_ibmapsize;
  unsigned short int hm2$w_resfiles;
  unsigned short int hm2$w_devtype;
  unsigned short int hm2$w_rvn;
  unsigned short int hm2$w_setcount;
  variant_union {
    unsigned short int hm2$w_volchar;
    variant_struct {
      unsigned hm2$v_readcheck : 1;
      unsigned hm2$v_writcheck : 1;
      unsigned hm2$v_erase : 1;
      unsigned hm2$v_nohighwater : 1;
      unsigned hm2$v_class_prot : 1;
    } hm2$dummy_w_volchar_struct;
  } hm2$dummy_w_volchar_union;
  unsigned long int hm2$l_volowner;
  unsigned long int hm2$l_sec_mask;
  unsigned short int hm2$w_protect;
  unsigned short int hm2$w_fileprot;
  unsigned short int hm2$w_recprot;
  unsigned short int hm2$w_checksum1;
  struct DATE hm2$q_credate;
  unsigned char hm2$b_window;
  unsigned char hm2$b_lru_lim;
  unsigned short int hm2$w_extend;
  struct DATE hm2$q_retainmin;
  struct DATE hm2$q_retainmax;
  struct DATE hm2$q_revdate;
  unsigned char hm2$r_min_class[HM2$S_MIN_CLASS];
  unsigned char hm2$r_max_class[HM2$S_MAX_CLASS];
  unsigned char hm2$fill_0[320];
  unsigned long int hm2$l_serialnum;
  unsigned char hm2$t_strucname[HM2$S_STRUCNAME];
  unsigned char hm2$t_volname[HM2$S_VOLNAME];
  unsigned char hm2$t_ownername[HM2$S_OWNERNAME];
  unsigned char hm2$t_format[HM2$S_FORMAT];
  unsigned char hm2$fill_1[2];
  unsigned short int hm2$w_checksum2;
};
$EOD
$ create/log INDEX.C
$DECK
/* INDEX, written by Joe Meadows, released to the world Sep. 8th, 1987.
   This is a public domain utility. No parts of this utility are
   copyrighted in any way. It may be used in any way, by anyone.
   There are no restrictions on this code. You may include it
   in a commercial package if you wish.

  Joe Meadows Jr.
  VAX/VMS System Manager / guru in training
  Fred Hutchinson Cancer Research Center
  1124 Columbia St.
  Seattle Wa. 98104
     bitnet - JOE@FHCRCVAX
     arpa   - JOE%FHCRCVAX.BITNET@WISCVM.WISC.EDU
     voice  - (206) 467-4970
*/

/* Modification History
   --------------------
   Sep. 8, 1987 JEM - Conversion from BETA to Release

*/
#include stdio
#include "hm2def.h"
#include "fh2def.h"
#include "fm2def.h"
#include "fi2def.h"
#include "FileInfo.h"  /* includes FAB, NAM, and XAB */
#include "searchdef.h" /* includes DESCRIP */
#include "displaydef.h"

main()
{
  static struct dsc$descriptor device = {0, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0};
  static struct dsc$descriptor devdesc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
  static $DESCRIPTOR(defaultname,"");
  static $DESCRIPTOR(null,"\0");
  static short int indexf_fid[3] = {1,1,0};
  static short int fid[3] = {0,0,0};
  static struct dsc$descriptor filename = {0, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0};
  static struct dsc$descriptor dynstr = {0, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0};
  static long int pagecount=0,opagecount=0;
  static long int offset=1;
  static long int flag=0;
  static long lastfid=0,currfid=0,endfid=0;
  static struct FileInfo *context;
  static struct FAB *fabptr;
  static struct NAM *namptr;
  static struct display_info display;
  static struct search_info search;
  static struct hm2def *hm2;
  static struct fh2def *fh2;
  static struct fm2def *fm2;
  static long int fm2offset;
  static long int count,lbn;
  static struct fi2def *fi2;
  static long int status=1;
  static char *block=0;
  static long int blocknum;
  static short int chan=0,tmpchan=0;
  static long int i=0,j=0,k=0,volume=0;

  if (cli_present("OUTPUT") & 1) {
    /* we should see if they want output to go to a file or to SYS$OUTPUT */
    status = cli_get_value("OUTPUT",&dynstr);
    if (status & 1) {
      str$append(&dynstr,&null);
      freopen(dynstr.dsc$a_pointer,"w",stdout,"rfm=var","rat=cr");
    };
  };

  (void) init_display(&display);
  status = init_search(&search);
  if (!(status & 1)) return(status);

  if (cli_present("FULLNAME")  & 1) {
    /* if FULLNAME specified, use lib$find_file to get the file ids,
       get the header, and display */
    while (cli_get_value("FULLNAME",&dynstr) & 1) {
      i = 2; /* flag for lib$find_file, MULTIPLE bit set */
      while (lib$find_file(&dynstr,&filename,&fabptr,0,0,0,&i) & 1) {
        namptr = fabptr->fab$l_nam;
        /* assign a temporary channel to the device */
        devdesc.dsc$w_length = namptr->nam$t_dvi[0];
        devdesc.dsc$a_pointer = &(*namptr).nam$t_dvi[1];

        /* assign a channel to the device */
        status=sys$assign(&devdesc,&tmpchan,0,0);
        if (!(status & 1)) return(status);

        fh2 = get_header((*namptr).nam$w_fid,(*namptr).nam$w_fid,
                         context,1,tmpchan);
        if (fh2)
          if (search_header(&search,fh2,context,1,tmpchan))
            display_header(&display,namptr->nam$w_fid[0],fh2,
                           context,1,tmpchan);

        status=sys$dassgn(tmpchan);
      }; /* while (lib$find_file()) */
    }; /* while (cli_get_value("FULLNAME")) */
    /* if they did a /FULLNAME search, and didn't do a /FILE_ID
       search, then we could just quit now.. */
    if ((cli_present("FILE_ID") & 1) == 0)
      return;
  }; /* if (cli_present("fullname")) */

  /* get the name of the device which we're planning on checking */
  status=cli_get_value("P1",&device);
  if (!(status & 1)) return(status);

  /* add in logic for /VOLUME for volume sets. If set, then go through
     each of the index files, one at a time.. */
  if (cli_present("VOLUME") & 1) {
    /* Oh boy, we need to loop through all of the index files! */
    volume = 1;
    status = get_root_name(&device,&device);
    if (!(status & 1)) return(status);
  };

  /* loop through all the index files, this is accomplished via a call */
  /* to get_next_device at the end of the while loop (only if /VOLUME set) */
  while (status & 1) {
    /* assign a channel to the device */
    status=sys$assign(&device,&chan,0,0);
    if (!(status & 1)) return(status);

    /* find out the complete name of INDEXF.SYS (this is to be sure and get
       the device name right, even if you're sitting in a rooted directory */
    status = fid_to_name(&chan,indexf_fid,&filename);
    if (!(status & 1)) return(status);

    /* don't ask for more pages than we can handle, in fact, lets leave
       a mild safety net */
    pagecount = freptecnt() - 1000;

    /* if FILE_ID search, then map in a small part of the file */
    if (cli_present("FILE_ID") & 1)
      pagecount = 10;

    offset = 1;
    /* map in part of the file now */
    status=map_section(&filename,&defaultname,&pagecount,
                       &offset,&flag,&context);
    if (!(status & 1)) return(status);

    /* home block is usually block number 2 */
    hm2 = (struct hm2def *)(context->fi_l_begadr+512);

    if (hm2->hm2$b_struclev != 2) {
      printf("Sorry, INDEX only works for structure level 2 disks.\n");
      return;
    };

    offset = hm2->hm2$w_ibmapvbn + hm2->hm2$w_ibmapsize;
    context->fi_l_recoff = offset - 1; /* Store the indexf offset here */
    opagecount = pagecount;
    pagecount -= (offset - 1);
    endfid = pagecount;
    lastfid = context->fi_l_filsiz - offset + 1;
    fh2 = context->fi_l_begadr + 512*(offset-1);

    if (cli_present("FILE_ID") & 1) {
      /* if FILE_ID specified, get the header, and display */
      while (cli_get_value("FILE_ID",&dynstr) & 1) {
        if (ots$cvt_ti_l(&dynstr,&i) & 1) {
          fid[0] = i;
          fh2 = get_header(fid,fid,context,1,chan);
          if (fh2)
            if (search_header(&search,fh2,context,1,chan))
              display_header(&display,fid[0],fh2,context,1,chan);
        };
      };
    }
    else
    for (currfid=1;currfid<=lastfid;currfid++) {
      if (currfid>endfid) {
        /* okay, that should have been the last one in this segment.. */
        /* lets read in the next section of the file */
        offset = offset + pagecount;
        pagecount = opagecount;
        status=map_section(&filename,&defaultname,
                           &pagecount,&offset,&flag,&context);
        if (!(status & 1)) return(status);
        endfid = endfid + pagecount;
        fh2 = context->fi_l_begadr;
      };

      if (search_header(&search,fh2,context,0,chan))
        (void)display_header(&display,currfid,fh2,context,0,chan);

      /* okay, point to the next file header */
      ++fh2;
    };

    /* call it a day, clean up and go home.... */
    status=delete_section(&context);
    if (!(status & 1)) return(status);

  if (volume)
    status = get_next_device(&device,&device);
  else
    status = 0;
  }; /* while (status & 1) */

}
$EOD
$ create/log INDEX.CLD
$DECK
define type placement_keywords
  keyword EXACT
  keyword ON_CYLINDER
  keyword RELATIVE_VOLUME_NUMBER
  keyword LBN_SPECIFIED

define type match_keywords
  keyword AND
  keyword OR
define type PROTECTION_FIELDS
   keyword SYSTEM, value
   keyword OWNER, value
   keyword GROUP, value
   keyword WORLD, value
define type PROTECTION_KEYWORDS
   keyword SET, value(required, list, type=PROTECTION_FIELDS)
   keyword CLEAR, value(required, list, type=PROTECTION_FIELDS)
define type DISPLAY_KEYWORDS
   keyword ALL
      negatable
   keyword ACL
      negatable
   keyword TYPE
      negatable
   keyword ORGANIZATION
      negatable
   keyword ATTRIBUTES
      negatable
   keyword CHARACTERISTICS
      negatable
   keyword JOURNAL
      negatable
   keyword CREATION_DATE
      negatable
   keyword REVISION_DATE
      negatable
   keyword EXPIRATION_DATE
      negatable
   keyword BACKUP_DATE
      negatable
   keyword NUMBER_OF_REVISIONS
      negatable
   keyword VFC_SIZE
      negatable
   keyword RECORD_SIZE
      negatable
   keyword MAXIMUM_RECORD_SIZE
      negatable
   keyword USED
      negatable
   keyword FIRST_FREE_BYTE
      negatable
   keyword ALLOCATED
      negatable
   keyword DEFAULT_EXTEND_QUANTITY
      negatable
   keyword BUCKET_SIZE
      negatable
   keyword GLOBAL_BUFFER_COUNT
      negatable
   keyword VERSION_LIMIT
      negatable
   keyword EXTENTS
      negatable
   keyword HEADERS
      negatable
   keyword LBN
      negatable
   keyword OWNER_UIC
      negatable
   keyword PROTECTION
      negatable
   keyword FILE_ID
      negatable
   keyword DIRECTORY_FILE_ID
      negatable
   keyword ACCESS_MODE
      negatable
   keyword HIGHWATER_MARK
      negatable
   keyword ACTIVE_RECOVERY_UNITS
      negatable
   keyword WASTED_BLOCKS
      negatable
   keyword NAME
      negatable
   keyword FULLNAME
      negatable
define type RECTYPE_KEYWORDS
   keyword UNDEFINED
      negatable
   keyword FIXED
      negatable
   keyword VARIABLE
      negatable
   keyword VFC
      negatable
   keyword STREAM
      negatable
   keyword LFSTREAM
      negatable
   keyword CRSTREAM
      negatable
define type FILEORG_KEYWORDS
   keyword SEQUENTIAL
      negatable
   keyword RELATIVE
      negatable
   keyword INDEXED
      negatable
   keyword DIRECT
      negatable
define type ATTRIB_KEYWORDS
   keyword FORTRANCC
      negatable
   keyword IMPLIEDCC
      negatable
   keyword PRINTCC
      negatable
   keyword SPAN
      negatable
define type CHAR_KEYWORDS
   keyword ACL_CORRUPT
      negatable
   keyword BACKUP
      negatable
   keyword BEST_TRY_CONTIGUOUS
      negatable
   keyword CHARGE
      negatable
   keyword CONTIGUOUS
      negatable
   keyword DIRECTORY
      negatable
   keyword ERASE_ON_DELETE
      negatable
   keyword FILE_CORRUPT
      negatable
   keyword LOCKED
      negatable
   keyword MARKED_FOR_DELETE
      negatable
   keyword SPOOL
      negatable
   keyword READ_VERIFY
      negatable
   keyword WRITE_BACK
      negatable
   keyword WRITE_VERIFY
      negatable
define type JOURNAL_KEYWORDS
   keyword JOURNAL
      negatable
   keyword AIJNL
      negatable
   keyword ATJNL
      negatable
   keyword BIJNL
      negatable
   keyword RUJNL
      negatable
   keyword NEVER_RU
      negatable
   keyword ONLY_RU
      negatable
define type ACCESS_KEYWORDS
   keyword USER
      negatable
   keyword SUPERVISOR
      negatable
   keyword EXECUTIVE
      negatable
   keyword KERNEL
      negatable
define verb INDEX
   image INDEX
   parameter P1
      default
      value (default="SYS$DISK",type=$infile)
   qualifier OUTPUT
      value (default="INDEXF.LIS",type=$outfile)
   qualifier DISPLAY
      value (required,list,type=DISPLAY_KEYWORDS)
   qualifier MATCH
      value (required,type=MATCH_KEYWORDS)
   qualifier ACL
   qualifier ACE
      value (required,list,type=$uic)
   qualifier TYPE
      value (required,list,type=RECTYPE_KEYWORDS)
   qualifier ORGANIZATION
      value (required,list,type=FILEORG_KEYWORDS)
   qualifier ATTRIBUTES
      value (required,list,type=ATTRIB_KEYWORDS)
   qualifier CHARACTERISTICS
      value (required,list,type=CHAR_KEYWORDS)
   qualifier PLACEMENT
      value (required,list,type=PLACEMENT_KEYWORDS)
   qualifier JOURNAL
      value (required,list,type=JOURNAL_KEYWORDS)
   qualifier ACCESS_MODE
      value (required,list,type=ACCESS_KEYWORDS)
   qualifier CREATION_DATE
      value (required,list,type=$datetime)
   qualifier REVISION_DATE
      value (required,list,type=$datetime)
   qualifier EXPIRATION_DATE
      value (required,list,type=$datetime)
   qualifier BACKUP_DATE
      value (required,list,type=$datetime)
   qualifier NUMBER_OF_REVISIONS
      value (required,list,type=$number)
   qualifier VFC_SIZE
      value (required,list,type=$number)
   qualifier RECORD_SIZE
      value (required,list,type=$number)
   qualifier MAXIMUM_RECORD_SIZE
      value (required,list,type=$number)
   qualifier USED
      value (required,list,type=$number)
   qualifier FIRST_FREE_BYTE
      value (required,list,type=$number)
   qualifier ALLOCATED
      value (required,list,type=$number)
   qualifier DEFAULT_EXTEND_QUANTITY
      value (required,list,type=$number)
   qualifier BUCKET_SIZE
      value (required,list,type=$number)
   qualifier GLOBAL_BUFFER_COUNT
      value (required,list,type=$number)
   qualifier VERSION_LIMIT
      value (required,list,type=$number)
   qualifier EXTENTS
      value (required,list,type=$number)
   qualifier HEADERS
      value (required,list,type=$number)
   qualifier LBN
      value (required,list,type=$number)
   qualifier OWNER_UIC
      value (required,list,type=$uic)
   qualifier PROTECTION
      value (required,list,type=protection_keywords)
   qualifier FILE_ID
      value (required,list,type=$number)
   qualifier DIRECTORY_FILE_ID
      value (required,list,type=$number)
   qualifier HIGHWATER_MARK
      value (required,list,type=$number)
   qualifier ACTIVE_RECOVERY_UNITS
      value (required,list)
   qualifier WASTED_BLOCKS
      value (required,list,type=$number)
   qualifier NAME
      value (required,list)
   qualifier FULLNAME
      value (required,list)
   qualifier VOLUME
$EOD
$ create/log INDEX.COM
$DECK
$ say = "write sys$output"
$ if p1.eqs."" then say "Linking INDEX''p2'"
$ if p1.eqs."ALL" then say "Compiling INDEX utility"
$ if (p1.nes."").and.(p1.nes."ALL") then say "Compiling ''p1'"
$ if p1.eqs."ALL" .or. p1.eqs."CLI" then cc/debug cli
$ if p1.eqs."ALL" .or. p1.eqs."DISPLAY" then cc/debug display
$ if p1.eqs."ALL" .or. p1.eqs."FID" then cc/debug fid
$ if p1.eqs."ALL" .or. p1.eqs."FREPTECNT" then cc/debug freptecnt
$ if p1.eqs."ALL" .or. p1.eqs."GET_HEADER" then cc/debug get_header
$ if p1.eqs."ALL" .or. p1.eqs."GETDVI" then cc/debug getdvi
$ if p1.eqs."ALL" .or. p1.eqs."INDEX" then cc/debug index
$ if p1.eqs."ALL" .or. p1.eqs."PARSE_UIC" then macro/debug parse_uic
$ if p1.eqs."ALL" .or. p1.eqs."SEARCH" then cc/debug search
$ if p1.eqs."ALL" .or. p1.eqs."SECTION" then cc/debug section
$ link'p2' index,cli,display,fid,freptecnt,get_header,getdvi,search,section,-
           parse_uic,c/option
$EOD
$ create/log INDEX.COMPILE
$DECK
index.c,.obj,cc/debug
cli.c,.obj,cc/debug
display.c,.obj,cc/debug
fid.c,.obj,cc/debug
freptecnt.c,.obj,cc/debug
get_header.c,.obj,cc/debug
getdvi.c,.obj,cc/debug
search.c,.obj,cc/debug
section.c,.obj,cc/debug
parse_uic.mar,.obj,macro/debug
c.opt,,,/option
$EOD