From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  9-JUN-1989 20:56
To:	MRGATE::"ARISIA::EVERHART"
Subj:	MAINT -- Full Screen File/Directory Maintenance (Part 10 of 11)

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Fri,  9 JUN 89 07:00:58 PDT
Received: from ucbvax.Berkeley.EDU by KL.SRI.COM with TCP; Fri, 9 Jun 89 06:52:36 PDT
Received: by ucbvax.Berkeley.EDU (5.61/1.36)
	id AA17236; Fri, 9 Jun 89 06:26:17 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 9 Jun 89 12:59:32 GMT
From: peirce@gumby.wisc.edu  (Leonard J. Peirce)
Organization: Western Michigan University, Kalamazoo, MI
Subject: MAINT -- Full Screen File/Directory Maintenance (Part 10 of 11)
Message-Id: <748@gumby.cc.wmich.edu>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

+-+-+-+ Beginning of part 10 +-+-+-+
X
X   if((term_code == SMG$K_TRM_LOWERCASE_N) `124`124
X      (term_code == SMG$K_TRM_UPPERCASE_N))
X      return(DONT_CREATE);`009`009/* don't create the file here, either */
X
X   /* ok, we need to create the file; open it for writing */
X
X   out_fab = cc$rms_fab;`009`009/* initialize the RMS blocks`009      */
X   out_rab = cc$rms_rab;
X
V   out_fab.fab$b_fac = FAB$M_PUT;`009/* using SYS$PUT for record I/O`009 `032
X    */
X   out_fab.fab$w_ifi = 0;`009`009/* make sure to reset every time      */
X   out_fab.fab$b_rat = FAB$M_CR;`009/* carriage-return carriage control   */
X   out_fab.fab$l_fna = TEXT_FILE;`009/* set filename`009`009`009      */
X   out_fab.fab$b_fns = (UCHAR) strlen(TEXT_FILE);
X
X   out_rab.rab$l_fab = &out_fab;`009/* set RAB fields`009`009      */
X   out_rab.rab$b_rac = RAB$C_SEQ;`009/* sequential access`009`009      */
X   out_rab.rab$l_rbf = buf;
X
X   status = SYS$CREATE(&out_fab);
X
X   if(status != RMS$_NORMAL)
X      return(CANT_OPEN);
X
X   /* connect the RMS blocks */
X
X   status = SYS$CONNECT(&out_rab);
X
X   if(status != RMS$_NORMAL)
X   `123
X      SYS$CLOSE(&out_fab);
X      delete(TEXT_FILE);`009`009/* delete the file to be thorough     */
X      return(CANT_OPEN);
X   `125
X
X   /* the file has been opened ok; get the descriptor for the directory,
X    * format it, and write it to the text descriptor file
X    */
X
X   /* position the cursor to prompt for the text descriptor */
X
X   status = SMG$SET_CURSOR_ABS(&disp_id,&MAIN_ROWS,&1L);
X
X   if(status != SS$_NORMAL)
X   `123
X      SYS$CLOSE(&out_fab);
X      delete(TEXT_FILE);
X      return(CANT_OPEN);
X   `125
X
X   /* prompt for and read in the text descriptor for the directory itself */
X
X   status = SMG$READ_STRING(&keybd_id,&text_d,&prompt_d,&DIR_TEXT_MAX,0,0,0,
X`009`009`009    &length,0,&disp_id,0,&SMG$M_BOLD,0);
X
X   if(status != SS$_NORMAL)
X   `123
X      SYS$CLOSE(&out_fab);
X      delete(TEXT_FILE);
X      return(CANT_OPEN);
X   `125
X
X   text_buf[length] = '\0';`009`009/* make it a string`009`009      */
X
X   clear_mess(disp_id,scr_width);`009/* clear things out`009`009      */
X
X   cat(buf,">>>",text_buf);`009`009/* format it correctly`009`009      */
X
X   /* now write the directory text descriptor record to the file */
X
X   out_rab.rab$w_rsz = length + 3;`009/* set length in RAB`009`009      */
X   status = SYS$PUT(&out_rab);`009`009/* write it to the file`009`009      */
X
X   if(status != RMS$_NORMAL)
X   `123
X      SYS$CLOSE(&out_rab);
X      delete(TEXT_FILE);
X      return(CANT_OPEN);
X   `125
X
X   /* write the spacing record to the file */
X
X   strcpy(buf,">");`009`009`009/* copy spacing record to the buffer  */
X   out_rab.rab$w_rsz = 1;`009`009/* set length of spacing record`009      */
X
V   status = SYS$PUT(&out_rab);`009`009/* write two of them and check later  *
X/
X   status = SYS$PUT(&out_rab);
X
X   if(status != RMS$_NORMAL)
X   `123
X      SYS$CLOSE(&out_rab);
X      delete(TEXT_FILE);
X      return(CANT_OPEN);
X   `125
X
X   /* now write the text descriptor entry for the text descriptor file
X    * itself; this is so the user knows what the file is when they bring
X    * the text descriptors in
X    */
X
X   cat(buf,TEXT_FILE," text descriptor file");
X   out_rab.rab$w_rsz = (USHORT) strlen(buf);
X
X   status = SYS$PUT(&out_rab);
X
X   if(status != RMS$_NORMAL)
X   `123
X      SYS$CLOSE(&out_rab);
X      delete(TEXT_FILE);
X      return(CANT_OPEN);
X   `125
X
X   /* we are done (finally!); just close the file and return */
X
X   status = SYS$CLOSE(&out_fab);
X
X   if(status != RMS$_NORMAL)
X   `123
X      delete(TEXT_FILE);
X      return(CANT_OPEN);
X   `125
X
X   return(NEW_FILE);
X
X`125`009/*** create_text ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009free_com
X
X  Purpose:`009Free the memory that was allocated for all of the command
X`009`009structures for a directory, including all of the memory that
X`009`009may have been allocated to hold things such as the copy name,
X`009`009the rename name, and the text descriptor.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xvoid free_comm(dirptr,num_file)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister ENT_DEF  *dirptr;`009`009/* pointer to directory entries`009      */
Vregister short`009  num_file;`009`009/* number of files in directory`009 `032
X    */
X
X`123`009/*** free_comm ***/
X
X
X   while(num_file-- >0)`009`009`009/* delete all command structs`009      */
X   `123
V      if(dirptr->command != NULL) `009/* command struct for this entry?     *
X/
X      `123
X`009 /* free up the command structure and everything associated with it */
X
X`009 free_comstr(dirptr->command);
X      `125
X
X      dirptr++;`009`009`009`009/* go to next command strucure`009      */
X   `125
X
X   return;
X
X`125`009/*** free_comm ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009exp_prot_str
X
X  Purpose:`009Take an integer value for a file's protection and produce a
X`009`009nice VMS-style string for the protection.  This routine will
X`009`009only be used by the Expand command because it won't fit on the
X`009`009screen in a file slot.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xvoid exp_prot_str(str,prot)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister char`009  *str;`009`009`009/* where to put the string`009      */
X`009 USHORT`009  prot;`009`009`009/* protection value`009`009      */
X
X`123`009/*** exp_prot_str ***/
X
X
X   /* initialize the string with the first field name and get a pointer
X    * to the end of the string
X    */
X
X   str = mystrcpy(str,"System:");
X
X   /* now see what the protection values for the field(s) are */
X
X   if(!(prot & SYSTEM_READ))
X      *str++ = 'R';
X   if(!(prot & SYSTEM_WRITE))
X      *str++ = 'W';
X   if(!(prot & SYSTEM_EXECUTE))
X      *str++ = 'E';
X   if(!(prot & SYSTEM_DELETE))
X      *str++ = 'D';
X
X   str = mystrcpy(str,", Owner:");
X
X   if(!(prot & OWNER_READ))
X      *str++ = 'R';
X   if(!(prot & OWNER_WRITE))
X      *str++ = 'W';
X   if(!(prot & OWNER_EXECUTE))
X      *str++ = 'E';
X   if(!(prot & OWNER_DELETE))
X      *str++ = 'D';
X
X   str = mystrcpy(str,", Group:");
X
X   if(!(prot & GROUP_READ))
X      *str++ = 'R';
X   if(!(prot & GROUP_WRITE))
X      *str++ = 'W';
X   if(!(prot & GROUP_EXECUTE))
X      *str++ = 'E';
X   if(!(prot & GROUP_DELETE))
X      *str++ = 'D';
X
X   str = mystrcpy(str,", World:");
X
X   if(!(prot & WORLD_READ))
X      *str++ = 'R';
X   if(!(prot & WORLD_WRITE))
X      *str++ = 'W';
X   if(!(prot & WORLD_EXECUTE))
X      *str++ = 'E';
X   if(!(prot & WORLD_DELETE))
X      *str++ = 'D';
X
X   *str = '\0';`009`009`009`009/* make it a string`009`009      */
X
X   return;
X
X`125`009/*** exp_prot_str ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009set_args
X
X  Purpose:`009Set the original values for ent_factor and slot_width along
X`009`009with initializing some of the other flags that provide infor-
X`009`009mation about what run-time arguments were specified.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xvoid set_args(args,slot_width,ent_factor,scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister ARG_DEF  *args;`009`009/* run-time argument flags`009      */
X`009 short`009  *slot_width,`009`009/* starting slot width`009`009      */
X`009`009  *ent_factor,`009`009/* ent. size memory allocation factor */
X`009`009  scr_width;`009`009/* width of screen being used`009      */
X
X`123`009/*** set_args ***/
X
X   /* initialize the width to include the length of the filename that
X    * will be displayed and the spot to hold the cursor; also update
X    * the entry size factor for later
X    */
X
X   *slot_width = NAME_MAX + 1;
X   *ent_factor = FUDGE_FACTOR;
X
X   if(args->full)
X   `123
X      /* just make the factors reflect full info on the screen */
X
X      *slot_width = FULL_MAX;
X      *ent_factor = NAME_MAX + DATE_MAX + PROT_MAX + 3;
X   `125
X   else
X   `123
X      /* nope, we have to see what info should be included to get the
X       * slot width and the entry factor
X       */
X
X      if(args->date)
X      `123
X`009 *slot_width = *slot_width + DATE_MAX + 1;
X`009 *ent_factor = *ent_factor + DATE_MAX + 1;
X      `125
X
X      if(args->size)
X`009 *slot_width = *slot_width + SIZE_MAX + 1;
X
X      if(args->prot)
X      `123
X`009 *slot_width = *slot_width + PROT_MAX + 1;
X`009 *ent_factor = *ent_factor + PROT_MAX + 1;
X      `125
X   `125
X
X   if(args->text)
X   `123
X      /* the user wants text descriptors */
X
X      *ent_factor = *ent_factor + TEXT_MAX + 1;
X      *slot_width = *slot_width + TEXT_MAX + 1;
X`032
X      /* now see if there is enough room to include the text descriptors on
X       * the screen
X       */
X
X      if(*slot_width > scr_width)
X      `123
V`009 args->text = SLOT_OVF;`009`009/* they overflow the file slots`009      *
X/
X`009 *slot_width = *slot_width - (TEXT_MAX + 1);
X      `125
X   `125
X
X   if(*slot_width == FULL_MAX)
X      args->full = 1;
X   else
X   `123
X      if(*slot_width == (NAME_MAX + 1))
X`009 args->def = 1;`009`009`009/* just default info on screen`009      */
X      else
X`009 args->def = 0;`009`009`009/* clear to be thorough.....`009      */
X   `125
X
X   return;
X
X`125`009/*** set_args ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009set_width
X
X  Purpose:`009Set the slot width for the current directory based on whether
X`009`009or not text descriptors will be included on the screen
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xvoid set_width(slot_width,text_flag)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 short`009  *slot_width,`009`009/* current slot width`009`009      */
X`009`009  text_flag;`009`009/* text descrips included for dir?    */
X
X`123`009/*** set_width ***/
X
X
X   /* should we at least TRY to get text descriptors on the screen? */
X
X   if(text_flag == DISPLAY_TEXT)
X   `123
X      /* yes, they need to be displayed; increase the slot_width
X       * to accommodate them
X       */
X
X      *slot_width = *slot_width + TEXT_MAX + 1;
X   `125
X
X   return;
X
X`125`009/*** set_width ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009get_scr_num
X
X  Purpose:`009Prompt for and read in a digit string that is supposed to
X`009`009represent the screen number that the user wants to go to.
X`009`009Also check to see if the screen number is valid.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009BAD_SCREEN_NO`009`009invalid screen number specified
X`009new_screen`009`009new screen number
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xshort get_scr_num(disp_id,keybd_id,curr_screen,num_screen,scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 long`009  disp_id,`009`009/* display id to work with`009      */
X `009 `009  keybd_id;`009`009/* keyboard id value`009`009      */
V`009 short`009  curr_screen,`009`009/* current screen of directory`009      *
X/
X`009`009  num_screen,`009`009/* number of screens in directory     */
X`009`009  scr_width;`009`009/* width of screen being used`009      */
X
X`123`009/*** get_scr_num ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
X`009 ULONG`009  status;`009`009/* return code status holder`009      */
X`009 int`009  new_screen;`009`009/* new screen number`009`009      */
X`009 USHORT`009  length;`009`009/* length of string read in`009      */
X`009 short`009  temp;`009`009`009/* temporary string length`009      */
Vstatic`009 char`009  buf[PAGE_NO_MAX+1];`009/* for holding page number string
X     */
Xstatic $DESCRIPTOR(buf_d,buf);
Xstatic $DESCRIPTOR(prompt_d,"Page number: ");
X
X
X   /* position the cursor to prompt for the page number */
X
X   status = SMG$SET_CURSOR_ABS(&disp_id,&MAIN_ROWS,&1L);
X
X   if(status != SS$_NORMAL)
X      return(curr_screen);  `032
X
X   /* prompt for and read it */
X
X   status = SMG$READ_STRING(&keybd_id,&buf_d,&prompt_d,&PAGE_NO_MAX,0,0,0,
X`009`009`009    &length,0,&disp_id,0,&SMG$M_BOLD,0);
X
X   if(status != SS$_NORMAL)
X   `123
X      info_mess(disp_id,"\07Error obtaining page number!",scr_width);
X      return(curr_screen);
X   `125
X
X   clear_mess(disp_id,scr_width);`009/* clear the stuff from the screen    */
X
X   if(length == 0)
X      return(curr_screen);`009`009/* user didn't specify anything`009      */
X
X   buf[length--] = '\0';`009`009/* make it a string`009`009      */
X
X   /* make sure that this is a string of DIGITS or atoi() will do
X    * weird things
X    */
X
X   temp = (short) length;`009`009/* get a SIGNED version of length     */
X
X   while(temp >= 0)
X   `123
X      if(isdigit(buf[temp]) `124`124 isspace(buf[temp]))
X`009 temp--;
X      else
X`009 return(BAD_SCREEN_NO);
X   `125
X
X   new_screen = atoi(buf);`009`009/* NOW make it an integer`009      */
X
X   if((new_screen < 1) `124`124 (new_screen > num_screen))
X      return(BAD_SCREEN_NO);`009`009/* bad screen number was specified    */
X
V   return((short) new_screen);`009`009/* return the new screen number`009`032
X     */
X
X`125`009/*** get_scr_num ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009edit_acl
X
X  Purpose:`009Call the ACL editor for the specified file.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X`032
XULONG edit_acl(filename)
X       `009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 char`009  *filename;`009`009/* file whose ACL will be edited      */
X
X`123`009/*** edit_acl ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xstatic`009ULONG`009  status,`009`009/* return code status holder`009      */
X`009`009  type_val,`009`009/* type of object being edited`009      */
X`009`009  options;`009`009/* options to ACL editor`009      */
X$DESCRIPTOR(item_d,"");`009`009/* descriptor for object name`009      */
X`009ITM_LST`009items[] = `123`009`009/* items for calling the ACL editor   */
X`1230,ACLEDIT$C_OBJNAM,&item_d,0`125,
X`1234,ACLEDIT$C_OBJTYP,&type_val,0L`125,
X`1234,ACLEDIT$C_OPTIONS,&options,0L`125,
X`1230,0,0L,0L`125
X`125;
X
X
X   /* use autoprompt mode for the ACL editor and journal the session */
X
X   options = (1 << ACLEDIT$V_PROMPT_MODE) `124 (1 << ACLEDIT$V_JOURNAL);
X   type_val = ACL$C_FILE;`009`009/* editing a file's ACL`009`009      */
V   item_d.dsc$a_pointer = filename;`009/* set address in descriptor`009  `032
X   */
X   item_d.dsc$w_length = (USHORT) strlen(filename);
X   items[0].buf_len = item_d.dsc$w_length;
X
X   return(ACLEDIT$EDIT(items));
X
X`125`009/*** edit_acl ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009put_acl
X
X  Purpose:`009Format the ACL for the current file and write it to the
X`009`009screen; this routine is called by expand().
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009CANT_DISPLAY`009`009error obtaining/formatting ACL
X`009  0`009`009`009Everything fine
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic short put_acl(keybd_id,fab,prot_xab,acl_buf,acl_len,row,disp_id,
X`009`009     scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 ULONG`009  keybd_id;`009`009/* keyboard id for user's terminal    */
Xstruct`009 FAB`009  *fab;`009`009`009/* current file's FAB`009`009      */
Vstruct`009 XABPRO`009  *prot_xab;`009`009/* XAB for getting ACL information
X    */
X`009 UCHAR`009  *acl_buf;`009`009/* where ACL binary info is stored    */
X`009 USHORT`009  acl_len;`009`009/* length of all ACL's for file       */
X`009 long`009  *row;`009`009`009/* current row of the display`009      */
X`009 ULONG`009  disp_id;`009`009/* where to write the information     */
X`009 short`009  scr_width;`009`009/* width of user's screen`009      */
X
X`123`009/*** put_acl ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister UCHAR`009  *tptr;`009`009/* pointer to current binary ACE      */
X`009 ULONG`009  status,`009`009/* return code status holder`009      */
X`009`009  ace_len;`009`009/* length of ASCII ACE`009`009      */
X`009 short`009  put_cnt = 0;`009`009/* set after first put_buf() call     */
X`009 USHORT`009  accum_len = 0,`009/* accumulated length of all ACE's    */
X`009     `009  buf_len;`009`009/* total processed in current buffer  */
Xstatic`009 char`009  outbuf[BUFSIZ];`009/* holds formatted ACE's`009      */
Xstatic $DESCRIPTOR(in_d,"");`009`009/* input descrip for formatting ACL's */
Xstatic $DESCRIPTOR(out_d,outbuf);`009/* output descrip for     "      "    */
X
X
X   /* process ALL of the ACL information for the current file; we do this by
X    * continuing until the accumulated length of all ACE's processed meets
X    * or exceeds the length that came in acl_len
X    */
X                                                          `032
X   while(accum_len < acl_len)
X   `123
X      /* process all of the ACE's in the current buffer; after we do that,
X       * see if we need to do a SYS$DISPLAY() to look for more
X       */
X
X      tptr = acl_buf;
X      buf_len = 0;
X      while((buf_len < ACLBUF_MAX) && (*tptr != 0))
X      `123
X`009 /* format the current ACE */
X
X`009 in_d.dsc$a_pointer = tptr;
X`009 in_d.dsc$w_length = (USHORT) *tptr;
X`009 status = SYS$FORMAT_ACL(&in_d,&ace_len,&out_d,0,0,0,0);
X
X`009 if(status != SS$_NORMAL)
X`009    return(CANT_DISPLAY);
X
X`009 *(outbuf + ace_len) = '\0';`009/* make it a string`009`009      */
X
X`009 if(!put_cnt)
X`009 `123
X`009    /* this is the first ACE that we are writing; insert the
X`009     * identification string before calling put_buf() to write it
X`009     */
X                                                   `032
X`009    strins(outbuf,"Access Cntrl List:  ",0);
X`009    put_buf(keybd_id,disp_id,outbuf,row,scr_width,NULL,'+');
X`009    put_cnt++;
X`009 `125
X`009 else
X`009 `123
X`009    /* here we specify a prefix pad string so that put_buf() formats
X`009     * things nicely
X`009     */
X
X`009    put_buf(keybd_id,disp_id,outbuf,row,scr_width,
X`009`009    "                    ",'+');
X`009 `125
X
X`009 buf_len += *tptr;`009`009/* update processed length`009      */
V`009 tptr = tptr + (ULONG) *tptr;`009/* move to next ACE in buffer`009      *
X/
X      `125
X
X      accum_len += buf_len;`009`009/* add in what was processed`009      */
X      if(accum_len < acl_len)`009`009/* do we need to a SYS$DISPLAY()?     */
X      `123
X`009 status = SYS$DISPLAY(fab);
X`009 if(status != RMS$_NORMAL)
X`009    return(CANT_DISPLAY);
X      `125
X   `125
X
X   return(0);
X
X`125`009/*** put_acl ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009free_comstr
X
X  Purpose:`009Free the memory that belongs to a specific command structure.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
X  Termination Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009status`009`009`009failure freeing memory
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X`032
Xstatic void free_comstr(command_str)
X       `009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 COM_DEF  *command_str;`009`009/* pointer to structure to be freed   */
X
X`123`009/*** free_comstr ***/
X`009`009      `009`009`009/********   LOCAL  VARIABLES   ********/
Xregister COM_DEF  *comm_ptr;`009`009/* register pointer for quickness     */
Xstatic`009 ULONG`009  status;`009`009/* return code status holder`009      */
Vstatic`009 long`009  num_bytes;`009`009/* number of bytes to be freed`009`032
X     */
X
X
X   comm_ptr = command_str;`009`009/* make a copy to make it faster      */
X
X   if(comm_ptr->copy_name != NULL)
X   `123
X      /* free up the memory for the copy name */
X
X      num_bytes = (long) comm_ptr->copy_len;
X      status = LIB$FREE_VM(&num_bytes,&(comm_ptr->copy_name));
X
X      if(status != SS$_NORMAL)
X`009 LIB$STOP(status);
X   `125
X
X   if(comm_ptr->ren_name != NULL)
X   `123
X      /* free up the memory for the rename name */
X
X      num_bytes = (long) comm_ptr->ren_len;
X      status = LIB$FREE_VM(&num_bytes,&(comm_ptr->ren_name));
X
X      if(status != SS$_NORMAL)
X`009 LIB$STOP(status);
X   `125
X
X   if(comm_ptr->text != NULL)
X   `123
X      /* free up the memory for the copy name */
X
X      num_bytes = (long) comm_ptr->text_len;
X      status = LIB$FREE_VM(&num_bytes,&(comm_ptr->text));
X
X      if(status != SS$_NORMAL)
X`009 LIB$STOP(status);
X   `125
X
X   /* now free up the command structure itself */
X
X   num_bytes = (long) sizeof(COM_DEF);
X   status = LIB$FREE_VM(&num_bytes,&command_str);
X
X   if(status != SS$_NORMAL)
X      LIB$STOP(status);
X
X   return;
X`125`009/*** free_comstr ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009make_text_rec
X
X  Purpose:`009Create a record to be written to a text descriptor file.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009none
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic void make_text_rec(buf,filename,text)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 char`009  *buf,`009`009`009/* where to put formatted record      */
X`009`009  *filename,`009`009/* filename to be inserted in record  */
X`009`009  *text;`009`009/* text descriptor`009`009      */
X
X`123`009/*** make_text_rec ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister char`009  *tptr;`009`009/* temporary character pointer`009      */
X
X
V   tptr = strchr(filename,';');`009`009/* lop off the version number.....`032
X   */
X
X   if(tptr != NULL)`009`009`009/* ..... if there was one`009      */
X      *tptr = '\0';
X
V   sprintf(buf,"%s %s",filename,text);`009/* make the text descriptor record
X    */
X  `032
X   if(tptr != NULL)
X      *tptr = ';';`009`009`009/* restore the filename`009`009      */
X
X   return;
X
X`125`009/*** make_text_rec ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009put_buf
X
X  Purpose:`009Output the current buffer to the display.
X
X`009`009This routine will also wrap long lines.  It will look
X`009`009for the character specified by the separator parameter
X`009`009and wrap it there if it finds one.
X
X`009`009Also, if there is a pad_str specified, it will be inserted
X`009`009at the beginning of the buffer to be printed; this is es-
X`009`009pecially useful when printing the output of put_acl().
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X                  `032
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009 0`009`009`009successful
X`009ret_val`009`009`009return code (possibly successful) from call
X`009`009`009`009to put_buf
X                                           `032
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic short put_buf(keybd_id,disp_id,buf,row,scr_width,pad_str,separator)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 ULONG`009  keybd_id,`009`009/* keyboard id for terminal`009      */
X`009 `009  disp_id;`009`009/* display id`009`009`009      */
X`009 char`009  *buf;`009`009`009/* buffer to be written`009`009      */
X`009 long`009  *row;`009`009`009/* row # where line is to be written  */
X`009 short`009  scr_width;`009`009/* width of screen being written to   */
X`009 char`009  *pad_str,`009`009/* prefix padding string`009      */
X`009 `009  separator;`009`009/* separator char for wrapping`009      */
X
X`123`009/*** put_buf ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister char`009  *tptr;`009`009/* pointer to long lines`009      */
Vstatic`009 ULONG`009  spot;`009`009`009/* used for finding word separators
X   */
Vstatic`009 USHORT`009  buf_len,`009`009/* length of current buffer`009      *
X/
X`009       `009  temp_len,`009`009/* temporary length`009`009      */
X`009`009  ret_val;`009`009/* return value holder`009`009      */
X
X
X   if(*buf == '\0')`009`009`009/* buffer is null; don't write it     */
X      return(0);
X
X   if(pad_str != NULL)`009`009`009/* if there was a pad string....      */
X      strins(buf,pad_str,0);`009`009/* .... insert it at the beginning    */
X
X   ret_val = 0;`009`009`009`009/* set default return value`009      */
V   buf_len = (USHORT) strlen(buf);`009/* get length of stuff to be written  *
X/
X
X   if(buf_len >= scr_width)`009`009/* too long for screen?`009`009      */
X   `123
X      /* the line is too long so we have to wrap it ourselves by breaking
X       * the input line up into segments that will fit on the screen
X       */
X
X      tptr = buf;
X      temp_len = scr_width;`009`009/* start with a whole line's worth    */
X      while(temp_len < buf_len)
X      `123
X`009 /* move backwards until we find a word boundary */
X
X`009 spot = (ULONG) temp_len;
X`009 while((*(tptr + spot) != separator) && (spot > 0L))
X`009    --spot;
X               `032
X`009 if(spot == 0L)`009`009`009/* couldn't find a word boundary?     */
X`009    spot = (ULONG) temp_len;`009/* reset for a whole screen width     */
X
X`009 ret_val = put_line(keybd_id,disp_id,tptr,row,(USHORT) spot,scr_width);
X
X`009 tptr += spot;`009`009`009/* start up where we left off`009      */
X`009 temp_len = spot + scr_width;`009/* get another line's worth`009      */
X      `125
X
X      /* write the last segment that wouldn't be written by the above loop */
X
X      ret_val = put_line(keybd_id,disp_id,tptr,row,(USHORT) strlen(tptr),
X`009`009`009 scr_width);
X   `125
X   else
X   `123
X      /* everything will fit on one line; just write it */
X
X      ret_val = put_line(keybd_id,disp_id,buf,row,buf_len,scr_width);
X   `125
X
X   return(ret_val);
X
X`125`009/*** put_buf ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009put_line
X
X  Purpose:`009Write the buffer to the display, checking first to see if we
X`009`009need to ask the user to type a character before continuing.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009  0`009`009`009completed successfully
X`009CANT_DISPLAY`009`009can't write line to virtual display
X                                           `032
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xshort put_line(keybd_id,disp_id,buf,row,buf_len,scr_width)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
X`009 ULONG`009  keybd_id,`009`009/* keyboard id for user's terminal    */
X`009`009  disp_id;`009`009/* where the output is to go`009      */
X`009 char`009  *buf;`009`009`009/* buffer to be written`009`009      */
X`009 long`009  *row;`009`009`009/* row where output is to go`009      */
X`009 USHORT`009  buf_len;`009`009/* length of buffer to be written     */
X`009 short`009  scr_width;`009`009/* width of screen being used`009      */
X
X`123`009/*** put_line ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xstatic`009 ULONG`009  status,`009`009/* return code status holder`009      */
X`009`009  temp;`009`009`009/* temporary value`009`009      */
Vstatic`009 USHORT`009  term_code;`009`009/* character read from keyboard`009
X      */
Xstatic $DESCRIPTOR(buf_d,"");`009`009/* buffer for outputting to screen    */
X
X
X   /* do we need refresh the screen and keep writing?  this could happen
X    * for files that might have long ACL's
X    */
X
X   if(*row >= (WORK_ROWS - 1))
X   `123
X      /* make the user type a character before we continue */
X
X      if(SMG$READ_KEYSTROKE(&keybd_id,&term_code,0,0,&disp_id,0,0)
X`009 != SS$_NORMAL)
X`009 return(CANT_DISPLAY);
X
X      /* now erase the display */
X
X      temp = (ULONG) scr_width;
X
X      if(SMG$ERASE_DISPLAY(&disp_id,&1L,&1L,&(WORK_ROWS-2),&temp)
X`009 != SS$_NORMAL)
X`009 return(CANT_DISPLAY);
X
X      *row = 1L;`009`009`009/* reset the row number`009`009      */
X   `125
X
X   /* write the buffer to the screen */
X
X   buf_d.dsc$a_pointer = buf;
X   buf_d.dsc$w_length = buf_len;
X
X   if(SMG$PUT_CHARS(&disp_id,&buf_d,row,&1L,0,0,0,0) != SS$_NORMAL)
X      return(CANT_DISPLAY);
X
X   *row += 1L;  `009`009`009/* increment the row position`009      */
X
X   return(SS$_NORMAL);
X
X`125`009/*** put_line ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009new_comm
X
X  Purpose:`009Allocate memory for a new command structure and return a
X`009`009pointer to the memory.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009ptr`009`009`009pointer to allocated memory
X`009NULL`009`009`009problems allocating memory
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic COM_DEF *new_comm()
X
X`123`009/*** new_comm ***/
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister COM_DEF  *ptr;`009`009`009/* pointer to allocated memory`009      */
X`009 ULONG`009  status;`009`009/* return code status holder`009      */
X`009 long`009  length;`009`009/* length of structure to allocate    */
X
X
X   length = (long) sizeof(COM_DEF);`009/* set up the length`009`009      */
V   status = LIB$GET_VM(&length,&ptr);`009/* allocate the memory`009`009  `032
X   */
X
X   if(status != SS$_NORMAL)
X      return(NULL);
X
X   ptr->copy_name = NULL;`009`009/* initialize the command structure   */
X   ptr->text = NULL;
X   ptr->ren_name = NULL;
X   ptr->copy_len = 0;
X   ptr->text_len = 0;
X   ptr->ren_len = 0;
X   ptr->comm_prot = 0;
X   ptr->comm_copy = 0;
X   ptr->comm_ren = 0;
X   ptr->comm_text = 0;
X   ptr->comm_del = 0;
X   ptr->prot = 0;
X
X   return(ptr);`009`009`009`009/* return pointer to the structure    */
X
X`125`009/*** new_comm ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009write_text
X
X  Purpose:`009Inverted coroutine (to xecute()) to write text descriptor
X`009`009records to the text descriptor file.  A record of length
X`009`009zero signifies that the file is to be closed.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009status`009`009`009return code from SYS$ calls
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic ULONG write_text(fab,rab,text,dir_text)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Xstruct`009 FAB`009  *fab;`009`009`009/* text file FAB`009`009      */
Xstruct`009 RAB`009  *rab;`009`009`009/* text file RAB`009`009      */
X`009 char`009  *text,`009`009/* text descriptor record`009      */
X`009`009  *dir_text;`009`009/* pointer to directory text descrip. */
X
X`123`009/*** write_text ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xstatic`009 ULONG`009  status;`009`009/* return code status holder`009      */
Xstatic`009 UCHAR`009  state,`009`009/* coroutine state variable`009      */
X`009`009  file_open;`009`009/* set if file has been opened`009      */
Vstatic`009 char`009  buf[DIR_TEXT_MAX+4];`009/* for formatting header records
X      */
X
X
X   /* special check in case an attempt is made to close the text file
X    * when nothing had been written to it
X    */
X
X   if((*text == '\0') && (!file_open))
X      return(RMS$_NORMAL);
X
X   if(state == 1)`009`009`009/* perform resuming operation`009      */
X      goto lab0;
X
X   /* initialize the RMS blocks */
X
X   *fab = cc$rms_fab;`009`009`009/* initialize the RMS blocks`009      */
X   *rab = cc$rms_rab;
X
V   fab->fab$b_fac = FAB$M_PUT;`009`009/* using SYS$PUT for record I/O`009`032
X     */
X   fab->fab$w_ifi = 0;`009`009`009/* make sure to reset every time      */
X   fab->fab$b_rat = FAB$M_CR;`009`009/* carriage-return carriage control   */
X   fab->fab$l_fna = TEXT_FILE;`009`009/* set filename`009`009`009      */
X   fab->fab$b_fns = (UCHAR) strlen(TEXT_FILE);
X
X   rab->rab$l_fab = fab;`009`009/* set RAB fields`009`009      */
X   rab->rab$b_rac = RAB$C_SEQ;`009`009/* sequential access`009`009      */
X   rab->rab$l_rbf = buf;
X
X   status = SYS$CREATE(fab);`009`009/* try to create the file`009      */
X
X   if((status != RMS$_NORMAL) && (status != RMS$_FILEPURGED))
X      return(status);
X
X   status = SYS$CONNECT(rab);`009`009/* connect the RMS blocks`009      */
X
X   if(status != RMS$_NORMAL)
X   `123
X      SYS$CLOSE(fab);
X      return(status);
X   `125
X  `032
X   /* write the text descriptor file header records */
X
X   cat(buf,">>>",dir_text);`009`009/* format directory text descriptor   */
X
X   rab->rab$w_rsz = (USHORT) strlen(buf);
X   status = SYS$PUT(rab);
X
X   if(status != RMS$_NORMAL)
X   `123
X      SYS$CLOSE(fab);
X      return(status);
X   `125
X
X   /* write the spacing record to the file */
X
X   strcpy(buf,">");`009`009`009/* copy spacing record to the buffer  */
X   rab->rab$w_rsz = 1;`009`009`009/* set length of spacing record`009      */
X
X   status = SYS$PUT(rab);`009`009/* write two of them and check later  */
X   status = SYS$PUT(rab);
X
X   if(status != RMS$_NORMAL)
X   `123
X      SYS$CLOSE(fab);
X      return(status);
X   `125
X
X   state = 1;`009`009`009`009/* update coroutine state variable    */
X   file_open = 1;`009`009`009/* file successfully opened`009      */
X   rab->rab$l_rbf = text;`009`009/* ok, because text is static`009      */
X
X   /* continue writing until there is an RMS problem or until we get a record
X    * of length zero
X    */
X
X   while((status == RMS$_NORMAL) && (*text != '\0'))
X   `123
X      /* write the current record to the text descriptor file */
X
X      rab->rab$w_rsz = (USHORT) strlen(text);
X      status = SYS$PUT(rab);
X
X      if(status != RMS$_NORMAL)
X`009 SYS$CLOSE(fab);`009`009/* close it because of the error      */
X
X      return(status);`009`009`009/* return the status`009`009      */
X
Xlab0:`009`009`009`009`009/* we return here on subsequent call  */
X      continue;
X   `125
X
X   /* close the text descriptor file */
X
X   status = SYS$CLOSE(fab);`009`009/* close the text descriptor file     */
X
X   state = 0;`009`009`009`009/* make sure to reset these`009      */
X   file_open = 0;
X
X   return(status);
X
X`125`009/*** write_text ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009make_name
X
X  Purpose:`009Create the new file name for a file operation.  Insert the
X`009`009default values if they were omitted by the user.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009  0`009`009`009Everything fine
X`009 -1`009`009`009Error parsing new filename
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic short make_name(orig_name,new_name,final_name)
X`009`009`009`009`009/*******   FORMAL  PARAMETERS   *******/
Vregister char`009  *orig_name,`009`009/* name when directory was read in    *
X/
X`009`009  *new_name,`009`009/* name read when COPY/RENAME done    */
X`009`009  *final_name;`009`009/* final name`009`009`009      */
X           `032
X`123`009/*** make_name ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
X`009 char`009  *tptr;`009`009/* temporary character pointer`009      */
X`009 ULONG`009  status;`009`009/* return code status holder`009      */
X`009 long`009  i;`009`009`009/* return code from strindex()`009      */
Vstatic`009 struct`009  fscndef  items[] = `123`009/* items used for scanning
X filenames  */
V`009`009  `1230,FSCN$_NAME,0L`125,`009/* look for the filename.....`009  `032
X   */
X`009`009  `1230,FSCN$_TYPE,0L`125,`009/* ...and the file type....`009      */
X`009`009  `1230,0,0L`125`125;`009`009/* terminate the item list`009      */
Xstatic $DESCRIPTOR(file_d,"");`009`009/* descriptor for filename`009      */
X
X
X   /* parse the name the user specified when the COPY or RENAME command
X    * was issued; the missing parts must be determined in case some of
X    * the new filename has to be provided
X    */
X
V   file_d.dsc$a_pointer = new_name;`009/* set up the descriptor first`009`032
X     */
X   file_d.dsc$w_length = (USHORT) strlen(new_name);
X
X   status = SYS$FILESCAN(&file_d,items,0);
X
X   if(status != SS$_NORMAL)
X      return(-1);
X
X   /* now determine if we have to insert the filename and/or the file
X    * type for the user
X    */
X
X   if((items[0].fscn$w_length != 0) && (items[1].fscn$w_length != 0))
X   `123
X      /* we don't have to do anything; just copy it to the newname */
X
X      strcpy(final_name,new_name);
X   `125
X   else if((items[0].fscn$w_length == 0) && (items[1].fscn$w_length == 0))
X   `123
X      /* neither the filename nor the filetype was specified; we cat them
X       * on to the current filename
X       */
X
X      cat(final_name,new_name,orig_name);
X      i = (long) strindex(final_name,";");
V      *(final_name + i) = '\0';`009`009/* lop off the version number`009 `032
X    */
X   `125
X   else if(items[1].fscn$w_length == 0)
X   `123
X      /* the filename was specified, the filetype was not; this defaults to
X       * a .LIS filetype
X       */
X
X      /* make sure we terminate the filename in the new name */
X
X      tptr = (char *) items[0].fscn$l_addr;
X      tptr[items[0].fscn$w_length] = '\0';
X
V      cat(final_name,new_name,".LIS");`009/* make the new filename`009      *
X/
X   `125
X   else
X   `123                                                  `032
X      /* the filetype was specified but the filename was not; copy the
X       * filename part from the original filename
X       */
X
X      i = (ptrdiff_t) ((char *) items[1].fscn$l_addr - new_name);
X
V      strcpy(final_name,new_name);`009/* first copy the new name in`009  `032
X   */
V      tptr = strchr(orig_name,'.');`009/* lop off everything except......`032
X   */
X      *tptr = '\0';`009`009`009/* ..... the filename`009`009      */
V      strins(final_name,orig_name,i);`009/* insert the filename in the final
X   */
X      *tptr = '.';`009`009`009/* put orig_name back the way it was  */
X   `125
X
X   return(0);
X
X`125`009/*** make_name ***/
X/*eject*/
V/****************************************************************************
X***
V*****************************************************************************
X***
X
X  Function:`009banynstr
X
X  Purpose:`009Determine if a finite-length character string contains
X`009`009any characters from a second null-terminated character
X`009`009string.
X
X  Global variables:
X
X`009Name`009`009`009Examine/Modify/Use/Read/Write
X`009----`009`009`009-----------------------------
X`009none
X
X  Return Codes:
X
X`009Code`009`009`009Reason
X`009----`009`009`009------
X`009 >=0`009`009`009match was found; return code is the offset
X`009`009`009`009into str1 where the character is found
X`009  -1`009`009`009no common characters in the two strings
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
Xstatic short banynstr(str1,str2,length)
X`009`009  `009`009`009/*******   FORMAL  PARAMETERS   *******/
Xregister char`009  *str1,`009`009/* string to search`009`009      */
X`009`009  *str2;`009`009/* what to look for`009`009      */
X`009 short`009  length;`009`009/* when to stop searching`009      */
X
X`123`009/*** banynstr ***/
X`009`009`009`009`009/********   LOCAL  VARIABLES   ********/
Xregister int`009  offset1,`009`009/* offset into string str1`009      */
X`009`009  offset2;`009`009/* offset into string str2`009      */
X
X
X   if(str1 == NULL `124`124 str2 == NULL `124`124 length <= 0)
X      return(-1);
X
X   if((*str1 == '\0') `124`124 (*str2 == '\0'))
X      return(-1);
X
X   offset1 = 0;
X
X   while(*(str1+offset1) != '\0' && length--)
X   `123
X      offset2 = 0;
X      while(*(str2+offset2) != '\0')
X      `123
X`009 if(*(str1+offset1) == *(str2+offset2))
X`009 `123
X`009    return(offset1);`009`009/* match found; return offset`009      */
X`009 `125
X`009 ++offset2;
X      `125
X      ++offset1;
X   `125
X
X   return(-1);`009`009`009`009/* no match; return -1`009`009      */
X
X`125`009/*** banynstr ***/
$ GOSUB UNPACK_FILE

$ FILE_IS = "MINE.CLD"
$ CHECKSUM_IS = 594881856
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
Xdefine type sort_options
X`009keyword`009date
X`009keyword`009filename
X`009keyword`009size
X`009keyword type
X
Xdefine verb maint
X`009image disk$acc:[peirce.bin.decus]maint.exe
X`009parameter p1,value(type=$infile),label=infile
X`009qualifier confirm`009placement=global
X`009qualifier date`009`009placement=global
X`009qualifier full`009`009placement=global
X`009qualifier help`009`009placement=global
X`009qualifier protection`009placement=global
X`009qualifier size`009`009placement=global
X`009qualifier sort`009`009placement=global,value(type=sort_options)
X`009qualifier text`009`009placement=global
X`009qualifier wide`009`009placement=global
X`009disallow full and date
X`009disallow full and size
X`009disallow full and protection
$ GOSUB UNPACK_FILE

