From decwrl!elroy.jpl.nasa.gov!usc!cs.utexas.edu!uunet!allbery Sun Mar 25 18:43:56 PST 1990
Article 1457 of comp.sources.misc:
Path: decwrl!elroy.jpl.nasa.gov!usc!cs.utexas.edu!uunet!allbery
From: viktor@melon.princeton.edu (Viktor Dukhovni)
Newsgroups: comp.sources.misc
Subject: v11i082: Fast mtools,  + mkdfs for SparcStation1 or Sun-3/80 Part 2
Keywords: DOS, floppy
Message-ID: <82378@uunet.UU.NET>
Date: 26 Mar 90 00:15:48 GMT
Sender: allbery@uunet.UU.NET
Lines: 1963
Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)

Posting-number: Volume 11, Issue 82
Submitted-by: viktor@melon.princeton.edu (Viktor Dukhovni)
Archive-name: sparc-mtools/part02

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 3)."
# Contents:  Readme init.c mdir.c mkdfs.c mmd.c mrd.c mread.c mren.c
#   mtype.c subdir.c
# Wrapped by viktor@cucumber on Fri Mar 16 20:50:08 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Readme' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Readme'\"
else
echo shar: Extracting \"'Readme'\" \(3809 characters\)
sed "s/^X//" >'Readme' <<'END_OF_FILE'
X				MTOOLS
X			version 1.6.2 - 5 Jul 89
X
XThis is a collection of MSDOS tools to allow you to read and write to
XMSDOS formatted diskettes from a Unix based system.
X
XThe following MSDOS commands are emulated:
X
XMtool 		MSDOS
Xname		equivalent	Description
X-----		----		-----------
Xmcopy		COPY		copy MSDOS files to/from Unix
Xmdel		DEL/ERASE	delete a MSDOS file
Xmdir		DIR		display a MSDOS directory
Xmkdfs		FORMAT		Format and build s DOS file system.
Xmmd		MD/MKDIR	make a MSDOS sub directory
Xmrd		RD/RMDIR	remove a MSDOS sub directory
Xmread		COPY		low level read (copy) a MSDOS file to Unix
Xmren		REN/RENAME	rename an existing MSDOS file
Xmtype		TYPE		display contents of a MSDOS file
Xmwrite		COPY		low level write (copy) a Unix file to MSDOS
X*		CD		change working directory
X
X	* by use of the environmental variable MCWD
X
XThe formats of IBM PC floppy disk drives are:
X
X   bytes per  sectors per  tracks    number    total     disk   introduced
X    sector      track     per side  of sides  capacity   size    in MSDOS
X     512         8          40        1        160k      5.25      1.0
X     512         9          40        1        180k      5.25      1.1
X     512         8          40        2        320k      5.25      2.0
X     512         9          40        2        360k      5.25      2.0
X     512        15          80        2        1.2M      5.25      3.0
X     512         9          80        2        720k      3.5       3.1
X     512        18          80        2        1.4M      3.5       3.2
X
X
XFind UNIX device(s) capable of reading one or more of these formats
Xand edit "devices.c" to add them to the driver switch,  you may
Xadd the same device more than once if it supports multiple formats
Xand needs "ioctls" to be set to the right physical parameters.
X
XThe disk geometry can be kept in the environment for unusual cases,
Xinit.c will pass "NCYL", "NSECT" and "NTRACK" to the disk parameter
Xsetting routine (if any).  This should be documented in an "mtools"
Xmanual page giving an overview of the whole package,  this file is a 
Xstart.
X
XThe manuals are very terse...  it's assumed that the reader is already
Xfamiliar with MSDOS.
X
XThe use of the environmental variable MCWD to keep track of the current
Xworking directory is a little awkward, especially since there is no
X'change directory' command.  Bourne shell users will have to type two
Xcommands to initially set their working directory, ie:
X
X	MCWD=/TMP
X	export MCWD
X
XWildcards are only applied to filenames and not to directory names.  For
Xexample '/usr/local/*.c' is appropriate, but '/usr/l*/main.c' is not.
X
XI really wanted to avoid the use of a 'text' mode and a 'data' mode when
Xtransferring files, but I couldn't find a better way.  It gets rather
Xconfusing and it's quite possible to mess up a file if you apply the
Xtext mode when it is not appropriate (ie:  to a COM or EXE file).
XLikewise, if you forget to apply the text mode (to a Unix text file)
Xthen if the file is used under MSDOS, it will be missing carriage
Xreturns.  However, if you aren't going to use the files on your Unix
Xsystem (you just intend to hold the files and then transfer them back to
XMSDOS later) then you shouldn't use the text mode during either mread or
Xmwrite.  This is because, the text mode is only useful if the files are
Xgonna be used under Unix.
X
XThe implementation of the Mcopy command is somewhat clumbsy since the
XMSDOS drive designation "A:" is used.  Mcopy is really a front-end to
Xthe low level Mread and Mwrite commands.
X
XThere are is a shell archives called "Unixpc.shar" that contain files
Xspecific to the AT&T Unix PC 7300/3b1.
X
XEmmet P. Gray				US Army, HQ III Corps & Fort Hood
X...!uunet!uiucuxc!fthood!egray		Attn: AFZF-DE-ENV
X					Directorate of Engineering & Housing
X					Environmental Management Office
X					Fort Hood, TX 76544-5057
END_OF_FILE
if test 3809 -ne `wc -c <'Readme'`; then
    echo shar: \"'Readme'\" unpacked with wrong size!
