From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 17-MAR-1992 19:04:45.49
To:	ARISIA::EVERHART
CC:	
Subj:	Re: utime on VMS

From:	RELAY-INFO-VAX@CRVAX.SRI.COM@SMTP@CRDGW2
To:	Everhart@Arisia@MRGATE

Received:  by crdgw1.ge.com (5.57/GE 1.123)
	 id AA11809; Tue, 17 Mar 92 17:52:50 EST
Received: From UCBVAX.BERKELEY.EDU by CRVAX.SRI.COM with TCP; Tue, 17 MAR 92 14:39:54 PST
Received: by ucbvax.Berkeley.EDU (5.63/1.43)
	id AA09330; Tue, 17 Mar 92 14:21:44 -0800
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: 16 Mar 92 08:17:02 GMT
From: micro-heart-of-gold.mit.edu!news.bbn.com!usc!zaphod.mps.ohio-state.edu!sol.ctr.columbia.edu!bronze!arenn@bloom-beacon.mit.edu  (Aaron M. Renn)
Organization: Indiana University
Subject: Re: utime on VMS
Message-Id: <1992Mar16.081702.4731@bronze.ucs.indiana.edu>
References: <1992Mar15.220608.13272@umbc3.umbc.edu>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

In article <1992Mar15.220608.13272@umbc3.umbc.edu> cs635124@umbc5.umbc.edu (cs635124) writes:
>   Is there a VMS equivalent of the unix function utime() (to update the
>access/modification times of a file)?  My VMS manual references something
>called C$VAXCIO, but gives no indication how to link to it or where header
>files might be.  I've been told that I can get this functionality by mucking
>with RMS, but I'd rather not :)

Here is my VMS VAXC version of the Unix "touch" program.  It can be used to
update/set the revision, creation, backup, or expiration dates of files
and comes with a full complement of VMS qualifiers (/LOG, /CREATE,
/BEFORE, /SINCE, /EXCLUDE) and a .HLP file.  Like Unix touch, it can
also be used to create a file if one does not exist.  It can be invoked
either by RUN, MCR, foreign command, or "native" command.  It compiles and
runs fine under VMS 5.4-3 and VAXC 3.1.