$ FILE_IS = "SUBS.C"
$ CHECKSUM_IS = 673245188
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
V/****************************************************************************
X**
V*****************************************************************************
X**
X
X   Site:`009Western Michigan University Academic Computer Center
X
X   System:`009Directory/File Maintenance
X `032
X   Program:`009MAINT
X
X   Version=01`009Level=01`00908/05/88`009Leonard J. Peirce
X
X   Purpose:`009General-purpose C subroutines.
X
X   Arguments:`009See descriptions for individual routines.
X
X   External variables:`009none
X
X   WMU external functions:
X
X          Defined:`009banystr,cat,strindex,strins,strmcpy
X
X          Called:
X
X   Files accessed:`009none
X
X   Return codes:`009See descriptions for individual routines
X
X   Compiling instructions:`009$ CC SUBS.C/OPTIMIZE
X
X   Linking instructions:`009See linking instructions for MAINT.C
X
V*****************************************************************************
X***
V*****************************************************************************
X**/
X
V/****************************************************************************
X**/
V/*                                                                       `032
X    */
V/*                        # I N C L U D E   F I L E S                    `032
X    */
V/*                                                                       `032
X    */
V/****************************************************************************
X**/
X
X#ifdef unix
X#include <stdio.h>`009`009`009/* to get define for NULL`009      */
X#include <varargs.h>`009`009`009/* variable-length argument header    */
X#else
X#include stdio`009`009`009`009/* to get define for NULL`009      */
X#include varargs`009`009`009/* variable-length argument header    */
X#endif
X
V/****************************************************************************
X**/
V/*                                                                       `032
X    */
V/*                             # D E F I N E S                           `032
X    */
V/*                                                                       `032
X    */
V/****************************************************************************
X**/
X
X
-+-+-+-+-+ End of part 10 +-+-+-+-+-