fi
# end of 'Readme'
fi
if test -f 'init.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'init.c'\"
else
echo shar: Extracting \"'init.c'\" \(5152 characters\)
sed "s/^X//" >'init.c' <<'END_OF_FILE'
X/*
X * Initialize a MSDOS diskette.  Read the boot block for disk layout
X * and switch to the proper floppy disk device to match the format
X * of the disk.  Sets a bunch of global variables.  Returns 0 on success,
X * or 1 on failure.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <signal.h>
X#include "devices.h"
X#include "msdos.h"
X
X/* #undef DUP_FAT */
X
Xextern int fd, dir_len, dir_start, clus_size, fat_len, num_clus;
Xextern unsigned char *fatbuf;
Xextern char *mcwd;
X
X/* The available drivers */
Xextern struct device fd_devices[];
X
X/* The bootblock */
Xunion bootblock bb ;
X
Xint
Xinit(mode)
Xint mode;
X{
X  int code, buflen, intr();
X  void perror(), exit(), move(), reset_dir();
X  char *getenv(), *fixmcwd(), *malloc(), *dummy;
X  long lseek();
X  struct device *try;
X  int ncyl = 0, nsect = 0, ntrack =0 ;
X  char *floppy = getenv("FLOPPY");
X
X  /*
X   * Let the user set the geometry in the environment
X   * It is possible for this to be the only way out of the catch-22
X   * wherein the geometry needs to be read from the first block
X   * which cannot be read until the geometry is set!
X   */
X
X  if ( dummy = getenv("NCYL") )
X    ncyl = strtol(dummy,0,0) ;
X  if ( dummy = getenv("NTRACK") )
X    ntrack = strtol(dummy,0,0) ;
X  if ( dummy = getenv("NSECT") )
X    nsect = strtol(dummy,0,0) ;
X  
X  fd = -1 ;
X
X  for ( try = fd_devices ; try->drv_dev ; ++try )
X    if ( !floppy ||
X	 strncmp(try->drv_dev, floppy, strlen(floppy)) == 0 ) {
X      (void) fprintf(stderr,"\nTrying %s ... ",try->drv_dev) ;
X      fflush(stderr);
X      if ( (fd = open(try->drv_dev, mode|try->drv_mode)) > 0 ) {
X	if ( try->drv_ifunc && (*(try->drv_ifunc))(fd,ncyl,ntrack,nsect) ) {
X	  close(fd) ;
X	  fd = -1;
X	  continue ;
X	}
X	if( read_boot() ) {
X	  close(fd) ;
X	  fd = -1;
X	  continue ;
X	}
X	(void) fprintf(stderr,"ok\n") ;
X	fflush(stderr) ;
X	break ;
X      }
X      perror("open") ;
X    }
X
X  if ( fd < 0 ) {
X    (void) fprintf(stderr,"All known devices failed.\nSorry.\n") ;
X    exit(1) ;
X  }
X	
X  dir_start = DIROFF(bb.sb) ;
X  dir_len = DIRLEN(bb.sb);
X  clus_size = CLSIZ(bb.sb);
X  fat_len = FATLEN(bb.sb);
X  num_clus = NCLUST(bb.sb);
X
X  /* Set the parameters if needed */
X  if ( try->drv_ifunc )
X    if( (*(try->drv_ifunc))(fd,NCYL(bb.sb),NTRACK(bb.sb),NSECT(bb.sb)) )
X      exit(1) ;
X  
X  buflen = fat_len * MSECSIZ;
X  fatbuf = (unsigned char *) malloc((unsigned int) buflen);
X
X  /* read the FAT sectors */
X  move(FATOFF(bb.sb));
X  if (read(fd, fatbuf, buflen) != buflen) {
X    (void) fprintf(stderr,"Could not read the FAT table\n");
X    perror("init: read");
X    exit(1) ;
X  }
X
X  /* set dir_chain to root directory */
X  reset_dir();
X  /* get Current Working Directory */
X  mcwd = fixmcwd(getenv("MCWD"));
X  /* test it out.. */
X  if (subdir("")) {
X    (void) fprintf(stderr, "Environment variable MCWD needs updating\n");
X    exit(1);
X  }
X  return(0);
X}
X
X/*
X * Set the logical sector.  Non brain-dead drivers don't move the
X * head until we ask for data,  so computing relative seeks is overkill.
X */
X
Xvoid
Xmove(sector)
Xint sector;
X{
X  long lseek();
X  void exit(), perror();
X
X  if (lseek(fd, (long)sector*MSECSIZ, 0) < 0) {
X    perror("move: lseek");
X    exit(1);
X  }
X}
X
X/*
X * Fix MCWD to be a proper directory name.  Always has a leading separator.
X * Never has a trailing separator (unless it is the path itself).
X */
X
Xchar *
Xfixmcwd(dirname)
Xchar *dirname;
X{
X  char *s, *ans, *malloc(), *strcpy(), *strcat();
X
X  if (dirname == NULL)
X    return("/");
X
X  ans = malloc((unsigned int) strlen(dirname)+2);
X  /* add a leading separator */
X  if (*dirname != '/' && *dirname != '\\') {
X    strcpy(ans, "/");
X    strcat(ans, dirname);
X  }
X  else
X    strcpy(ans, dirname);
X  /* translate to upper case */
X  for (s = ans; *s; ++s) {
X    if (islower(*s))
X      *s = toupper(*s);
X  }
X  /* if separator alone */
X  if (strlen(ans) == 1)
X    return(ans);
X  /* zap the trailing separator */
X  s--;
X  if (*s == '/' || *s == '\\')
X    *s = '\0';
X  return(ans);
X}
X
X/*
X * Do a graceful exit if the program is interupted.  This will reduce
X * (but not eliminate) the risk of generating a corrupted disk on
X * a user abort.
X */
X
Xint
Xintr()
X{
X  void writefat();
X
X  writefat();
X  close(fd);
X  exit(1);
X}
X
X/*
X * Write the FAT table to the disk.  Up to now the FAT manipulation has
X * been done in memory.  All errors are fatal.  (Might not be too smart
X * to wait till the end of the program to write the table.  Oh well...)
X */
X
Xvoid
Xwritefat()
X{
X  int buflen;
X  void move();
X
X  move(FATOFF(bb.sb)) ;
X  buflen = fat_len * MSECSIZ;
X  if (write(fd, (char *) fatbuf, buflen) != buflen) {
X    perror("writefat: write");
X    exit(1);
X  }
X#ifdef DUP_FAT
X  /* the duplicate FAT table */
X  if (write(fd, (char *) fatbuf, buflen) != buflen) {
X    perror("writefat: write");
X    exit(1);
X  }
X#endif				/* DUP_FAT */
X  return;
X}
X
Xread_boot()
X{
X  unsigned char buf[MSECSIZ];
X  static unsigned char ans;
X
X  move(0) ;
X	
X  if (read(fd, &bb, MSECSIZ) != MSECSIZ ) {
X    return(1) ;
X  }
X  
X  /* Do not know how to deal with non 512 byte blocks! */
X  if ( SECSIZ(bb.sb) != MSECSIZ ) {
X    fprintf(stderr,"File system block size of %d bytes is not valid\n",
X            SECSIZ(bb.sb));
X    exit(1) ;
X  }
X
X  return(0) ;
X}
END_OF_FILE
if test 5152 -ne `wc -c <'init.c'`; then
    echo shar: \"'init.c'\" unpacked with wrong size!
