[net.sources] Touch and Chmod for MS-DOS 2.X, MicroSoft C 3.0

rose@uw-june (Scott Rose) (06/09/85)

Below is a quick and dirty yet-another-version of touch and of chmod for
  the IBM-PC MS-DOS 2.X.  Must be compiled with MicroSoft 3.0 C compiler.
  Shar format.

---Cut me!---Here!---
#!/bin/sh
cat >README <<'------ EOF ------'
This distribution contains a hastily slapped together 'touch' and an even
  hastier 'chmod' function for the IBM-PC running DOS 2.X.  Both are designed
  to be compiled with the Microsoft C Compiler 3.0.

'touch' is an attempt to match the action of the Unix 'touch' command as 
  closely as possible (as opposed to an attempt to define a touch with 
  reasonable semantics).  Thus, touching a non-existant file causes it
  to be created, when possible.  Non-expandable wildcard characters cause
  immediate termination of execution, regardless whether other file specs
  in the file list are valid, just as if the shell had found a problem and
  reported it.  The faulty semantics of the DOS '?' wildcard are reflected
  in the execution of this program because of the cheap and easy manner in
  which the expansion is implemented.

'chmod' is a limited command to change the mode of its arguments to read/write
  or read-only, the only supported modes in MS-DOS.  So sloppy is my work
  here that, although I hear that DOS 3.0 provides such a command, I didn't
  bother to walk down the hall to check it out.  Ah, the perils of public
  domain.

To compile either file, type

	cl -c x.c
	cl -o x x.obj ssetargv.obj

   where x is either 'chmod' or 'touch'.  Ssetargv is required to expand the
   wildcard characters.  Note that I have followed the suggested Microsoft
   conventions for which files to place in the 'sys' subdirectory of the
   'include' subdirectory.

	Scott Rose  (rose@uw-bluechip.arpa)
	Department of Computer Science
	University of Washington
	Seattle, Washington
------ EOF ------
ls -l README
cat >chmod.c <<'------ EOF ------'
/*
 * Chmod.c
 *
 *	Change the protection mode of the argument files to read-only or 
 *	read/write.
 *
 *	Designed for use with the Microsoft 3.00 C Compiler for MS-DOS 2.X.
 *	To effect wildcard expansion, link with the file SSETARGV.OBJ.
 *
 *	Hastily authored by Scott Rose at the University of Washington.
 *	Public domain.
 *
 */


#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>




main(argc, argv)

int argc;
char *argv[];
{
    int tmp;
    int	index;

    if(argc < 3)
    {
    	fprintf(stderr, "usage: chmod r|w <file-list>\n");
	exit(-1);
    }

    if(*argv[1] == 'w')
    	tmp = S_IREAD | S_IWRITE;
    else if(*argv[1] == 'r')
    	tmp = S_IREAD;
    else
    {
    	fprintf(stderr, "chmod: invalid mode spec.\n");
	exit(-1);
    }

    for(index = 2; index < argc; index++)
    	if(CheckArg(argv[index]))
	{
	    fprintf(stderr, "No match.\n");
	    exit(-1);
	}

    for(index = 2; index < argc; index++)
    	if(chmod(argv[index], tmp))
	    fprintf(stderr, "chmod: file %s not found.\n", argv[index]);

}	/* end chmod */




/*
 * CheckArg
 *
 *	Scan the argument filename for wildcard characters.
 *
 */

static
CheckArg(name)

char	*name;
{
    register char	c;

    while(c = *name++)
	if(c == '?' || c == '*')
	    return(-1);

    return(0);

}	/* end CheckArg */
------ EOF ------
ls -l chmod.c
cat >touch.c <<'------ EOF ------'
/*
 * Touch.c
 *
 *	Mimics the Unix TOUCH command.  Designed for the Microsoft C Compiler
 *	for MS-DOS, version 3.00.
 *
 *	Touch updates the modify time of the files that match its arguments.
 *	Filenames are expanded.  Nonexistant arguments are created with a file
 *	size of zero; failure of any wildcard spec cancels the entire 
 *	operation (which semantics are purely for consistency with the Unix
 *	version of the command).
 *
 *	This code is designed to be compiled with the small model.  The file
 *	SSETARGV.OBJ must be linked in in order to replace the standard 
 *	command line argument handling with that which expands wildcard 
 *	characters automatically.
 *
 *	Authored by Scott Rose and Randy Day, University of Washington
 *	Computer Science.  Public domain for eternity.
 *
 */


#include <stdio.h>
#include <sys\types.h>
#include <sys\utime.h>
#include <sys\timeb.h>
#include <sys\stat.h>


static struct utimbuf	Time;




/*
 * main
 *
 *	Main execution control.
 *
 */

main(argc, argv)

int	argc;
char	*argv[];
{
    int		index;


    if(argc == 1)	/* no arguments */
    {
        fprintf(stderr, "usage: touch <file-list>\n");
	exit(-1);
    }

    /* Check for residual wildcard characters.
     *   The XSETARGV routines, at variance with the Unix shell filename
     *   expansion semantics, pass filename arguments with unmatched wildcard
     *   characters to the caller, unmodified.  Rather than attempt to use
     *   such bogus filenames, they are detected and the operation aborted,
     *   just as if detected by a shell.
     */

    for(index = 1; index < argc; index++)
    	if(CheckArg(argv[index]))
	{
	    fprintf(stderr, "No match.\n");
	    exit(-1);
	}

    FreezeTime(&Time);

    for(index = 1; index < argc; index++)
    	Touch(argv[index]);

    exit(0);

}	/* end main */




/*
 * Touch
 *
 *	Update the modify time of the specified file, creating it if 
 *	necessary.
 *
 */

static
Touch(name)

char	*name;
{
    if(access(name, 2))		/* check write privilege */
    {
    	if(access(name, 0))	/* check existence, creat if possible */
	{
	    int	tmp;

	    if((tmp = creat(name, S_IWRITE)) == -1)
	    {
	        fprintf(stderr, "touch: unable to create %s.\n", name);
		return(-1);
	    }
	    close(tmp);
	}
	else	/* no write privilege */
	{
	    fprintf(stderr, "touch: no write privilege for %s.\n", name);
	    return(-1);
	}
    }
	    
    return(utime(name, &Time));

}	/* end Touch */




/*
 * FreezeTime
 *
 *	Record the current time in the static global struct Time.
 *
 */

static
FreezeTime(uTimeBuf)

struct utimbuf	*uTimeBuf;
{
    struct timeb	timeBuf;

    ftime(&timeBuf);
    Time.modtime = timeBuf.time;

}	/* end FreezeTime */




/*
 * CheckArg
 *
 *	Scan the argument filename for wildcard characters.
 *
 */

static
CheckArg(name)

char	*name;
{
    register char	c;

    while(c = *name++)
	if(c == '?' || c == '*')
	    return(-1);

    return(0);

}	/* end CheckArg */
------ EOF ------
ls -l touch.c