$! ------------------ CUT HERE -----------------------
$ v='f$verify(f$trnlnm("SHARE_VERIFY"))'
$!
$! This archive created by VMS_SHARE Version 7.1-004  3-AUG-1989
$!   On 16-MAR-1992 03:07:46.11   By user ARENN (Aaron M. Renn)
$!
$! This VMS_SHARE Written by:
$!    Andy Harper, Kings College London UK
$!
$! Acknowledgements to:
$!    James Gray       - Original VMS_SHARE
$!    Michael Bednarek - Original Concept and implementation
$!
$! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER
$! AND EXECUTE AS A COMMAND PROCEDURE  (  @name  )
$!
$! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING:
$!       1. AAAREADME.1ST;1
$!       2. ACPDEF.H;1
$!       3. DESCRIP.MMS;1
$!       4. MAKETOUCH.COM;1
$!       5. TOUCH.C;1
$!       6. TOUCH.CLD;1
$!       7. TOUCH.H;1
$!       8. TOUCH.HLP;1
$!       9. TOUCH.OPT;1
$!      10. TOUCHCMD.CLD;1
$!      11. TOUCHMSG.MSG;1
$!
$set="set"
$set symbol/scope=(nolocal,noglobal)
$f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID"))
$e="write sys$error  ""%UNPACK"", "
$w="write sys$output ""%UNPACK"", "
$ if f$trnlnm("SHARE_LOG") then $ w = "!"
$ if f$getsyi("version") .ges. "V4.4" then $ goto START
$ e "-E-OLDVER, Must run at least VMS 4.4"
$ v=f$verify(v)
$ exit 44
$UNPACK: SUBROUTINE ! P1=filename, P2=checksum
$ if f$search(P1) .eqs. "" then $ goto file_absent
$ e "-W-EXISTS, File ''P1' exists. Skipped."
$ delete/nolog 'f'*
$ exit
$file_absent:
$ if f$parse(P1) .nes. "" then $ goto dirok
$ dn=f$parse(P1,,,"DIRECTORY")
$ w "-I-CREDIR, Creating directory ''dn'."
$ create/dir 'dn'
$ if $status then $ goto dirok
$ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped."
$ delete/nolog 'f'*
$ exit
$dirok:
$ w "-I-PROCESS, Processing file ''P1'."
$ define/user sys$output nl:
$ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1'
PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET(
SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");
buff:=CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(buff))
;LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION(
BEGINNING_OF(buff));g:=0;LOOP EXITIF MARK(NONE)=END_OF(buff);x:=
ERASE_CHARACTER(1);IF g = 0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x=
"V" THEN APPEND_LINE;MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;
IF x="+" THEN g:=1;ERASE_LINE;ENDIF;ELSE IF x="-" THEN g:=0;ENDIF;ERASE_LINE;
ENDIF;ENDLOOP;p:="`";POSITION(BEGINNING_OF(buff));LOOP r:=SEARCH(p,FORWARD);
EXITIF r=0;POSITION(r);ERASE(r);COPY_TEXT(ASCII(INT(ERASE_CHARACTER(3))));
ENDLOOP;o:=GET_INFO(COMMAND_LINE,"output_file");WRITE_FILE(buff,o);
ENDPROCEDURE;Unpacker;EXIT;
$ delete/nolog 'f'*
$ CHECKSUM 'P1'
$ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT
$ e "-E-CHKSMFAIL, Checksum of ''P1' failed."
$ ENDSUBROUTINE
$START:
$ create/nolog 'f'
XTOUCH is a VMS utility for modifying the date-time attributes of files.
XIt supports a full range of qualifiers including /BEFORE, /SINCE, /EXCLUDE,
X/LOG, and /CONFIRM.  It will take a list of files and supports wildcards.
XLike UN*X touch, it can be used to create a file if one does not exists.
X
XYou should have received the following files:
X
XAAAREADME.1ST    -- This file
XACPDEF.H         -- In case your system is missing header files
XDESCRIP.MMS      -- Description file for building with MMS
XMAKETOUCH.COM    -- DCL script for compiling TOUCH
XTOUCH.C          -- The TOUCH program module
XTOUCH.CLD        -- Command definition file for TOUCH
XTOUCH.H          -- TOUCH header file
XTOUCH.HLP        -- Help file source
XTOUCH.OPT        -- Linker options file
XTOUCHCMD.CLD     -- Command definition file to be linked into the image
XTOUCHMSG.MSG     -- Message source file
X
XTo compile touch, either type @MAKETOUCH (add DEBUG as P1 to make`032
Xdebugger version) or MMS.  If you wish to make the /FORCE qualifier
X(which tells TOUCH to create the file if the specified file is not
Xfound) the default, see TOUCH.C before compiling.  There is a`032
Xpreprocessor directive you will need to uncomment.  If your system
Xis missing ATRDEF.H or FIBDEF.H, you'll have to edit the source code
Xto remove those includes and add an include for the supplied ACPDEF.H
X
XTo enable the command, edit the file TOUCH.CLD and change the Image name
Xto point to the location of TOUCH.EXE, then type SET COMMAND TOUCH.  Or,
Xyou can define a foreign command TOUCH :== $ DISK:`091DIRECTORY`093TOUCH.EXE
V.
XTouch can also be RUN and invoked via MCR (but the MCR handling is not`032
Xperfect.  Essentially, unless invoked as a "real" command, TOUCH acts as
Xthough it were invoked by the foreign command interface). `032
X
XSee the program source code for copyright and disclaimer.
XQuestions, comments, job offers to:
X
XAaron M. Renn
Xarenn@indiana.edu
Xarenn@indiana.bitnet
Xarenn@isis.cs.du.edu
$ CALL UNPACK AAAREADME.1ST;1 223505905
$ create/nolog 'f'
X/************************************************************************/
X * ACPDEF.H  --  File attribute header file for TOUCH V1.1              *
X *                                                                      *
X * This file is for use if any of the system header files are missing.  *
X * Only the QIO/ACP ones though.                                        *
X ************************************************************************/
X
X/* Stuff from FIBDEF.H */
X
X#define FIB$M_WRITE 256
X
X/* Stuff from ATRDEF.H */
X
X#define ATR$C_BAKDATE 20
X#define ATR$C_CREDATE 17
X#define ATR$C_EXPDATE 19
X#define ATR$C_REVDATE 18
X#define ATR$S_BAKDATE 8
X#define ATR$S_CREDATE 8
X#define ATR$S_EXPDATE 8
X#define ATR$S_REVDATE 8
$ CALL UNPACK ACPDEF.H;1 1699046593
$ create/nolog 'f'
X! MMS Description file for building TOUCH V1.1
X!
X! By Aaron M. Renn
X!
X
X.IFDEF DEBUG
XCFLAGS=/NOOPTIMIZE/DEBUG
XLFLAGS=/DEBUG
X.ELSE
XCFLAGS=/OPTIMIZE/NODEBUG
XLFLAGS=/TRACEBACK
X.ENDIF
X
XALL              : TOUCH.EXE, TOUCH.HLB
X      @ WRITE SYS$OUTPUT "Type SET COMMAND TOUCH to enable command."
X
XTOUCH.OBJ        : TOUCH.C, TOUCH.H
X      CC $(CFLAGS) TOUCH.C
X
XTOUCHCMD.OBJ     : TOUCHCMD.CLD
X      SET COMMAND/OBJECT TOUCHCMD.CLD
X
XTOUCHMSG.OBJ     : TOUCHMSG.MSG
X      MESSAGE/OBJECT TOUCHMSG.MSG
X
XTOUCH.EXE        : TOUCH.OBJ, TOUCHCMD.OBJ, TOUCHMSG.OBJ
X      LINK $(LFLAGS) TOUCH.OBJ, TOUCHCMD.OBJ, TOUCHMSG.OBJ, TOUCH.OPT/OPTION
VS
X
XTOUCH.HLB        : TOUCH.HLP
X      LIBRARIAN/HELP/CREATE TOUCH.HLB TOUCH.HLP
$ CALL UNPACK DESCRIP.MMS;1 906829823
$ create/nolog 'f'
X$ ! Compile touch.  By Aaron M. Renn
X$ !
X$ debug = 0
X$ if p1 .eqs. "DEBUG" then debug = 1
X$ wr := write sys$output
X$ if debug .eq. 1
X$ then
X$ wr "$ CC/NOOPTIMIZE/DEBUG/OBJECT=TOUCH.OBJ TOUCH.C"
X$ cc/nooptimize/debug/object=touch.obj touch.c
X$ else
X$ wr "$ CC/OPTIMIZE/NODEBUG/OBJECT=TOUCH.OBJ TOUCH.C"
X$ cc/optimize/nodebug/object=touch.obj touch.c
X$ endif
X$ wr "$ SET COMMAND/OBJECT=TOUCHCMD.OBJ TOUCHCMD.CLD"
X$ set command/object=touchcmd.obj touchcmd.cld
X$ wr "$ MESSAGE/OBJECT=TOUCHMSG.OBJ TOUCHMSG.MSG"
X$ message/object=touchmsg.obj touchmsg.msg
X$ if debug .eq. 1
X$ then
X$ wr "$ LINK/DEBUG TOUCH.OBJ, TOUCHMSG.OBJ, TOUCHCMD.OBJ, TOUCH.OPT/OPTIONS"
X$ link/debug touch.obj, touchmsg.obj, touchcmd.obj, touch.opt/options
X$ else
X$ wr "$ LINK TOUCH.OBJ, TOUCHMSG.OBJ, TOUCHCMD.OBJ, TOUCH.OPT/OPTIONS"
X$ link touch.obj, touchmsg.obj, touchcmd.obj, touch.opt/options
X$ endif
X$ if p2 .eqs. "DEL"
X$ then
X$ wr "$ DELETE/NOLOG/NOCONFIRM TOUCH.OBJ;*, TOUCHMSG.OBJ;*, TOUCHCMD.OBJ;*"
X$ delete/nolog/noconfirm touch.obj;*, touchmsg.obj;*, touchcmd.obj;*
X$ endif
X$ exit
$ CALL UNPACK MAKETOUCH.COM;1 1882203384
$ create/nolog 'f'
X/************************************************************************
X * TOUCH.C  --  Main program module for TOUCH V1.1                      *
X *                                                                      *
X * By Aaron M. Renn -- Copyright (c) 1992                               *
X *                                                                      *
X * This program may be freely distributed.  However, it comes AS IS,    *
X * with absolutely NO WARRANTIES.  Anyone using this program does so at *
X * his/her own risk and agrees not to hold the author responsible for   *
X * anything arising out of the use of this program.                     *
X ************************************************************************/
X
X#include <atrdef.h>
X#include <clidef.h>`032
X#include <climsgdef.h>
X#include <descrip.h>
X#include <fibdef.h>
X#include <iodef.h>
X#include <lib$routines.h>
X#include <rms.h>
X#include <ssdef.h>
X#include <stdio.h>
X#include <str$routines.h>
X#include <strdef.h>
X#include <string.h>
X#include <stsdef.h>
X
X#include "touch.h"
X
X/*#define FORCE 1*/   /* Uncomment this directive to make /FORCE the default
V */
X
X/************************************************************************/
X
Xint *c$alloc_tmp();
Xstruct dsc$descriptor *c$dsc();
Xstruct dsc$descriptor *c$ldsc();
Xvoid cksts();
Xvoid bye();
Xuquad cli_get_value();
Xint confirm();
Xvoid put_message();
Xvoid error_handler();
Xint main();
X
Xglobalref unsigned int TOUCH_CREATED, TOUCH_CREATEFAIL, TOUCH_SUMMARY,`032
X   TOUCH_TOUCHED, TOUCH_DISPFAIL, TOUCH_SEARCHFAIL, TOUCH_TOUCHFAIL,
X   TOUCH_PRGMFAULT, TOUCH_INVQUAVAL, TOUCH_TABLE;
X
Xint *c$_tmphead = (int *) 0;
X
X/************************************************************************/
X
Xint *c$alloc_tmp()
X`123
X   int *tmp;
X  `032
X   tmp = (int *) malloc(12);
X   *tmp = c$_tmphead;
X   c$_tmphead = tmp;
X   return(c$_tmphead + 1);
X`125
X
X/************************************************************************/
X
Xstruct dsc$descriptor *c$dsc(c$_string)
X   char *c$_string;
X`123
X   int *tmp;
X   struct dsc$descriptor *c$_tmpdesc;
X
X   while (c$_tmphead) `123
X      tmp = *c$_tmphead;
X      free(c$_tmphead);
X      c$_tmphead = tmp;
X      `125                    `032
X   c$_tmpdesc = (struct dsc$descriptor *) c$alloc_tmp();
X   c$_tmpdesc->dsc$w_length = strlen(c$_string);
X   c$_tmpdesc->dsc$b_dtype = DSC$K_DTYPE_T;
X   c$_tmpdesc->dsc$b_class = DSC$K_CLASS_S;
X   c$_tmpdesc->dsc$a_pointer = c$_string;
X   return(c$_tmpdesc);
X`125
X
X/************************************************************************/
X
Xstruct dsc$descriptor *c$ldsc(c$_string,c$_length)
X   char *c$_string;
X   int c$_length;
X`123
X   int *tmp;
X   struct dsc$descriptor *c$_tmpdesc;
X
X   while (c$_tmphead) `123
X      tmp = *c$_tmphead;
X      free(c$_tmphead);`032
X      c$_tmphead = tmp;
X      `125
X   c$_tmpdesc = (struct dsc$descriptor *) c$alloc_tmp();
X   c$_tmpdesc->dsc$w_length = c$_length;
X   c$_tmpdesc->dsc$b_dtype = DSC$K_DTYPE_T;
X   c$_tmpdesc->dsc$b_class = DSC$K_CLASS_S;
X   c$_tmpdesc->dsc$a_pointer = c$_string;
X   return(c$_tmpdesc);
X`125
X
X/************************************************************************/
X
Xvoid cksts(status)
X   int status;
X`123
X   if (!(status & STS$M_SUCCESS)) lib$signal(status);
X   return;
X`125
X
X/************************************************************************/
X
Xvoid bye()
X`123
X   if (c$_tmphead) free(c$_tmphead);
X   exit(0);
X`125
X
X/************************************************************************/
X
Xuquad cli_get_value(qualifier,flag)
X   char *qualifier;
X   unsigned char *flag;
X`123
X   char tmp1`09135`093, tmp2`09135`093;
X   unsigned long int status;
X   $DESCRIPTOR_D(rdesc);
X   uquad restim = `123 0, 0 `125;
X  `032
X   if (cli$present(c$dsc(qualifier)) == CLI$_PRESENT) `123
X      status = cli$get_value(c$dsc(qualifier),&rdesc);
X      if (status == CLI$_ABSENT) cksts(sys$gettim(&restim));
X      else `123
X         cksts(status);
X         strncpy(tmp1,DPTR(rdesc),DLEN(rdesc));
X         tmp1`091DLEN(rdesc)`093 = '\0';
X         if (!strcmp(tmp1,"TODAY")) `123
X            cksts(sys$asctim(0,c$ldsc(tmp2,35),0,0));
X            *(strchr(tmp2,':')-3) = '\0';
X            sprintf(tmp1,"%s 00:00:00.00",tmp2);
X            `125
X         cksts(sys$bintim(c$dsc(tmp1),&restim));
X         `125
X      *flag = TRUE;
X      `125
X   else if (cli$present(c$dsc(qualifier)) == CLI$_NEGATED)
X      *flag = TRUE;
X   else *flag = FALSE;
X   return(restim);
X`125
X
X/************************************************************************/
X
Xint confirm(filename)
X   char *filename;
X`123
X   char prompt`091256`093;
X   static unsigned char flag = 0;
X   unsigned short int reslen;
X   unsigned long int status;
X   $DESCRIPTOR_D(rdesc);
X
X   if (flag) return(TRUE);
X   sprintf(prompt,"TOUCH %s ? `091N`093: ",filename);
X   status = (lib$get_command(&rdesc,c$dsc(prompt),&reslen));
X   if (status == RMS$_EOF) return(-1);
X   cksts(status);
X   if (reslen == 0) return(FALSE);
X   switch (*DPTR(rdesc)) `123
X      case('y'): case('Y'): case('t'): case('T'): case('1'): return(TRUE);
X      case('a'): case('A'): flag = TRUE; return(TRUE);
X      case('q'): case ('Q'): return(-1);
X      default: return(FALSE);
X      `125
X`125
X
X/************************************************************************/
X
Xvoid put_message(faoarg, error_code, sts, stv)
X   char *faoarg;
X   unsigned long int *error_code, sts, stv;
X`123
X   struct `123
X      unsigned long int count, error, faocount, *faodesc, arg1, arg2;
X      `125 mesvec;
X  `032
X   if (!sts) `123 mesvec.count = 3;  mesvec.arg1 = 0; mesvec.arg2 = 0; `125
X   else `123 mesvec.count = 5; mesvec.arg1 = sts; mesvec.arg2 = stv; `125
X   mesvec.error = error_code;
X   mesvec.faocount = 1;
X   mesvec.faodesc = c$dsc(faoarg);
X   cksts(sys$putmsg(&mesvec,0,0,0));
X   return;
X`125
X
X/************************************************************************/
X
Xvoid error_handler(sigargs, mechargs)
X   unsigned long int sigargs`091`093, mechargs`091`093;
X`123
X   struct `123
X      unsigned long int count, error, faocount, args`09110`093;
X      `125 mesvec = `123 0, &TOUCH_PRGMFAULT, 0 `125;
X   unsigned char i;
X
X   mesvec.count = sigargs`0910`093;
X   for (i=1;i<=9;i++) mesvec.args`091i-1`093 = sigargs`091i`093;
X   cksts(sys$putmsg(&mesvec,0,0,0));
X   bye();
X`125
X
X/************************************************************************/
X
Xmain()
X`123
X   CLIDEF1 cli;
X   char tmp`091NAM$C_MAXRSS`093, filename`091NAM$C_MAXRSS`093, expname`091NA
VM$C_MAXRSS`093,`032
X      resname`091NAM$C_MAXRSS`093, exnames`09150`093`091NAM$C_MAXRSS`093, i;
X   unsigned long int count = 0, status, reslen, temp;
X   unsigned short int chan, excount;
X   struct dsc$descriptor tmpdsc;
X   $DESCRIPTOR_D(rdesc);
X   quadptr modtim;
X   struct `123
X      uquad backup, create, expire, revise, before, since;
X      `125 times, times2;
X   struct `123
X      unsigned char log, confirm, force, display, backup, create, expire,`03
V2
X         revise, version, exclude, before, since, made;
X      `125 flags;
X   FAB fab;
X   NAM nam;
X   IOSB iosb;
X   FIB fib;`032
X   const FIB nullfib = `123 0, 0, 0 `125;
X   const FIBDESC fib_desc = `123 sizeof(fib), &fib `125;
X   const ACB acb`0915`093 =`032
X      `123`123 ATR$S_BAKDATE, ATR$C_BAKDATE, &times2.backup `125,
X       `123 ATR$S_CREDATE, ATR$C_CREDATE, &times2.create `125,
X       `123 ATR$S_EXPDATE, ATR$C_EXPDATE, &times2.expire `125,
X       `123 ATR$S_REVDATE, ATR$C_REVDATE, &times2.revise `125,
X       `123 0, 0, 0 `125`125;
X
X   lib$establish(error_handler);
X
X/* First find out how we were invoked.  A status of 0 means by CLI verb
X   If we want, the actual name of the verb is in the descriptor cli$q_rqdesc
V.
X   If a foreign command, mcr, or run, we do dcl parsing ourselves. Oh, the
X   cli$b_rqstat contains a code for the verb, too. Check out cliverbdef.h */
X
X   cli.cli$b_rqtype = CLI$K_GETCMD;
X   sys$cli(&cli);
X   if (cli.cli$b_rqstat) `123
X      cksts(lib$get_foreign(c$ldsc(filename,256),0,&reslen,0));
X      filename`091reslen`093 = '\0';
X      sprintf(tmp,"TOUCH %s",filename);
X      lib$establish(lib$sig_to_ret);
X      status = cli$dcl_parse(c$dsc(tmp),&TOUCH_TABLE,lib$get_command,
X         lib$get_command,0);
X      if ((status == RMS$_EOF) `124`124 (status == CLI$_NOCOMD)) bye();
X      cksts(status);
X      lib$establish(error_handler);
X      `125
X
X   if (cli$present(c$dsc("LOG")) == CLI$_PRESENT) flags.log = TRUE;
X      else flags.log = FALSE;
X   if (cli$present(c$dsc("CONFIRM")) == CLI$_PRESENT) flags.confirm = TRUE;
X      else flags.confirm = FALSE;
X   if (cli$present(c$dsc("DISPLAY")) == CLI$_PRESENT) flags.display = TRUE;
X      else flags.display = FALSE;
X
X#ifndef FORCE
X   if (cli$present(c$dsc("FORCE")) == CLI$_PRESENT) flags.force = TRUE;
X      else flags.force = FALSE;
X#else
X   if (cli$present(c$dsc("FORCE")) == CLI$_NEGATED) flags.force = FALSE;
X      else flags.force = TRUE;
X#endif
X
X/* Truly the lazy man's way out.  I just delcared a 50 element string array
X   to handle excluded filenames.  I doubt there's anybody out there who'd
X   list 50 exclude files.  If there is, that person's in trouble, if not,
X   I'm just wasting a chunk of memory.  I'll fix this one of these days */
X
X   if (cli$present(c$dsc("EXCLUDE")) == CLI$_PRESENT) `123
X      while(cli$get_value(c$dsc("EXCLUDE"),&rdesc) & STS$M_SUCCESS) `123
X         strncpy(exnames`091excount`093,DPTR(rdesc),DLEN(rdesc));
X         exnames`091excount`093`091DLEN(rdesc)`093 = '\0';
X         fab = cc$rms_fab;
X         nam = cc$rms_nam;
X         fab.fab$l_fna = exnames`091excount`093;
X         fab.fab$b_fns = strlen(exnames`091excount`093);
X         fab.fab$l_nam = &nam;
X         nam.nam$l_esa = expname;
X         nam.nam$b_ess = NAM$C_MAXRSS;
X         status = sys$parse(&fab,0,0);
X         if (status != RMS$_NORMAL) `123
X            put_message(exnames`091excount`093,&TOUCH_INVQUAVAL,fab.fab$l_st
Vs,
X               fab.fab$l_stv);
X            bye();
X            `125
X         strncpy(exnames`091excount`093,expname,nam.nam$b_esl);
X         exnames`091excount`093`091nam.nam$b_esl`093 = '\0';
X         if (exnames`091excount`093`091nam.nam$b_esl-1`093 == ';')
X            strcat(exnames`091excount`093,"*");
X         if (strstr(exnames`091excount`093,"...") != NULL) `123
X            strcpy(tmp,strstr(exnames`091excount`093,"..."));
X            exnames`091excount`093`091strlen(exnames`091excount`093)-strlen(
Vtmp)`093='\0';
X            strcat(exnames`091excount`093,"*");
X            strcat(exnames`091excount`093,strchr(tmp,'`093'));
X            `125
X         ++excount;
X         if (excount == 50) break; /* Blech! */
X         `125
X      --excount;
X      flags.exclude = TRUE;
X      `125
X   else flags.exclude = FALSE;
X
X   times.backup = cli_get_value("BACKUP_DATE",&flags.backup);
X   times.create = cli_get_value("CREATION_DATE",&flags.create);
X   times.expire = cli_get_value("EXPIRATION_DATE",&flags.expire);
X   times.revise = cli_get_value("REVISION_DATE",&flags.revise);
X   times.before = cli_get_value("BEFORE",&flags.before);
X   times.since = cli_get_value("SINCE",&flags.since);
X
X   if (flags.before `124`124 flags.since) `123
X      cksts(cli$get_value(c$dsc("MODIFIER"),&rdesc));
X      switch(*DPTR(rdesc)) `123
X         case ('B'): modtim.l0 = &times2.backup.l0;
X                     modtim.l1 = &times2.backup.l1;
X                     break;
X         case ('C'): modtim.l0 = &times2.create.l0;
X                     modtim.l1 = &times2.create.l1;
X                     break;
X         case ('E'): modtim.l0 = &times2.expire.l0;
X                     modtim.l1 = &times2.expire.l1;
X                     break;
X         default:    modtim.l0 = &times2.revise.l0;
X                     modtim.l1 = &times2.revise.l1;
X         `125
X      `125
X
X/* If no time qualifiers are present, default to revision and use`032
X   current time since we have to do something. */
X
X   if ((!flags.backup) && (!flags.create) && (!flags.expire) &&`032
X      (!flags.revise) && (!flags.display)) `123
X      flags.revise = TRUE;
X      cksts(sys$gettim(&times.revise));
X      `125
X
X   if (cli$present(c$dsc("FILENAME")) != CLI$_PRESENT) `123 /* Just in case.
V */
X      lib$establish(lib$sig_to_ret);
X      lib$signal(CLI$_INSFPRM);
X      `125
X
X   while(cli$get_value(c$dsc("FILENAME"),&rdesc) & STS$M_SUCCESS) `123
X      strncpy(filename,DPTR(rdesc),DLEN(rdesc));
X      filename`091DLEN(rdesc)`093 = '\0';
X
X      fab = cc$rms_fab;           `032
X      nam = cc$rms_nam;
X      nam.nam$l_esa = expname;    `032
X      nam.nam$b_ess = NAM$C_MAXRSS;
X      nam.nam$l_rsa = resname;
X      nam.nam$b_rss = NAM$C_MAXRSS;
X      fab.fab$l_fna = filename;
X      fab.fab$b_fns = strlen(filename);
X      fab.fab$l_nam = &nam;
X
X      status = sys$parse(&fab,0,0);
X      if (!(status & STS$M_SUCCESS)) `123
X         put_message(filename,&TOUCH_SEARCHFAIL,fab.fab$l_sts,fab.fab$l_stv)
V;
X         continue;
X         `125
X      expname`091nam.nam$b_esl`093 = '\0';
X  `032
X      for (;;) `123
X         status = sys$search(&fab,0,0);
X         resname`091nam.nam$b_rsl`093 = '\0';
X
X         if (status == RMS$_NMF) break;
X
X         if (flags.exclude) `123
X            temp = status;
X            DESC(tmpdsc,resname);
X            status = STR$_NOMATCH;
X            for (i = 0; i <= excount; i++) `123
X               status = str$match_wild(&tmpdsc,c$dsc(exnames`091i`093));
X               if (status == STR$_NOMATCH) continue;
X               break;
X               `125
X            if (status == STR$_MATCH) continue;
X            status = temp;
X            `125
X
X         if ((status == RMS$_FNF) && (!flags.force)) `123
X            put_message(expname,&TOUCH_SEARCHFAIL,fab.fab$l_sts,
X               fab.fab$l_stv);
X            break;
X            `125
X
X         if ((status != RMS$_NORMAL) && (status != RMS$_FNF)) `123
X            put_message(expname,&TOUCH_SEARCHFAIL,fab.fab$l_sts,fab.fab$l_st
Vv);
X            break;
X            `125
X
X         flags.made = FALSE;
X         fib = nullfib;
X
X /* Set the FIB for appropriate operation.  Must not have write access set o
Vn
X    display or our read attempt will bomb if we're not the owner of the file
X    or privileged user. */
X
X         if ((flags.backup) `124`124 (flags.create) `124`124 (flags.expire)
V `124`124
X            (flags.revise)) fib.fib$l_acctl = FIB$M_WRITE;
X
X         /* Copy the directory ID from the NAM block */
X         for (i=0;i<3;i++) fib.fib$w_did`091i`093 = nam.nam$w_did`091i`093;
X
X         /* Get the device name and assign an IO channel */
X         strncpy(tmp,nam.nam$l_dev,nam.nam$b_dev);
X         tmp`091nam.nam$b_dev`093 = '\0';
X         cksts(sys$assign(c$dsc(tmp),&chan,0,0));
X
X         /* Get the filename in form NAME.TYPE;VERSION from NAM block */
X         strncpy(tmp,nam.nam$l_name,nam.nam$b_name);
X         tmp`091nam.nam$b_name`093 = '\0';
X         strcat(tmp,nam.nam$l_type);
X         tmp`091nam.nam$b_name+nam.nam$b_type`093 = '\0';
X         strcat(tmp,nam.nam$l_ver);
X         tmp`091nam.nam$b_name+nam.nam$b_type+nam.nam$b_ver`093 = '\0';
X
X         /* Access the file and get info.  Note that the FIB is passed
X            by descriptor */
X         cksts(sys$qiow(0,chan,IO$_ACCESS`124IO$M_ACCESS,&iosb,0,0,&fib_desc
V,
X            c$dsc(tmp),0,0,&acb,0));
X
X         if (flags.before)
X            if (*modtim.l1 > times.before.l1) status = 0;
X               else if ((*modtim.l1 == times.before.l1) &&`032
X                  (*modtim.l0 >= times.before.l0)) status = 0;
X         if (flags.since)
X            if (*modtim.l1 < times.since.l1) status = 0;
X               else if ((*modtim.l1 == times.since.l1) &&
X                  (*modtim.l0 <= times.since.l0)) status = 0;
X         if (!status) `123
X            if (iosb.status & STS$M_SUCCESS)
X               cksts(sys$qiow(0,chan,IO$_DEACCESS,0,0,0,&fib_desc,0,0,0,&acb
V,0));
X            cksts(sys$dassgn(chan));
X            continue;
X            `125
X
X         if (flags.confirm) `123`032
X            i = confirm(resname);
X            if (i != 1) `123
X               if (iosb.status & STS$M_SUCCESS)
X                  cksts(sys$qiow(0,chan,IO$_DEACCESS,&iosb,0,0,&fib_desc,0,0
V,0,
X                     &acb,0));
X               cksts(sys$dassgn(chan));
X               if (i == -1) bye();
X               continue;
X               `125
X            `125
X
X         if ((iosb.status == SS$_NOSUCHFILE) && (flags.force)) `123
X            cksts(sys$qiow(0,chan,IO$_CREATE`124IO$M_CREATE,&iosb,0,0,&fib_d
Vesc,
X               c$dsc(tmp),0,0,&acb,0));
X            if (!(iosb.status & STS$M_SUCCESS)) `123
X               put_message(resname,&TOUCH_CREATEFAIL,iosb.status,0);
X               cksts(sys$dassgn(chan));
X               break;
X               `125
X            cksts(sys$qiow(0,chan,IO$_ACCESS`124IO$M_ACCESS,&iosb,0,0,&fib_d
Vesc,
X               c$dsc(tmp),0,0,&acb,0));
X            flags.made = TRUE; /* So that we show the right /LOG value */
X            `125
X
X         if (!(iosb.status & STS$M_SUCCESS)) `123
X            if ((flags.display) && ((!flags.backup) `124`124 (!flags.create)
V `124`124
X               (!flags.expire) `124`124 (!flags.revise)))
X                  put_message(resname,&TOUCH_DISPFAIL,iosb.status,0);
X            else put_message(resname,&TOUCH_TOUCHFAIL,iosb.status,0);
X            cksts(sys$dassgn(chan));
X            continue;
X            `125
X
X         if (flags.backup) times2.backup = times.backup;`032
X         if (flags.create) times2.create = times.create;  `032
X         if (flags.expire) times2.expire = times.expire;  `032
X         if (flags.revise) times2.revise = times.revise;`032
X
X      /* When we deaccess the file, our modified acb will be written back`03
V2
X         with the new times if we changed anything, if not, nothing will be
X         changed, not even the revision time. */
X
X         cksts(sys$qiow(0,chan,IO$_DEACCESS,&iosb,0,0,&fib_desc,0,0,0,&acb,0
V));
X
X         if (!(iosb.status & STS$M_SUCCESS)) `123
X            if (flags.display) lib$signal(iosb.status);
X            put_message(resname,&TOUCH_TOUCHFAIL,iosb.status,0);
X            cksts(sys$dassgn(chan));
X            continue;
X            `125
X
X         cksts(sys$dassgn(chan));
X         ++count;
X
X         if (flags.display) `123
X            fprintf(stdout,"%s\n",resname);
X            cksts(sys$asctim(&reslen,c$ldsc(tmp,255),&times2.backup,0));
X            tmp`091reslen`093 = '\0';
X            fprintf(stdout,"    Backup:     %s\n",tmp);
X            cksts(sys$asctim(&reslen,c$ldsc(tmp,255),&times2.create,0));
X            tmp`091reslen`093 = '\0';
X            fprintf(stdout,"    Creation:   %s\n",tmp);
X            cksts(sys$asctim(&reslen,c$ldsc(tmp,255),&times2.expire,0));
X            tmp`091reslen`093 = '\0';
X            fprintf(stdout,"    Expiration: %s\n",tmp);
X            cksts(sys$asctim(&reslen,c$ldsc(tmp,255),&times2.revise,0));
X            tmp`091reslen`093 = '\0';
X            fprintf(stdout,"    Revision:   %s\n\n",tmp);
X            `125
X
X         if (flags.log)
X            if (!flags.made) put_message(resname,&TOUCH_TOUCHED,0,0);
X            else put_message(resname,&TOUCH_CREATED,0,0);
X         `125
X      `125
X   if ((flags.log) && (count > 1)) `123
X      sprintf(tmp,"%d",count);
X      put_message(tmp,&TOUCH_SUMMARY,0,0);
X      `125
X
X   bye();
X`125
$ CALL UNPACK TOUCH.C;1 107543453
$ create/nolog 'f'
X! TOUCH.CLD -- Command definition file for TOUCH V1.1
X!              For adding to command table
X!`032
X! By Aaron M. Renn
X!
X
XIdent "TOUCH.CLD V1.1"
X
XDefine Verb TOUCH
X         `032
X      Image $DISK54:`091ARENN.COMFILES`093TOUCH.EXE
X
X      Parameter P1
X         Label=FILENAME,
X         Value (Type=$INFILE, Required, Impcat, List),`032
X         Prompt="File"
X
X      Qualifier BACKUP_DATE,
X         Negatable,
X         Value (Type=$DATETIME)
X
X      Qualifier CREATION_DATE,
X         Negatable,
X         Value (Type=$DATETIME)
X
X      Qualifier EXPIRATION_DATE,
X         Negatable,
X         Value (Type=$DATETIME)
X
X      Qualifier REVISION_DATE,
X         Negatable,`032
X         Value (Type=$DATETIME)
X
X      Qualifier BEFORE,
X         Nonnegatable,
X         Value (Type=$DATETIME, Default="TODAY")
X
X      Qualifier SINCE,
X         Nonnegatable,`032
X         Value (Type=$DATETIME, Default="TODAY")
X
X      Qualifier MODIFIER,`032
X         Default,`032
X         Nonnegatable,`032
X         Value (Type=MOD_TYPES, Default="R")
X
X      Qualifier EXCLUDE
X         Nonnegatable,
X         Value (Required, List)
X
X      Qualifier CONFIRM,`032
X         Negatable
X
X      Qualifier FORCE,`032
X         Negatable
X
X      Qualifier LOG,`032
X         Negatable
X
X      Qualifier DISPLAY,`032
X         Nonnegatable
X
X      Define Type MOD_TYPES
X         Keyword BACKUP_DATE
X         Keyword CREATION_DATE
X         Keyword EXPIRATION_DATE
X         Keyword REVISION_DATE
$ CALL UNPACK TOUCH.CLD;1 288178586
$ create/nolog 'f'
X/************************************************************************
X * TOUCH.H -- Header file for TOUCH V1.1                                *
X *                                                                      *
X * By Aaron M. Renn                                                     *
X *                                                                      *
X * This header file contains various typedefs, structure definitions,   *
X * and macros used in the main program module TOUCH.C of course         *
X ************************************************************************/
X
X#ifndef ___TOUCH_LOADED
X#define ___TOUCH_LOADED
X
X#include <clidef.h>
X#include <rms.h>
X
X#ifndef TRUE
X#define TRUE  (1)
X#endif
X#ifndef FALSE
X#define FALSE (0)
X#endif
X
X#define DLEN(x)  (x).dsc$w_length
X#define DPTR(x)  (x).dsc$a_pointer
X
X#define $DESCRIPTOR_D(x)  struct dsc$descriptor x = `123 0, DSC$K_DTYPE_T, \
X                          DSC$K_CLASS_D, 0 `125
X
X#define DESC(x,y) (x).dsc$w_length = strlen(y); \
X                  (x).dsc$b_dtype = DSC$K_DTYPE_T; \
X                  (x).dsc$b_class = DSC$K_CLASS_S; \
X                  (x).dsc$a_pointer = (y)
X
Xtypedef struct `123                  /* Quadword time structure */
X   unsigned long int l0, l1;
X   `125 uquad;
X
Xtypedef struct `123
X   unsigned long int *l0, *l1;
X   `125 quadptr;
X
Xtypedef struct `123                  /* IO status block */
X   unsigned short int status, size;
X   unsigned long int device_info;
X   `125 IOSB;
X
Xtypedef struct `123                  /* File access control block */
X   unsigned short int atr$w_size, atr$w_type;
X   unsigned long int *atr$l_addr;
X   `125 ACB;
X
Xtypedef struct `123                  /* My own short File Identification Blo
Vck */
X   unsigned long int fib$l_acctl;
X   unsigned short int fib$w_fid`0913`093, fib$w_did`0913`093;
X   `125 FIB;
X
Xtypedef struct `123                   /* FIB descriptor */
X   unsigned long int fib$l_len, *fib$l_addr;
X   `125 FIBDESC;
X  `032
Xtypedef struct clidef1 CLIDEF1;   /* CLI structure  */
Xtypedef struct FAB FAB;           /* RMS structures */
Xtypedef struct NAM NAM;`032
Xtypedef struct XABDAT XABDAT;
X
X#endif                            /* End TOUCH.H */
$ CALL UNPACK TOUCH.H;1 2019904403
$ create/nolog 'f'
X1 TOUCH
X
X   The TOUCH command will display or modifiy date-time attributes of files.
X   Wildcards are allowed in filenames.  Date specifications follow the`032
X   rules found in the VMS DCL Concepts Manual.  Modification of file`032
X   attributes requires ownership of the file or access privileges.
X
X   Format
X
X       TOUCH filespec`091,...`093
X
X2 Parameter
X
X   filespec`091,...`093
X
X      Specifies the name of one or more files whose attributes are to be
X      displayed or modified.  Wildcards are permitted, where an
X      asterisk (*) matches zero or more characters and a percent sign
X      (%) matches any one character.  This pararmeter is required.
X
X2 Qualifiers                                                    `032
X     `032
X /BACKUP_DATE
X
X         /BACKUP_DATE`091=time`093
X         /NOBACKUP_DATE
X
X      Sets the backup date on the file(s) equal to the specified time.
X      If no value is given, the default is to use the current date and
X      time.  If /NOBACKUP_DATE is specified, the backup date is set to
X      the VMS base date of 17-NOV-1858 00:00:00.00.
X
X /BEFORE
X  `032
X         /BEFORE`091=time`093
X
X      Selects only those files dated prior to the specified time.  The
X      default date to compare this time against in selecting files is`032
X      the revision date, but this can be changed with the /MODIFIER`032
X      qualifier.  If no time is specified, the default value is TODAY.
X
X /CONFIRM
X     `032
X         /CONFIRM
X         /NOCONFIRM  (default)
X  `032
X      Controls whether or not a confirmation request is given before
X      modifying the file.  The default is not to do so.  This qualifier
X      functions somewhat differently than the confirm qualifier in other
X      VMS utilities (such as DELETE and RENAME).  Valid affirmative
X      responses are YES, TRUE, and 1, however, only the first letter is
X      significant.  Any response beginning with Y, for example, will be
X      considered as YES.  Pressing the control-z key or typing QUIT (again,
X      only the first letter is significant) aborts the command.  Entering
X      ALL (first letter only significant), will modify any remaining files
X      without further confirmation prompts.  Any other response will be`032
X      treated as a negative response.
X
X /CREATION_DATE
X
X         /CREATION_DATE`091=time`093
X         /NOCREATION_DATE
X
X      Sets the creation date on the file(s) equal to the specified time.
X      If no value is given, the default is to use the current date and
X      time.  If /NOCREATION_DATE is specified, the creation date is set
X      the VMS base date of 17-NOV-1858 00:00:00.00.
X
X /DISPLAY
X
X         /DISPLAY
X
X      This qualifer is used to display the various attributes of the`032
X      specified files.
X
X /EXCLUDE
X
X         /EXCLUDE=(filespec`091,...`093)
X
X      A list of files that are not to be modified or displayed.  Wildcards
X      are permitted.  If only one file is specified, the parentheses may
X      be omitted.
X
X /EXPIRATION_DATE
X
X         /EXPIRATION_DATE`091=time`093
X         /NOEXPIRATION_DATE
X
X      Sets the expiration date on the file(s) equal to the specified time.
X      If no value is given, the default is to use the current date and
X      time.  If /NOEXPIRATION_DATE is specified, the file is set not to
X      have an expiration date.
X
X /FORCE
X
X         /FORCE
X         /NOFORCE   (normal default)
X
X      This qualifier determines whether or not to create a file using the
X      specified attributes if the given filename is not found. `032
X      This qualifier will not create a directory path to the file. If the`03
V2
X      file(s) are found, this qualifer has no effect.  If you do not
X      specify a creation date with the /CREATION_DATE qualifier, the file
X      will be created with a date of 17-NOV-1858 00:00:00.00.  The normal`03
V2
X      default is /NOFORCE, but this can be changed at compile time.
X
X /LOG
X        `032
X         /LOG
X         /NOLOG   (default)
X
X      Controls whether or not an informational message is displayed when
X      a file is successfully modified.
X
X /MODIFIER
X
X         /MODIFIER`091=keyword`093
X
X      This qualifier is used in conjunction with /BEFORE and /SINCE to`032
X      select which date-time value is to be used in selecting files.
X      The default is to use the revision date, in which case this`032
X      qualifier may be omitted.  The valid keywords are BACKUP_DATE,
X      CREATION_DATE, EXPIRATION_DATE, and REVISION_DATE.
X
X /REVISION_DATE
X
X         /REVISION_DATE`091=time`093
X         /NOREVISON_DATE
X
X      Sets the revision date on the file(s) equal to the specified time.
X      If no time value is given, the default is to use the current date
X      and time.  If /NOREVISION_DATE is specified, the revision date is
X      set to the VMS base date of 17-NOV-1858 00:00:00.00.  If no other`032
X      time modification qualifers are present and the /DISPLAY qualifier`032
X      is also absent, this qualifier is present by default with a value`032
X      equal to the current time.
X
X /SINCE                                          `032
X
X         /SINCE`091=time`093
X
X      Selects only those files that are dated after the specified date.
X      The default date to compare this time agains when selecting files`032
X      is the revision date, but this can be changed with the /MODIFIER`032
X      qualifier.  If no time is specified, the default is TODAY.
X
X2 /BACKUP_DATE
X
X         /BACKUP_DATE`091=time`093
X         /NOBACKUP_DATE
X
X      Sets the backup date on the file(s) equal to the specified time.
X      If no value is given, the default is to use the current date and
X      time.  If /NOBACKUP_DATE is specified, the backup date is set to
X      the VMS base date of 17-NOV-1858 00:00:00.00.
X
X2 /BEFORE
X  `032
X         /BEFORE`091=time`093
X
X      Selects only those files dated prior to the specified time.  The
X      default date to compare this time against in selecting files is`032
X      the revision date, but this can be changed with the /MODIFIER`032
X      qualifier.  If no time is specified, the default value is TODAY.
X
X2 /CONFIRM
X     `032
X         /CONFIRM
X         /NOCONFIRM  (default)
X  `032
X      Controls whether or not a confirmation request is given before
X      modifying the file.  The default is not to do so.  This qualifier
X      functions somewhat differently than the confirm qualifier in other
X      VMS utilities (such as DELETE and RENAME).  Valid affirmative
X      responses are YES, TRUE, and 1, however, only the first letter is
X      significant.  Any response beginning with Y, for example, will be
X      considered as YES.  Pressing the control-z key or typing QUIT (again,
X      only the first letter is significant) aborts the command.  Entering
X      ALL (first letter only significant), will modify any remaining files
X      without further confirmation prompts.  Any other response will be`032
X      treated as a negative response.
X
X2 /CREATION_DATE
X
X         /CREATION_DATE`091=time`093
X         /NOCREATION_DATE
X
X      Sets the creation date on the file(s) equal to the specified time.
X      If no value is given, the default is to use the current date and
X      time.  If /NOCREATION_DATE is specified, the creation date is set
X      the VMS base date of 17-NOV-1858 00:00:00.00.
X
X2 /DISPLAY
X
X         /DISPLAY
X
X      This qualifer is used to display the various attributes of the`032
X      specified files.
X
X2 /EXCLUDE
X
X         /EXCLUDE=(filespec`091,...`093)
X
X      A list of files that are not to be modified or displayed.  Wildcards
X      are permitted.  If only one file is specified, the parentheses may
X      be omitted.
X
X2 /EXPIRATION_DATE
X
X         /EXPIRATION_DATE`091=time`093
X         /NOEXPIRATION_DATE
X
X      Sets the expiration date on the file(s) equal to the specified time.
X      If no value is given, the default is to use the current date and
X      time.  If /NOEXPIRATION_DATE is specified, the file is set not to
X      have an expiration date.
X
X2 /FORCE
X
X         /FORCE
X         /NOFORCE   (normal default)
X
X      This qualifier determines whether or not to create a file using the
X      specified attributes if the given filename is not found.
X      This qualifier will not create a directory path to a file.  If the`032
X      file(s) are found, this qualifer has no effect.  If you do not
X      specify a creation date with the /CREATION_DATE qualifier, the file
X      with be created with a date of 17-NOV-1858 00:00:00.00. The normal`032
X      default is /NOFORCE, but this can be changed at compile time.
X
X2 /LOG
X        `032
X         /LOG
X         /NOLOG   (default)
X
X      Controls whether or not an informational message is displayed when
X      a file is successfully modified.
X
X2 /MODIFIER
X
X         /MODIFIER`091=keyword`093
X
X      This qualifier is used in conjunction with /BEFORE and /SINCE to`032
X      select which date-time value is to be used in selecting files.
X      The default is to use the revision date, in which case this`032
X      qualifier may be omitted.  The valid keywords are BACKUP_DATE,
X      CREATION_DATE, EXPIRATION_DATE, and REVISION_DATE.
X
X2 /REVISION_DATE
X
X         /REVISION_DATE`091=time`093
X         /NOREVISON_DATE
X
X      Sets the revision date on the file(s) equal to the specified time.
X      If no time value is given, the default is to use the current date
X      and time.  If /NOREVISION_DATE is specified, the revision date is
X      set to the VMS base date of 17-NOV-1858 00:00:00.00.  If no other`032
X      time modification qualifers are present and the /DISPLAY qualifier`032
X      is also absent, this qualifier is present by default with a value`032
X      equal to the current time.
X
X2 /SINCE                                          `032
X
X         /SINCE`091=time`093
X
X      Selects only those files that are dated after the specified date.
X      The default date to compare this time agains when selecting files`032
X      is the revision date, but this can be changed with the /MODIFIER`032
X      qualifier.  If no time is specified, the default is TODAY.
X
X2 Examples
X
X      By itself, the touch command updates the revision time of the files.
X      The command:
X
X      $ TOUCH *.*;*
X
X      will update the revision time on every file in the current directory.
X
X      The following command:
X
X      $ TOUCH/LOG/SINCE=YESTERDAY/MODIFIER=CREATION/EXPIRATION *.*;*
X      %TOUCH-I-TOUCHED, File DISK4:`091JONES`093LOGIN.COM touched.
X
X      will change the expiration time on every file in the current directory
X      created since YESTERDAY to the current time.  In this case, one
X      file was matched.  An informational message was displayed because
X      the /LOG qualifier was present.
X
X      The next example:
X
X      $ TOUCH/BACKUP=20-DEC-1991 *.TXT;*/EXCLUDE=(MYFILE.TXT,YOURFILE.TXT)
X
X      Will set the backup date on every file in the current directory of
X      type .TXT to 20-DEC-1991 00:00:00.00, except for MYFILE.TXT and
X      YOURFILE.TXT.
X
X      The TOUCH command can also be used to create files with the given
X      time characteristics.
X  `032
X      $ TOUCH/EXPIRATION=1-JAN-1994/FORCE/LOG FOO.COM
X      %TOUCH-I-CREATED, File DISK1:`091SMITH`093FOO.COM touched
X          `032
X      Since the /FORCE qualfier was specified, the file FOO.COM was created
X      when it could not be found.  This can be used, for example, to`032
X      ensure that a file exists before attempting to access it.
X
X2 Author
X
X      Aaron M. Renn
X
X      arenn@indiana.edu
X      arenn@indiana.bitnet
X      arenn@isis.cs.du.edu
X
X      My affiliation with Indiana University is as a student and this`032
X      program is in no way associated with that school.  Questions,`032
X      comments, and bug reports are welcome.
X
X2 Bugs
X
X      For bug reports, see the Author subtopic.
$ CALL UNPACK TOUCH.HLP;1 2032685425
$ create/nolog 'f'
Xsys$library:vaxcrtl/share
$ CALL UNPACK TOUCH.OPT;1 1377640302
$ create/nolog 'f'
X! TOUCHCMD.CLD -- Command definition file for TOUCH V1.0
X!                 This is linked into the executable.
X!`032
X! By Aaron M. Renn
X!
X
XModule TOUCH_TABLE
X
XIdent "TOUCHCMD.CLD V1.1"
X
XDefine Verb TOUCH
X
X      Parameter P1
X         Label=FILENAME,
X         Value (Type=$INFILE, Required, Impcat, List),
X         Prompt="File"
X
X      Qualifier BACKUP_DATE,
X         Negatable,
X         Value (Type=$DATETIME)
X
X      Qualifier CREATION_DATE,
X         Negatable,
X         Value (Type=$DATETIME)
X
X      Qualifier EXPIRATION_DATE,
X         Negatable,
X         Value (Type=$DATETIME)
X
X      Qualifier REVISION_DATE,
X         Negatable,`032
X         Value (Type=$DATETIME)
X
X      Qualifier BEFORE,
X         Nonnegatable,
X         Value (Type=$DATETIME, Default="TODAY")
X
X      Qualifier SINCE,
X         Nonnegatable,`032
X         Value (Type=$DATETIME, Default="TODAY")
X
X      Qualifier MODIFIER,`032
X         Default,`032
X         Nonnegatable,`032
X         Value (Type=MOD_TYPES, Default="R")
X
X      Qualifier EXCLUDE
X         Nonnegatable,
X         Value (Required, List)
X
X      Qualifier CONFIRM,`032
X         Negatable
X
X      Qualifier FORCE,`032
X         Negatable
X
X      Qualifier LOG,`032
X         Negatable
X
X      Qualifier DISPLAY,`032
X         Nonnegatable
X
X     Define Type MOD_TYPES
X         Keyword BACKUP_DATE
X         Keyword CREATION_DATE
X         Keyword EXPIRATION_DATE
X         Keyword REVISION_DATE
$ CALL UNPACK TOUCHCMD.CLD;1 1091779574
$ create/nolog 'f'
X! TOUCHMSG.MSG -- Error and informational messages for TOUCH V1.1
X!`032
X! By Aaron M. Renn`032
X!
X
X.TITLE      TOUCH   Messages for TOUCH
X.IDENT      "TOUCHMSG.MSG V1.1-002"
X.FACILITY   TOUCH,1
X
X.SEVERITY   INFORMATIONAL
XCREATED     /FAO_COUNT=1 <File !AS touched>
XSUMMARY     /FAO_COUNT=1 <Total of !AS files touched>
XTOUCHED     /FAO_COUNT=1 <File !AS touched>
X
X.SEVERITY   WARNING
XSEARCHFAIL  /FAO_COUNT=1 <Error searching for !AS>
X
X.SEVERITY   ERROR
XCREATEFAIL  /FAO_COUNT=1 <Error touching file !AS>
XDISPFAIL    /FAO_COUNT=1 <Error displaying file !AS>
XTOUCHFAIL   /FAO_COUNT=1 <Error touching file !AS>
X
X.SEVERITY   FATAL
XINVQUAVAL   /FAO_COUNT=1 <Value '!AS' invalid for /EXCLUDE qualifier>`032
XPRGMFAULT                <Unable to touch>
$ CALL UNPACK TOUCHMSG.MSG;1 2055049292
$ v=f$verify(v)
$ EXIT