fi
# end of 'init.c'
fi
if test -f 'mdir.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mdir.c'\"
else
echo shar: Extracting \"'mdir.c'\" \(4882 characters\)
sed "s/^X//" >'mdir.c' <<'END_OF_FILE'
X/*
X * Display a MSDOS directory
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *mcwd;			/* the current working directory */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int i, entry, files, blocks, fargn, wide, faked;
X	long size;
X	char name[9], ext[4], *date, *time, *convdate(), *convtime();
X	char *strncpy(), newpath[MAX_PATH], *getname(), *getpath(), *pathname;
X	char *newfile, *filename, *unixname(), volume[12], *sep;
X	char *strcpy(), *strcat(), newname[MAX_PATH], *strncat();
X	void exit(), reset_dir(), free();
X	struct directory *dir, *search();
X
X	if (init(0)) {
X		fprintf(stderr, "mdir: Cannot initialize diskette\n");
X		exit(1);
X	}
X					/* find the volume label */
X	reset_dir();
X	volume[0] = '\0';
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == 0x0)
X			break;
X					/* if not volume label */
X		if (!(dir->attr & 0x08))
X			continue;
X
X		strncpy(volume, (char *) dir->name, 8);
X		volume[8] = '\0';
X		strncat(volume, (char *) dir->ext, 3);
X		volume[11] = '\0';
X		break;
X	}
X	if (volume[0] == '\0')
X		printf(" Volume in drive has no label\n");
X	else
X		printf(" Volume in drive is %s\n", volume);
X	fargn = 1;
X	wide = 0;
X					/* first argument number */
X	if (argc > 1) {
X		if (!strcmp(argv[1], "-w")) {
X			wide = 1;
X			fargn = 2;
X		}
X	}
X					/* fake an argument */
X	faked = 0;
X	if (argc == fargn) {
X		faked++;
X		argc++;
X	}
X	files = 0;
X	for (i=fargn; i<argc; i++) {
X		if (faked) {
X			filename = getname(".");
X			pathname = getpath(".");
X		}
X		else {
X			filename = getname(argv[i]);
X			pathname = getpath(argv[i]);
X		}
X					/* move to first guess subdirectory */
X					/* required by isdir() */
X		if (subdir(pathname)) {
X			free(filename);
X			free(pathname);
X			continue;
X		}
X					/* is filename really a subdirectory? */
X		if (isdir(filename)) {
X			strcpy(newpath, pathname);
X			if (strcmp(pathname,"/") && strcmp(pathname, "\\")) {
X				if (*pathname != '\0')
X					strcat(newpath, "/");
X			}
X			strcat(newpath, filename);
X					/* move to real subdirectory */
X			if (subdir(newpath)) {
X				free(filename);
X				free(pathname);
X				continue;
X			}
X			strcpy(newname, "*");
X		}
X		else {
X			strcpy(newpath, pathname);
X			strcpy(newname, filename);
X		}
X
X		if (*filename == '\0')
X			strcpy(newname, "*");
X
X		if (*newpath == '/' || *newpath == '\\')
X			printf(" Directory for %s\n\n", newpath);
X		else if (!strcmp(newpath, "."))
X			printf(" Directory for %s\n\n", mcwd);
X		else {
X			if (strlen(mcwd) == 1 || !strlen(newpath))
X				sep = "";
X			else
X				sep = "/";
X			printf(" Directory for %s%s%s\n\n", mcwd, sep, newpath);
X		}
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X					/* if empty */
X			if (dir->name[0] == 0x0)
X				break;
X					/* if erased */
X			if (dir->name[0] == 0xe5)
X				continue;
X					/* if a volume label */
X			if (dir->attr & 0x08)
X				continue;
X
X			strncpy(name, (char *) dir->name, 8);
X			strncpy(ext, (char *) dir->ext, 3);
X			name[8] = '\0';
X			ext[3] = '\0';
X
X			newfile = unixname(name, ext);
X			if (!match(newfile, newname)) {
X				free(newfile);
X				continue;
X			}
X			free(newfile);
X
X			files++;
X			if (wide && files != 1) {
X				if (!((files-1) % 5))
X					putchar('\n');
X			}
X			date = convdate(dir->date[1], dir->date[0]);
X			time = convtime(dir->time[1], dir->time[0]);
X			size = dir->size[2]*0x10000L + dir->size[1]*0x100 + dir->size[0];
X					/* is a subdirectory */
X			if (dir->attr & 0x10) {
X				if (wide)
X					printf("%-9.9s%-6.6s", name, ext);
X				else
X					printf("%8s %3s  <DIR>     %s  %s\n", name, ext, date, time);
X				continue;
X			}
X			if (wide)
X				printf("%-9.9s%-6.6s", name, ext);
X			else
X				printf("%8s %3s %8d   %s  %s\n", name, ext, size, date, time);
X		}
X		if (argc > 2)
X			putchar('\n');
X
X		free(filename);
X		free(pathname);
X	}
X
X	blocks = getfree() * MSECSIZ;
X	if (!files)
X		printf("File \"%s\" not found\n", newname);
X	else
X		printf("     %3d File(s)     %6ld bytes free\n", files, blocks);
X	close(fd);
X	exit(0);
X}
X
X/*
X * Get the amount of free space on the diskette
X */
X
Xint
Xgetfree()
X{
X	register int i, total;
X
X	total = 0;
X	for (i=2; i<num_clus+2; i++) {
X					/* if getfat returns zero */
X		if (!getfat(i))
X			total += clus_size;
X	}
X	return(total);
X}
END_OF_FILE
if test 4882 -ne `wc -c <'mdir.c'`; then
    echo shar: \"'mdir.c'\" unpacked with wrong size!
fi
# end of 'mdir.c'
fi
if test -f 'mkdfs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mkdfs.c'\"
else
echo shar: Extracting \"'mkdfs.c'\" \(4022 characters\)
sed "s/^X//" >'mkdfs.c' <<'END_OF_FILE'
X#ifndef sun
X	/*
X         * FIX ME!
X	 * All we need is a convenient way for the user to choose the
X         * DOS layout parameters for the FS,  and yet I did not want
X         * to hard code tables for the various drives.
X         * Something like a /etc/dosformat.dat file would be nice
X	 * the user can then use mkdfs <drivename>,  this involes
X	 * table parsing routines etc.,  not too hard,  just unpleasant.
X	 */
X	main() {
X		printf("Do not know how to format disks on your system\n";
X		exit(1) ;
X	}
X#else
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <errno.h>
X#include <sys/wait.h>
X#include <sys/file.h>
X#include <assert.h>
X#include "msdos.h"
X#include "bootblk.h"
X
X#define VOLLBL 0x8
X#define FAT720 0xf9
X#define FAT1440 0xf0
Xstatic char floppy[] = "/dev/rfd0c" ;
Xstatic char disklabel[] = "ANYDSKLABEL" ;
X
Xvoid move(), Write(), usage(), formatit() ;
X
Xstatic char *progname, buf[MSECSIZ] ;
X
Xmain(argc,argv)
X  char **argv;
X{
X  int c, fd, sec ;
X  int fat_len = 3 ;
X  int fat = FAT720 ;
X  int dir_len = 7 ;
X  int hdflag=0, fflag = 0 ;
X
X  progname = argv[0] ;
X
X  while( (c=getopt(argc,argv,"hf")) != EOF ) {
X    switch(c) {
X    case 'f' :
X      fflag++ ;
X      break;
X    case 'h' :
X      hdflag++ ;
X      break;
X    case '?':
X    default:
X      fprintf(stderr,"Unknown option \"%c\"\n",c) ;
X      usage() ;
X    }
X  }
X
X  if (fflag) 
X    formatit(hdflag) ;
X
X  /*  Lets initialize the MSDOS FS */
X
X  if ( (fd=open(floppy,O_RDWR)) == -1 ) {
X    fprintf(stderr,"%s: open: ",progname) ;
X    perror(floppy) ;
X    exit(1) ;
X  }
X
X  if ( hdflag ) {
X    dir_len=14 ;
X    fat_len=9 ;
X    fat=FAT1440 ;
X  }
X  
X  bzero(buf,sizeof(buf)) ;
X  bcopy(hdflag?hdboot:ldboot,buf,MSECSIZ) ;   /* Create the boot block */
X  Write(fd,buf,MSECSIZ) ;   /* Dump the boot block */
X  bzero(buf,sizeof(buf)) ;
X  for( c=0; c < 2 ; ++c ) {
X    buf[0] = fat ;
X    buf[1] = 0xff ;
X    buf[2] = 0xff ;
X    Write(fd,buf,MSECSIZ) ;    /* First block of FAT */
X    bzero(buf,3) ;
X    for( sec=fat_len; --sec ; )
X      Write(fd,buf,MSECSIZ) ;  /* Rest of FAT */
X  }
X  strcpy(((struct directory *)buf)->name,disklabel) ;
X  ((struct directory *)buf)->attr= VOLLBL ;
X  Write(fd,buf,MSECSIZ) ;  /* Root dir */
X  bzero(buf,strlen(disklabel)) ;
X  ((struct directory *)buf)->attr= 0 ;
X  for( ; --dir_len ; )
X    Write(fd,buf,MSECSIZ) ;  /* Root dir */
X}
X
Xvoid 
Xmove(fd,sector)
X  int fd, sector ;
X{
X  if ( lseek(fd,sector*MSECSIZ,L_SET) != sector*MSECSIZ) {
X    fprintf(stderr,"%s: lseek: ",progname) ;
X    perror(floppy) ;
X    exit(1) ;
X  }
X}
X
Xvoid
XWrite(fd,buf,count)
X  int fd,count ;
X  char * buf ;
X{
X  if ( write(fd,buf,count) != count ) {
X    fprintf(stderr,"%s: write: ",progname) ;
X    perror(floppy) ;
X    exit(1) ;
X  }
X}
X
Xvoid
Xusage() 
X{
X  fprintf(stderr,"Usage: %s [-h] [-f]\n",progname) ;
X  fprintf(stderr,"\tBuilds an empty DOS filesystem\n") ;
X  fprintf(stderr,"\t-h: high density\n\t-f: reformat first\n") ;
X  exit(1) ;
X}
X
Xvoid
Xformatit(hdq)
X  int hdq;
X{
X  int pid;
X  struct wait w;
X  int retval;
X
X  if( (pid=fork()) == -1 ) {
X    fprintf(stderr,"%s: ",progname) ;
X    perror("fork") ;
X    exit(1) ;
X  }
X
X  if ( !pid ) {
X    if ( hdq ) 
X      execl("/bin/fdformat","fdformat",floppy,0) ;
X    else
X      execl("/bin/fdformat","fdformat","-l",floppy,0) ;
X
X    fprintf(stderr,"%s: ",progname) ;
X    perror("exec") ;
X    exit(1) ;
X  }
X
X  while ( (retval=wait4(pid,&w,0,0)) == -1 && errno == EINTR ) ;
X
X  if (retval == -1) {
X    fprintf(stderr,"%s: ",progname) ;
X    perror("wait4") ;
X    fprintf(stderr,"The format operation may have failed\nTry again\n") ;
X    exit(1) ;
X  }
X
X  if ( WIFSIGNALED(w) ) {
X    fprintf(stderr,"%s: ",progname) ;
X    psignal(w.w_termsig,"/bin/fdformat") ;
X    if (w.w_coredump)
X      fprintf(stderr,"Core dumped\n") ;
X    exit(1) ;
X  }
X
X  assert( WIFEXITED(w) ) ; /* If not signalled,  must be exited
X                              we are not tracing stopped processes */
X
X  if ( w.w_retcode ) {
X    fprintf(stderr,"%s: /bin/fdformat exited with non-zero exit code %d\n",
X      progname,w.w_retcode) ;
X    exit(1) ;
X  }
X}
X#endif
END_OF_FILE
if test 4022 -ne `wc -c <'mkdfs.c'`; then
    echo shar: \"'mkdfs.c'\" unpacked with wrong size!
fi
# end of 'mkdfs.c'
fi
if test -f 'mmd.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mmd.c'\"
else
echo shar: Extracting \"'mmd.c'\" \(4058 characters\)
sed "s/^X//" >'mmd.c' <<'END_OF_FILE'
X/*
X * Make a MSDOS sub directory
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *mcwd;			/* the Current Working Directory */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int entry, slot, fat, dot, fargn, verbose;
X	char *filename, *newfile, *fixname(), *strncpy();
X	char *getpath(), *pathname, tname[9], text[4], *fixed, *unixname();
X	void exit(), putcluster(), writefat(), writedir(), free();
X	struct directory *dir, *search(), *mk_entry();
X	long time(), now;
X
X	if (init(2)) {
X		fprintf(stderr, "mmd: Cannot initialize diskette\n");
X		exit(1);
X	}
X
X	fargn = 1;
X	verbose = 0;
X	if (argc > 1) {
X		if (!strcmp(argv[1], "-v")) {
X			fargn = 2;
X			verbose = 1;
X		}
X	}
X					/* only 1 directory ! */
X	if (argc != fargn+1) {
X		fprintf(stderr, "Usage: mmd [-v] msdosdirectory\n");
X		exit(1);
X	}
X	fixed = fixname(argv[fargn], verbose);
X
X	strncpy(tname, fixed, 8);
X	strncpy(text, fixed+8, 3);
X	tname[8] = '\0';
X	text[3] = '\0';
X
X	filename = unixname(tname, text);
X	pathname = getpath(argv[fargn]);
X
X	if (subdir(pathname))
X		exit(1);
X					/* see if exists and get slot */
X	slot = -1;
X	dot = 0;
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == 0x0) {
X			if (slot < 0)
X				slot = entry;
X			break;
X		}
X					/* if erased */
X		if (dir->name[0] == 0xe5) {
X			if (slot < 0)
X				slot = entry;
X			continue;
X		}
X					/* if not a directory */
X		if (!(dir->attr & 0x10))
X			continue;
X
X		strncpy(tname, (char *) dir->name, 8);
X		strncpy(text, (char *) dir->ext, 3);
X		tname[8] = '\0';
X		text[3] = '\0';
X
X		newfile = unixname(tname, text);
X					/* save the 'dot' directory info */
X		if (!strcmp(".", newfile))
X			dot = dir->start[1]*0x100 + dir->start[0];
X
X		if (!strcmp(filename, newfile)) {
X			fprintf(stderr, "mmd: Directory \"%s\" already exists\n", filename);
X			exit(1);
X		}
X		free(newfile);
X	}
X					/* no '.' entry means root directory */
X	if (dot == 0 && slot < 0) {
X		fprintf(stderr, "mmd: No directory slots\n");
X		exit(1);
X	}
X					/* make the directory grow */
X	if (dot && slot < 0) {
X		if (grow(dot)) {
X			fprintf(stderr, "mmd: Disk full\n");
X			exit(1);
X		}
X					/* first slot in 'new' directory */
X		slot = entry;
X	}
X	if ((fat = nextfat(0)) == -1) {
X		fprintf(stderr, "mmd: Disk full\n");
X		exit(1);
X	}
X					/* make directory entry */
X	time(&now);
X	dir = mk_entry(fixed, 0x10, fat, 0L, now);
X	writedir(slot, dir);
X					/* write the cluster */
X	putfat(fat, 0xfff);
X	putcluster(fat, dot);
X					/* write FAT sectors */
X	writefat();
X	close(fd);
X	exit(0);
X}
X
X/*
X * Write a blank directory 'template' to the cluster starting at 'dot'.
X */
X
Xvoid
Xputcluster(dot, dot_dot)
Xint dot, dot_dot;
X{
X	int buflen, start;
X	static struct directory dirs[32];
X	struct directory *mk_entry();
X	void exit(), perror(), move();
X	long time(), now;
X
X	start = (dot - 2)*clus_size + dir_start + dir_len;
X	move(start);
X
X	buflen = clus_size * MSECSIZ;
X					/* make the '.' and '..' entries */	
X	time(&now);
X	dirs[0] = *mk_entry(".          ", 0x10, dot, 0L, now);
X	dirs[1] = *mk_entry("..         ", 0x10, dot_dot, 0L, now);
X
X	if (write(fd, (char *) &dirs[0], buflen) != buflen) {
X		perror("putcluster: write");
X		exit(1);
X	}
X	return;
X}
X
X/*
X * Returns next free cluster or -1 if none are available.
X */
X
Xint
Xnextfat(last)
Xint last;
X{
X	register int i;
X
X	for (i=last+1; i<num_clus+2; i++) {
X		if (!getfat(i))
X			return(i);
X	}
X	return(-1);
X}
END_OF_FILE
if test 4058 -ne `wc -c <'mmd.c'`; then
    echo shar: \"'mmd.c'\" unpacked with wrong size!
fi
# end of 'mmd.c'
fi
if test -f 'mrd.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mrd.c'\"
else
echo shar: Extracting \"'mrd.c'\" \(3277 characters\)
sed "s/^X//" >'mrd.c' <<'END_OF_FILE'
X/*
X * Delete a MSDOS sub directory
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *mcwd;			/* the Current Working Directory */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int ismatch, entry, start;
X	char *filename, *newfile, text[4], tname[9], *getname();
X	char *strncpy(), *pathname, *getpath(), *unixname();
X	void exit(), zapit(), writefat(), writedir(), free();
X	struct directory *dir, *search();
X
X	if (init(2)) {
X		fprintf(stderr, "mrd: Cannot initialize diskette\n");
X		exit(1);
X	}
X					/* only 1 directory ! */
X	if (argc != 2) {
X		fprintf(stderr, "Usage: mrd mdsosdirectory\n");
X		exit(1);
X	}
X
X	filename = getname(argv[1]);
X	pathname = getpath(argv[1]);
X	if (subdir(pathname))
X		exit(1);
X
X	ismatch = 0;
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == 0x0)
X			break;
X					/* if erased */
X		if (dir->name[0] == 0xe5)
X			continue;
X					/* if not dir */
X		if (!(dir->attr & 0x10))
X			continue;
X
X		strncpy(tname, (char *) dir->name, 8);
X		strncpy(text, (char *) dir->ext, 3);
X		tname[8] = '\0';
X		text[3] = '\0';
X
X		newfile = unixname(tname, text);
X		if (!strcmp(newfile, filename)) {
X			start = dir->start[1]*0x100 + dir->start[0];
X			if (!isempty(start)) {
X				fprintf(stderr, "mrd: Directory \"%s\" is not empty\n", filename);
X				exit(1);
X			}
X			if (!start) {
X				fprintf(stderr, "mrd: Can't remove root directory\n");
X				exit(1);
X			}
X			zapit(start);
X			dir->name[0] = 0xe5;
X			writedir(entry, dir);
X			ismatch = 1;
X		}
X		free(newfile);
X	}
X	if (!ismatch) {
X		fprintf(stderr, "mrd: Directory \"%s\" not found\n", filename);
X		exit(1);
X	}
X					/* update the FAT sectors */
X	writefat();
X	close(fd);
X	exit(0);
X}
X
X/*
X * See if directory is empty.  Returns 1 if empty, 0 if not.  Can't use
X * subdir() and search() as it would clobber the globals.
X */
X
Xint
Xisempty(fat)
Xint fat;
X{
X	register int i;
X	int next, buflen, sector;
X	unsigned char tbuf[CLSTRBUF];
X	void perror(), exit(), move();
X
X	while (1) {
X		sector = (fat-2)*clus_size + dir_start + dir_len;
X		move(sector);
X		buflen = clus_size * MSECSIZ;
X		if (read(fd, (char *) tbuf, buflen) != buflen) {
X			perror("isempty: read");
X			exit(1);
X		}
X					/* check first character of name */
X		for (i=0; i<MSECSIZ; i+=MDIRSIZ) {
X			if (tbuf[i] == '.')
X				continue;
X			if (tbuf[i] != 0x0 && tbuf[i] != 0xe5)
X				return(0);
X		}
X					/* get next cluster number */
X		next = getfat(fat);
X		if (next == -1) {
X			fprintf(stderr, "isempty: FAT problem\n");
X			exit(1);
X		}
X					/* end of cluster chain */
X		if (next >= 0xff8)
X			break;
X		fat = next;
X	}
X	return(1);
X}
END_OF_FILE
if test 3277 -ne `wc -c <'mrd.c'`; then
    echo shar: \"'mrd.c'\" unpacked with wrong size!
fi
# end of 'mrd.c'
fi
if test -f 'mread.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mread.c'\"
else
echo shar: Extracting \"'mread.c'\" \(6791 characters\)
sed "s/^X//" >'mread.c' <<'END_OF_FILE'
X/*
X * Read (copy) a MSDOS file to Unix
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "msdos.h"
X
X#define LOWERCASE
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *buf;			/* The input buffer */
Xlong bufsiz;			/* It's size */
Xint maxcontig;			/* In clusters */
Xchar *mcwd;			/* the Current Working Directory */
X
Xextern union bootblock bb;
Xlong size;
Xlong current;
Xint textmode = 0;
Xint nowarn = 0;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	extern int optind;
X	extern char *optarg;
X	int fat, i, ismatch, entry, single, c, oops, mod_time;
X	long mod_date, convstamp();
X	char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
X	char *strncpy(), *pathname, *getpath(), *target, tmp[MAX_PATH];
X	char *strcat(), *strcpy();
X	void perror(), exit(), free();
X	struct directory *dir, *search();
X	struct stat stbuf;
X
X	if (init(0)) {
X		fprintf(stderr, "mread: Cannot initialize diskette\n");
X		exit(1);
X	}
X					/* get command line options */
X	oops = 0;
X	mod_time = 0;
X	while ((c = getopt(argc, argv, "tnm")) != EOF) {
X		switch(c) {
X			case 't':
X				textmode = 1;
X				break;
X			case 'n':
X				nowarn = 1;
X				break;
X			case 'm':
X				mod_time = 1;
X				break;
X			default:
X				oops = 1;
X				break;
X		}
X	}
X
X	if (oops || (argc - optind) < 2) {
X		fprintf(stderr, "Usage: mread [-tn] msdosfile unixfile\n");
X		fprintf(stderr, "    or mread [-tn] msdosfile [msdosfiles...] unixdirectory\n");
X		exit(1);
X	}
X					/* only 1 file to copy... */
X	single = 1;
X	target = argv[argc-1];
X					/* ...unless last arg is a directory */
X	if (!stat(target, &stbuf)) {
X		if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
X			single = 0;	
X	}
X					/* too many arguments */
X	if (single && (argc - optind) != 2) {
X		fprintf(stderr,
X			"mread: too many arguments or target dir omitted\n");
X		exit(1);
X	}
X
X	bufsiz = NSECT(bb.sb) * NTRACK(bb.sb) ;
X	maxcontig = (bufsiz += clus_size - (--bufsiz) % clus_size)/clus_size;
X
X	if ( (buf = (char *)malloc(bufsiz *= MSECSIZ)) == NULL ) {
X		fprintf(stderr,"Could not allocate input buffer\n");
X		exit(1) ;
X	}
X
X	for (i=optind; i<argc-1; i++) {
X		filename = getname(argv[i]);
X		pathname = getpath(argv[i]);
X		if (subdir(pathname)) {
X			free(filename);
X			free(pathname);
X			continue;
X		}
X
X		ismatch = 0;
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X					/* if empty */
X			if (dir->name[0] == 0x0)
X				break;
X					/* if erased */
X			if (dir->name[0] == 0xe5)
X				continue;
X					/* if dir or volume lable */
X			if ((dir->attr & 0x10) || (dir->attr & 0x08))
X				continue;
X
X			strncpy(tname, (char *) dir->name, 8);
X			strncpy(text, (char *) dir->ext, 3);
X			tname[8] = '\0';
X			text[3] = '\0';
X
X			newfile = unixname(tname, text);
X			fat = dir->start[1]*0x100 + dir->start[0];
X			size = dir->size[2]*0x10000L + dir->size[1]*0x100 + dir->size[0];
X			if (mod_time)
X				mod_date = convstamp(dir->time, dir->date);
X			else
X				mod_date = 0L;
X
X					/* if single file */
X			if (single) {
X				if (!strcmp(newfile, filename)) {
X					readit(fat, target, mod_date);
X					ismatch = 1;
X					break;
X				}
X			}
X					/* if multiple files */
X			else {
X				if (match(newfile, filename)) {
X					printf("Copying %s\n", newfile);
X					strcpy(tmp, target);
X					strcat(tmp, "/");
X					strcat(tmp, newfile);
X					readit(fat, tmp, mod_date);
X					ismatch = 1;
X				}
X			}
X			free(newfile);
X		}
X		if (!ismatch)
X			fprintf(stderr, "mread: File \"%s\" not found\n", filename);
X		free(filename);
X		free(pathname);
X	}
X	close(fd);
X	exit(0);
X}
X
X/*
X * Decode the FAT chain given the begining FAT entry, open the named Unix
X * file for write.
X */
X
Xstatic int readpos;
X
Xint
Xreadit(fat, target, mod_date)
Xint fat;
Xchar *target;
Xlong mod_date;
X{
X	void getclusters() ;
X	char ans[10];
X	void exit();
X	int curfat;
X	FILE *fp;
X	struct stat stbuf;
X	struct utimbuf {
X		time_t actime;
X		time_t modtime;
X	} utbuf;
X
X#ifdef LOWERCASE
X	char *c;
X	c = target;
X	while(*c) {
X		if (isupper(*c))
X			*c = tolower(*c);
X		c++;
X	}
X#endif /* LOWERCASE */
X
X	if (!nowarn) {
X		if (!access(target, 0)) {
X			while (1) {
X				printf("File \"%s\" exists, overwrite (y/n) ? ", target);
X				gets(ans);
X				if (ans[0] == 'n' || ans[0] == 'N')
X					return;
X				if (ans[0] == 'y' || ans[0] == 'Y')
X					break;
X			}
X					/* sanity checking */
X			if (!stat(target, &stbuf)) {
X				if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
X					fprintf(stderr, "mread: \"%s\" is not a regular file\n", target);
X					return;
X				}
X			}
X		}
X	}
X
X	if (!(fp = fopen(target, "w"))) {
X		fprintf(stderr, "mread: Can't open \"%s\" for write\n", target);
X		return;
X	}
X
X	current = 0L;
X	readpos = -1;
X	for(;;) {
X		/*
X		 * Find chain of contiguous clusters
X		 * curfat -> last in chain + 1
X		 */
X		for(curfat=fat;
X		    ++curfat < fat + maxcontig &&
X		    getfat(curfat-1)==curfat;) ;
X
X		getclusters(fat, curfat, fp);
X					/* get next cluster number */
X		fat = getfat(--curfat);
X		if (fat == -1) {
X			fprintf(stderr, "mread: FAT problem\n");
X			exit(1);
X		}
X					/* end of cluster chain */
X		if (fat >= 0xff8)
X			break;
X	}
X	if (fclose(fp)) {
X		fprintf(stderr,"Error closing %s\n",target) ;
X		perror("close?") ;
X		exit(1) ;
X	}
X					/* preserve mod times ? */
X	if (mod_date != 0L) {
X		utbuf.actime = mod_date;
X		utbuf.modtime = mod_date;
X		utime(target, &utbuf);
X	}
X	return;
X}
X
X/*
X * Read the named cluster, write to the Unix file descriptor.
X */
X
Xvoid
Xgetclusters(start, end, fp)
XFILE *fp;
X{
X	register int i;
X	int buflen, blk;
X	void exit(), perror(), move();
X
X	blk = (start - 2)*clus_size + dir_start + dir_len;
X	if (blk != readpos)
X		move(blk);
X
X	buflen = (end-start) * clus_size * MSECSIZ;
X
X	if (read(fd, (char *) buf, buflen) != buflen) {
X		perror("getcluster: read");
X		exit(1);
X	}
X	readpos = blk + (end-start)*clus_size;
X					/* stop at size not EOF marker */
X	if (textmode) {
X		for (i=0; i<buflen; i++) {
X			current++;
X			if (current > size) 
X				break;
X			if ( buf[i] == '\r')
X				continue;
X			if ( current == size && buf[i] == 0x1a)
X				continue;
X			putc((char) buf[i], fp);
X		}
X	}
X	else {
X		buflen = (size > buflen) ? buflen : size;
X		if (fwrite(buf,buflen,1,fp)!=1) {
X			perror("getclusters: fwrite") ;
X			exit(1) ;
X		}
X		size -= buflen ;
X	}
X		
X	return;
X}
END_OF_FILE
if test 6791 -ne `wc -c <'mread.c'`; then
    echo shar: \"'mread.c'\" unpacked with wrong size!
fi
# end of 'mread.c'
fi
if test -f 'mren.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mren.c'\"
else
echo shar: Extracting \"'mren.c'\" \(3153 characters\)
sed "s/^X//" >'mren.c' <<'END_OF_FILE'
X/*
X * Rename an existing MSDOS file
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *mcwd;			/* the Current Working Directory */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int entry, ismatch, nogo, fargn, verbose, got_it;
X	char *filename, *newfile, *fixname(), *strncpy(), *unixname();
X	char *getpath(), *pathname, tname[9], text[4], *getname(), *target;
X	char *new, ans[10], *temp, *strcpy();
X	void exit(), writedir(), free();
X	struct directory *dir, *search();
X
X	if (init(2)) {
X		fprintf(stderr, "mren: Cannot initialize diskette\n");
X		exit(1);
X	}
X	fargn = 1;
X	verbose = 0;
X	if (argc > 1) {
X		if (!strcmp(argv[1], "-v")) {
X			fargn = 2;
X			verbose = 1;
X		}
X	}
X	if (argc != fargn+2) {
X		fprintf(stderr, "Usage: mren [-v] sourcefile targetfile\n");
X		exit(1);
X	}
X	filename = getname(argv[fargn]);
X	pathname = getpath(argv[fargn]);
X	if (subdir(pathname))
X		exit(1);
X
X	temp = getname(argv[fargn+1]);
X	target = fixname(argv[fargn+1], verbose);
X
X	strncpy(tname, target, 8);
X	strncpy(text, target+8, 3);
X	tname[8] = '\0';
X	text[3] = '\0';
X
X	new = unixname(tname, text);
X	nogo = 0;
X					/* the name supplied may be altered */
X	if (strcmp(temp, new) && verbose) {
X		while (!nogo) {
X			printf("Do you accept \"%s\" as the new file name (y/n) ? ", new);
X			gets(ans);
X			if (ans[0] == 'y' || ans[0] == 'Y')
X				break;
X			if (ans[0] == 'n' || ans[0] == 'N')
X				nogo = 1;
X		}
X	}
X	if (nogo)
X		exit(0);
X					/* see if exists and do it */
X	ismatch = 0;
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == 0x0)
X			break;
X					/* if erased */
X		if (dir->name[0] == 0xe5)
X			continue;
X					/* if volume label */
X		if (dir->attr == 0x08)
X			continue;
X					/* you may rename a directory */
X		strncpy(tname, (char *) dir->name, 8);
X		strncpy(text, (char *) dir->ext, 3);
X		tname[8] = '\0';
X		text[3] = '\0';
X
X		newfile = unixname(tname, text);
X
X					/* if the new name already exists */
X		if (!strcmp(new, newfile)) {
X			fprintf(stderr, "mren: File \"%s\" already exists\n", new);
X			exit(1);
X		}
X					/* if the old name exists */
X		if (!strcmp(filename, newfile)) {
X			ismatch = 1;
X			got_it = entry;
X		}
X		free(newfile);
X	}
X	if (!ismatch) {
X		fprintf(stderr, "mren: File \"%s\" not found\n", filename);
X		exit(1);
X	}
X					/* so go ahead and do it */
X	dir = search(got_it);
X	strncpy((char *) dir->name, target, 8);
X	strncpy((char *) dir->ext, target+8, 3);
X	writedir(got_it, dir);
X
X	close(fd);
X	exit(0);
X}
END_OF_FILE
if test 3153 -ne `wc -c <'mren.c'`; then
    echo shar: \"'mren.c'\" unpacked with wrong size!
fi
# end of 'mren.c'
fi
if test -f 'mtype.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mtype.c'\"
else
echo shar: Extracting \"'mtype.c'\" \(3748 characters\)
sed "s/^X//" >'mtype.c' <<'END_OF_FILE'
X/*
X * Display contents of a MSDOS file
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *mcwd;			/* the Current Working Directory */
X
Xlong size;
Xlong current;
Xint stripmode = 0;
Xint textmode = 0;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	extern int optind;
X	extern char *optarg;
X	int fat, i, ismatch, entry, c, oops;
X	char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
X	char *strncpy(), *pathname, *getpath();
X	void exit(), readit(), free();
X	struct directory *dir, *search();
X
X	if (init(0)) {
X		fprintf(stderr, "mtype: Cannot initialize diskette\n");
X		exit(1);
X	}
X					/* get command line options */
X	oops = 0;
X	while ((c = getopt(argc, argv, "st")) != EOF) {
X		switch(c) {
X			case 's':
X				stripmode = 1;
X				break;
X			case 't':
X				textmode = 1;
X				break;
X			default:
X				oops = 1;
X				break;
X		}
X	}
X
X	if (oops || (argc - optind) < 1) {
X		fprintf(stderr, "Usage: mtype [-st] msdosfile [msdosfiles...]\n");
X		exit(1);
X	}
X
X	for (i=optind; i<argc; i++) {
X		filename = getname(argv[i]);
X		pathname = getpath(argv[i]);
X		if (subdir(pathname)) {
X			free(filename);
X			free(pathname);
X			continue;
X		}
X		ismatch = 0;
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X					/* if empty */
X			if (dir->name[0] == 0x0)
X				break;
X					/* if erased */
X			if (dir->name[0] == 0xe5)
X				continue;
X					/* if dir or volume label */
X			if ((dir->attr & 0x10) || (dir->attr & 0x08))
X				continue;
X
X			strncpy(tname, (char *) dir->name, 8);
X			strncpy(text, (char *) dir->ext, 3);
X			tname[8] = '\0';
X			text[3] = '\0';
X
X			newfile = unixname(tname, text);
X					/* see it if matches the pattern */
X			if (match(newfile, filename)) {
X				fat = dir->start[1]*0x100 + dir->start[0];
X				size = dir->size[2]*0x10000L + dir->size[1]*0x100 + dir->size[0];
X				readit(fat);
X				ismatch = 1;
X			}
X			free(newfile);
X		}
X		if (!ismatch)
X			fprintf(stderr, "mtype: File \"%s\" not found\n", filename);
X		free(filename);
X		free(pathname);
X	}
X	close(fd);
X	exit(0);
X}
X
X/*
X * Decode the FAT chain given the begining FAT entry.
X */
X
Xvoid
Xreadit(fat)
Xint fat;
X{
X	void getcluster();
X
X	current = 0L;
X	while (1) {
X		getcluster(fat);
X					/* get next cluster number */
X		fat = getfat(fat);
X		if (fat == -1) {
X			fprintf(stderr, "mtype: FAT problem\n");
X			exit(1);
X		}
X					/* end of cluster chain */
X		if (fat >= 0xff8)
X			break;
X	}
X	return;
X}
X
X/*
X * Read the named cluster, output to the stdout.
X */
X
Xvoid
Xgetcluster(num)
Xint num;
X{
X	register int i;
X	int buflen, start;
X	unsigned char buf[CLSTRBUF];
X	void exit(), perror(), move();
X
X	start = (num - 2)*clus_size + dir_start + dir_len;
X	move(start);
X
X	buflen = clus_size * MSECSIZ;
X	if (read(fd, (char *) buf, buflen) != buflen) {
X		perror("getcluster: read");
X		exit(1);
X	}
X					/* stop at size not EOF marker */
X	for (i=0; i<buflen; i++) {
X		current++;
X		if (current > size) 
X			break;
X		if (textmode && buf[i] == '\r')
X			continue;
X		if (textmode && current == size && buf[i] == 0x1a)
X			continue;
X		if (stripmode)
X			putchar(buf[i] & 0x7f);
X		else
X			putchar(buf[i]);
X	}
X	return;
X}
END_OF_FILE
if test 3748 -ne `wc -c <'mtype.c'`; then
    echo shar: \"'mtype.c'\" unpacked with wrong size!
fi
# end of 'mtype.c'
fi
if test -f 'subdir.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'subdir.c'\"
else
echo shar: Extracting \"'subdir.c'\" \(3775 characters\)
sed "s/^X//" >'subdir.c' <<'END_OF_FILE'
X/*
X * subdir(), getdir(), get_chain(), reset_dir()
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xextern int dir_chain[25], dir_start, dir_len, dir_entries, clus_size;
Xextern char *mcwd;
Xstatic char lastpath[MAX_PATH];
X
X/*
X * Parse the path names of a sub directory.  Both '/' and '\' are
X * valid separators.  However, the use of '\' will force the operator
X * to use quotes in the command line to protect '\' from the shell.
X * Returns 1 on error.  Attempts to optimize by remembering the last
X * path it parsed
X */
X
Xint
Xsubdir(name)
Xchar *name;
X{
X	char *s, *tmp, tbuf[MAX_PATH], *path, *strcpy(), *strcat();
X	int code;
X	void reset_dir();
X					/* if full pathname */
X	if (*name == '/' || *name == '\\')
X		strcpy(tbuf, name);
X					/* if relative to MCWD */
X	else {
X		if (!strlen(name))
X			strcpy(tbuf, mcwd);
X		else {
X			strcpy(tbuf, mcwd);
X			strcat(tbuf, "/");
X			strcat(tbuf, name);
X		}
X	}
X					/* if paths are same, do nothing */
X	if (!strcmp(tbuf, lastpath))
X		return(0);
X					/* not recursive, start at root */
X	reset_dir();
X	strcpy(lastpath, tbuf);
X					/* zap the leading separator */
X	tmp = tbuf;
X	if (*tmp == '\\' || *tmp == '/')
X		tmp++;
X	for (s = tmp; *s; ++s) {
X		if (*s == '\\' || *s == '/') {
X			path = tmp;
X			*s = '\0';
X			if (getdir(path))
X				return(1);
X			tmp = s+1;
X		}
X	}
X	code = getdir(tmp);
X	return(code);
X}
X
X/*
X * Find the directory and get the starting cluster.  A null directory
X * is ok.  Returns a 1 on error.
X */
X
Xint
Xgetdir(path)
Xchar *path;
X{
X	int entry, start;
X	char *newname, *unixname(), *strncpy(), name[9], ext[4];
X	struct directory *dir, *search();
X	void reset_dir(), free();
X					/* nothing required */
X	if (*path == '\0')
X		return(0);
X
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == 0x0)
X			break;
X					/* if erased */
X		if (dir->name[0] == 0xe5)
X			continue;
X					/* skip if not a directory */
X		if (!(dir->attr & 0x10))
X			continue;
X
X		strncpy(name, (char *) dir->name, 8);
X		strncpy(ext, (char *) dir->ext, 3);
X		name[8] = '\0';
X		ext[3] = '\0';
X
X		newname = unixname(name, ext);
X		if (!strcmp(newname, path)) {
X			start = dir->start[1]*0x100 + dir->start[0];
X					/* if '..' pointing to root */
X			if (!start && !strcmp(path, "..")) {
X				reset_dir();
X				return(0);
X			}
X					/* fill in the directory chain */
X			dir_entries = get_chain(start) * 16;
X			return(0);
X		}
X		free(newname);
X	}
X					/* if '.' or '..', must be root */
X	if (!strcmp(path, ".") || !strcmp(path, "..")) {
X		reset_dir();
X		return(0);
X	}
X	fprintf(stderr, "Path component \"%s\" is not a directory\n", path);
X	return(1);
X}
X
X/*
X * Fill in the global variable dir_chain.  Argument is the starting
X * cluster number.  Info, in this variable is used by search() to 
X * scan a directory.  An arbitrary limit of 25 sectors is placed, this
X * equates to 400 entries.  Returns the number of sectors in the chain.
X */
X
Xint
Xget_chain(num)				/* fill the directory chain */
Xint num;
X{
X	int i, next;
X	void exit();
X
X	i = 0;
X	while (1) {
X		dir_chain[i] = (num - 2)*clus_size + dir_start + dir_len;
X					/* sectors, not clusters! */
X		if (clus_size == 2) {
X			dir_chain[i+1] = dir_chain[i] + 1;
X			i++;
X		}
X		i++;
X		if (i >= 25) {
X			fprintf(stderr, "get_chain: directory too large\n");
X			exit(1);
X		}
X					/* get next cluster number */
X		next = getfat(num);
X		if (next == -1) {
X			fprintf(stderr, "get_chain: FAT problem\n");
X			exit(1);
X		}
X					/* end of cluster chain */
X		if (next >= 0xff8) {
X			break;
X		}
X		num = next;
X	}
X	return(i);
X}
X
X/* 
X * Reset the global variable dir_chain to the root directory.
X */
X
Xvoid
Xreset_dir()
X{
X	register int i;
X
X	for (i=0; i<dir_len; i++)
X		dir_chain[i] = dir_start + i;
X	dir_entries = dir_len * 16;
X					/* disable subdir() optimization */
X	lastpath[0] = '\0';
X	return;
X}
END_OF_FILE
if test 3775 -ne `wc -c <'subdir.c'`; then
    echo shar: \"'subdir.c'\" unpacked with wrong size!
fi
# end of 'subdir.c'
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
	Viktor Dukhovni <viktor@math.princeton.edu>	: ARPA
		<...!uunet!princeton!math!viktor>	: UUCP
	Fine Hall, Washington Rd., Princeton, NJ 08544  : US-Post
		+1-(609)-258-5792		 	: VOICE


