From decwrl!elroy.jpl.nasa.gov!usc!cs.utexas.edu!uunet!allbery Sun Mar 25 18:43:53 PST 1990
Article 1456 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: v11i081: Fast mtools,  + mkdfs for SparcStation1 or Sun-3/80 Part 1
Keywords: DOS, floppy
Message-ID: <82377@uunet.UU.NET>
Date: 26 Mar 90 00:15:31 GMT
Sender: allbery@uunet.UU.NET
Lines: 2159
Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)

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

	By permission of Emmet Gray I am reposting "mtools"

The comp.sources.unix archives are out of date wrt Emmet's latest version
and I have added a somewhat more general driver support mechanism,   so
that the Unix PC and other machines that can read DOS disks only after
various parameters are changed with disk ioctls can be supported more easily.

	Included is "mkdfs" an "mkfs" for dos disks,  currently this
works only with 3.5", 80 track disks, and knows the path of the low level format
program only on the SparcStation 1 or Sun 3/80.  A more general program
based on an external table (/etc/dosformat.dat?) should be written one day.

	The mread and mwrite are considerably faster on fresh disks,
up to a factor of 12 for large files on high density disks.  The algorithm
degrades to the original speed once files get substantially fragemented,
A more robust algorithm is possible,  but this is quite good enough for
moving files around,  which is the main application I would expect to see
for this package.  

	Enjoy!  And please send those bug fixes or improvements,  the
package is still 90% Emmet's code,  so I would much have preferred for him
to resubmit it,  but there is a lot of demand for it now with the desktop
Suns selling in unprecedented numbers,  and Emmet did not have much time
to devote to this.  The only bug I am aware of now is that globbing DOS
file names does not work entirely as expected.  This should either be fixed
or documented.

	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

#! /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 1 (of 3)."
# Contents:  Customize MANIFEST Makefile Mcopy.1 Mdel.1 Mdir.1 Mkdfs.1
#   Mmd.1 Mrd.1 Mread.1 Mren.1 Mtype.1 Mwrite.1 bootblk.h convdate.c
#   devices.c devices.h fixname.c getfat.c isdir.c match.c mcopy.c
#   mdel.c mkentry.c msdos.h putfat.c search.c unixname.c
# Wrapped by viktor@cucumber on Fri Mar 16 20:50:05 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Customize' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Customize'\"
else
echo shar: Extracting \"'Customize'\" \(2654 characters\)
sed "s/^X//" >'Customize' <<'END_OF_FILE'
XHow to configure Mtools for non-standard disk formats...
X
XThere are three approaches to the problem of trying to read and write
XMSDOS formatted diskettes in a Unix box doesn't have a floppy drive
Xthat meets the physical drive requirements.  For example, if your
XUnix box only has a 80 track floppy, you can:
X
X	1) Get a device driver to "double step" the 80 track drive
X	to read and write to 40 track diskettes.
X
X		Pros: No new hardware costs.
X		Cons: Device drivers are a bitch to write (or
X	  	      	expensive to buy).
X		      Success rates are low when using 80 track
X			drives to write 40 tracks.
X
X	2) Get a conventional device driver and purchase a 40 track
X	drive.  You'll still need the device driver unless your 
X	Unix vendor was thoughtful enough to leave you some "extras".
X
X		Pros: High success rates (40 track to 40 track)
X		Cons: The "foriegn" drive may cause trouble with
X			maintenance contracts
X
X	3) Purchase a 80 track drive for your PC.  This exploits the
X	fact that MSDOS already has a configurable device driver
X	feature.
X
X		Pros: You don't alter your Unix box in any way.
X		Cons: You'll have to process all MSDOS diskettes
X			thru the one PC before using Mtools.
X
X               +--------+          +-----------+
X          +--> | Unix   |          |  IBM PC   |
X          |    | box    |          |  clone    |
X        mtools +--------+          +-----+-----+
X          |    | 80 trk |          | 80  | 40  |        MSDOS
X          +--> | track  | <------> | trk | trk | <----> world
X               +--------+          +-----+-----+
X                                    ^         ^
X                                    |  MSDOS  |
X                                    +- COPY --+
X
XHow to customize Mtools...
X
XThe program can be easily customized to accept non-standard disk
Xformats.  For example, a popular disk format for Unix machines seems to
Xbe 80 track, double sided, 8 sector.  This doesn't conform to any of the
XIBM standard formats, but MSDOS 3.2 (or greater) can be made to format
Xvirtually anything using DRIVPARM (or DRIVER.SYS) in the CONFIG.SYS
Xfile.  Let's take a hypothetical case of a brand X Unix machine with a
X80 track, double sided, 8 sector disk drive.  You could purchase an
Xexternal 80 track drive for your IBM compatible computer and format the
Xnew drive D: under MSDOS with the following in your CONFIG.SYS file
X
X	DRIVPARM=/D:2 /T:80 /S:8 /H:2 /F:2
X		or
X	DEVICE=DRIVER.SYS /D:2 /T:80 /S:8 /H:2 /F:2
X
X
XEmmet P. Gray				US Army, HQ III Corps & Fort Hood
X...!unnet!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 2654 -ne `wc -c <'Customize'`; then
    echo shar: \"'Customize'\" unpacked with wrong size!
fi
# end of 'Customize'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(1305 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X Customize                  1	
X MANIFEST                   1	
X Makefile                   1	
X Mcopy.1                    1	
X Mdel.1                     1	
X Mdir.1                     1	
X Mkdfs.1                    1	
X Mmd.1                      1	
X Mrd.1                      1	
X Mread.1                    1	
X Mren.1                     1	
X Mtype.1                    1	
X Mwrite.1                   1	
X Readme                     2	
X bootblk.h                  1	
X convdate.c                 1	
X devices.c                  1	
X devices.h                  1	
X fixname.c                  1	
X getfat.c                   1	
X init.c                     2	
X isdir.c                    1	
X match.c                    1	
X mcopy.c                    1	
X mdel.c                     1	
X mdir.c                     2	
X mkdfs.c                    2	
X mkentry.c                  1	
X mmd.c                      2	
X mrd.c                      2	
X mread.c                    2	
X mren.c                     2	
X msdos.h                    1	
X mtype.c                    2	
X mwrite.c                   3	
X putfat.c                   1	
X search.c                   1	
X subdir.c                   2	
X unixname.c                 1	
END_OF_FILE
if test 1305 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(2592 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X#       Makefile for MSDOS tools
X#
X
XCFLAGS	= -g
XLDFLAGS	= 
XLINT	= lint -p
X#
X# Rich Salz's excelent cshar package.
X# Available from comp.sources.unix archives.
X#
XSHAR	= makekit -m
XBINDIR	= /u/viktor/bin/sun4
XMANDIR  = /u/viktor/man/man1
XPROGS	= mdir mread mwrite mdel mtype mmd mrd mren mcopy mkdfs
XCMNOBJ = init.o search.o unixname.o subdir.o getfat.o devices.o
X
XMKDFS   = mkdfs.o
XMDIR	= mdir.o match.o convdate.o isdir.o $(CMNOBJ)
XMREAD	= mread.o match.o convdate.o $(CMNOBJ)
XMWRITE	= mwrite.o fixname.o putfat.o mkentry.o isdir.o $(CMNOBJ)
XMDEL	= mdel.o match.o putfat.o $(CMNOBJ)
XMTYPE	= mtype.o match.o $(CMNOBJ)
XMMD	= mmd.o fixname.o putfat.o mkentry.o $(CMNOBJ)
XMRD	= mrd.o putfat.o $(CMNOBJ)
XMREN	= mren.o fixname.o putfat.c isdir.o $(CMNOBJ)
XMCOPY	= mcopy.o
X
Xall:	$(PROGS)
X
Xmkdfs:  $(MKDFS)
X	$(CC) $(LDFLAGS) $(MKDFS) -o mkdfs
X
Xmdir:	$(MDIR)
X	$(CC) $(LDFLAGS) $(MDIR) -o mdir
X
Xmread:	$(MREAD)
X	$(CC) $(LDFLAGS) $(MREAD) -o mread
X
Xmwrite:	$(MWRITE)
X	$(CC) $(LDFLAGS) $(MWRITE) -o mwrite
X
Xmdel:	$(MDEL)
X	$(CC) $(LDFLAGS) $(MDEL) -o mdel
X
Xmtype:	$(MTYPE)
X	$(CC) $(LDFLAGS) $(MTYPE) -o mtype
X
Xmmd:	$(MMD)
X	$(CC) $(LDFLAGS) $(MMD) -o mmd
X
Xmrd:	$(MRD)
X	$(CC) $(LDFLAGS) $(MRD) -o mrd
X
Xmren:	$(MREN)
X	$(CC) $(LDFLAGS) $(MREN) -o mren
X
Xmcopy:	$(MCOPY)
X	$(CC) $(LDFLAGS) $(MCOPY) -o mcopy
X
Xinstall: all
X	cp mdir $(BINDIR)/mdir
X	cp mread $(BINDIR)/mread
X	cp mwrite $(BINDIR)/mwrite
X	cp mdel $(BINDIR)/mdel
X	cp mtype $(BINDIR)/mtype
X	cp mmd $(BINDIR)/mmd
X	cp mrd $(BINDIR)/mrd
X	cp mren $(BINDIR)/mren
X	cp mcopy $(BINDIR)/mcopy
X
Xinstall-man:
X	cp Mread.1 $(MANDIR)/mread.1
X	cp Mdir.1 $(MANDIR)/mdir.1
X	cp Mwrite.1 $(MANDIR)/mwrite.1
X	cp Mdel.1 $(MANDIR)/mdel.1
X	cp Mtype.1 $(MANDIR)/mtype.1
X	cp Mmd.1 $(MANDIR)/mmd.1
X	cp Mrd.1 $(MANDIR)/mrd.1
X	cp Mren.1 $(MANDIR)/mren.1
X	cp Mcopy.1 $(MANDIR)/mcopy.1
X
Xclean:
X	rm $(PROGS) *.o
X
Xlint:
X	$(LINT) mdir.c getfat.c init.c search.c match.c convdate.c subdir.c \
X	unixname.c isdir.c
X	$(LINT) mread.c getfat.c init.c search.c match.c unixname.c subdir.c
X	$(LINT) mwrite.c getfat.c init.c search.c fixname.c unixname.c \
X	putfat.c subdir.c mkentry.c isdir.c
X	$(LINT) mdel.c getfat.c init.c search.c match.c unixname.c putfat.c \
X	subdir.c
X	$(LINT) mtype.c getfat.c init.c search.c match.c unixname.c subdir.c
X	$(LINT) mmd.c getfat.c init.c search.c fixname.c unixname.c putfat.c \
X	subdir.c mkentry.c
X	$(LINT) mrd.c getfat.c init.c search.c unixname.c putfat.c subdir.c
X	$(LINT) mren.c getfat.c init.c search.c fixname.c unixname.c putfat.c \
X	subdir.c
X	$(LINT) mcopy.c
X
Xshar:
X	$(SHAR) MANIFEST Customize Makefile Readme *.[1ch]
X
Xinit.o:	msdos.h devices.h
END_OF_FILE
if test 2592 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'Mcopy.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Mcopy.1'\"
else
echo shar: Extracting \"'Mcopy.1'\" \(1676 characters\)
sed "s/^X//" >'Mcopy.1' <<'END_OF_FILE'
X.TH MCOPY 1 local
X.SH NAME
Xmcopy \- copy MSDOS files to/from Unix
X.SH SYNOPSIS
X.B mcopy
X[
X.B -tnvm
X] unixfile a:msdosfile
X.PP
X.B mcopy
X[
X.B -tnvm
X] unixfile [ unixfiles... ] a:msdosdirectory
X.PP
X.B mcopy
X[
X.B -tnm
X] a:msdosfile unixfile
X.PP
X.B mcopy
X[
X.B -tnm
X] a:msdosfile [ a:msdosfiles... ] unixdirectory
X.SH DESCRIPTION
XIn the first two forms,
X.I mcopy
Xcopies the specified Unix file to the named MSDOS file or copies
Xmultiple Unix files to the named MSDOS directory.  The last two forms
Xcopy MSDOS files to Unix.  MSDOS sub directories are supported with
Xeither the '/' or '\e\' separator.  The use of the '\e\' separator or
Xwildcards will require the names to be enclosed in quotes to protect
Xthem from the shell.
X.PP
XThe use of the 'a:' drive designation on the MSDOS files determines the
Xdirection of the transfer.  A missing drive designation implies a Unix
Xfile whose path starts in the current directory 
X.PP
X.I Mcopy
Xwill allow the following command line options:
X.TP
X.B t
XText file transfer.
X.I Mcopy
Xwill translate incoming carriage return/line feeds to line feeds.
X.TP
X.B n
XNo warning.
X.I Mcopy
Xwill not warn the user when overwriting an existing file.
X.TP
X.B v
Xverbose mode.
X.TP
X.B m
XPreserve the file modification time.
X.PP
XIf the target file already exists, and the
X.I -n
Xoption is not in effect,
X.I mcopy
Xasks whether or not to overwrite the file.
X.PP
XThe environmental variable MCWD may be used to establish a current
Xworking directory (relative to the MSDOS diskette).
X.SH SEE ALSO
Xmdir(1), mtype(1), mread(1), mwrite(1)
X.SH BUGS
XWildcards are only applied to filenames, not to directory names.
XUnlike MSDOS, the destination directory may not be omitted.
END_OF_FILE
if test 1676 -ne `wc -c <'Mcopy.1'`; then
    echo shar: \"'Mcopy.1'\" unpacked with wrong size!
fi
# end of 'Mcopy.1'
fi
if test -f 'Mdel.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Mdel.1'\"
else
echo shar: Extracting \"'Mdel.1'\" \(869 characters\)
sed "s/^X//" >'Mdel.1' <<'END_OF_FILE'
X.TH MDEL 1 local
X.SH NAME
Xmdel \- delete a MSDOS file
X.SH SYNOPSIS
X.B mdel
X[
X.B -v
X] msdosfile [ msdosfiles...  ]
X.SH DESCRIPTION
X.I Mdel
Xdeletes a file on a MSDOS formatted diskette.  Sub directories are supported
Xwith either the '/' or '\e\' separator.  The use of the '\e\' separator
Xor wildcards will require the names to be enclosed in quotes to protect
Xthem from the shell.
X.PP
X.I Mdel
Xwill allow the following command line option:
X.TP
X.B v
XVerbose mode.  Echo the file names as they are processed.
X.PP
X.I Mdel
Xwill ask for verification prior to removing a read\-only file.
X.PP
XThe environmental variable MCWD may be used to establish a current
Xworking directory (relative to the MSDOS diskette).
X.SH SEE ALSO
Xmdir(1)
X.SH BUGS
XAllows multiple arguments, which does not follow the MSDOS convention.
XWildcards are only applied to filenames, not to directory names.
END_OF_FILE
if test 869 -ne `wc -c <'Mdel.1'`; then
    echo shar: \"'Mdel.1'\" unpacked with wrong size!
fi
# end of 'Mdel.1'
fi
if test -f 'Mdir.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Mdir.1'\"
else
echo shar: Extracting \"'Mdir.1'\" \(975 characters\)
sed "s/^X//" >'Mdir.1' <<'END_OF_FILE'
X.TH MDIR 1 local
X.SH NAME
Xmdir \- display a MSDOS directory
X.SH SYNOPSIS
X.B mdir
X[
X.B -w
X] msdosdirectory
X.PP
X.B mdir
X[
X.B -w
X] msdosfile [ msdosfiles...  ] 
X.SH DESCRIPTION
X.I Mdir
Xdisplays the contents of a MSDOS formatted diskette.  Sub directories
Xare supported with either the '/' or '\e\' separator.  The use of 
Xthe '\e\' separator or wildcards will require the names to be enclosed
Xin quotes to protect them from the shell.
X.PP
X.I Mdir
Xwill allow the following command line option:
X.TP
X.B w
XWide output.  This option will print the file names across the page
Xwithout displaying the file size or creation date.
X.PP
XAn error occurs if a component of the path is not a directory.
X.PP
XThe environmental variable MCWD may be used to establish a current
Xworking directory (relative to the MSDOS diskette).
X.SH SEE ALSO
Xmtype(1)
X.SH BUGS
XAllows multiple arguments, which does not follow the MSDOS convention.
XWildcards are only applied to filenames, not to directory names.
END_OF_FILE
if test 975 -ne `wc -c <'Mdir.1'`; then
    echo shar: \"'Mdir.1'\" unpacked with wrong size!
fi
# end of 'Mdir.1'
fi
if test -f 'Mkdfs.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Mkdfs.1'\"
else
echo shar: Extracting \"'Mkdfs.1'\" \(862 characters\)
sed "s/^X//" >'Mkdfs.1' <<'END_OF_FILE'
X.TH MKDFS 1 local
X.SH NAME
Xmkdfs \- Initialize an MSDOS disk.
X.SH SYNOPSIS
X.B mkdfs
X[
X.B -h
X]
X[
X.B -f
X]
X.SH DESCRIPTION
X.I Mkdfs
XMkdfs formats and initializes a DOS file system on a 3.5 inch Sun 4/60 or
X3/80 internal floppy.  It first calls the standard Sun format utility and 
Xthen lays out an empty filesystem.
X.PP
X.I Mkdfs
Xaccepts the following options:
X.TP
X.B h
XHigh density switch.
XSince 720K disks are far more common in the DOS world,  the lower
Xdensity is the default,  use this option for the high density 1.44MB disks.
X.TP
X.B f
XFirst reformat the drive,  useful for new or abused drives.  (Using the drive
Xin a Mac counts in the last category)
X.SH SEE ALSO
Xmdir(1), mread(1), mtype(1), mren(1), mkd(1), mrd(1), mdel(1), mcopy(1)
X.SH AUTHOR
XViktor Dukhovni, <viktor@math.princeton.edu>
X.SH BUGS
XShould detect high density disks obsoleting the h option.
END_OF_FILE
if test 862 -ne `wc -c <'Mkdfs.1'`; then
    echo shar: \"'Mkdfs.1'\" unpacked with wrong size!
fi
# end of 'Mkdfs.1'
fi
if test -f 'Mmd.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Mmd.1'\"
else
echo shar: Extracting \"'Mmd.1'\" \(906 characters\)
sed "s/^X//" >'Mmd.1' <<'END_OF_FILE'
X.TH MMD 1 local
X.SH NAME
Xmmd \- make a MSDOS sub directory
X.SH SYNOPSIS
X.B mmd
X[
X.B -v
X] msdosdirectory
X.SH DESCRIPTION
X.I Mmd
Xmakes a new directory on a MSDOS formatted diskette.  Sub directories
Xare supported with either the '/' or '\e\' separator.  The use of
Xthe '\e\' separator will require the directory name to be enclosed in
Xquotes to protect it from the shell.
X.PP
X.I Mmd
Xwill allow the following command line option:
X.TP
X.B v
XVerbose mode.  Display the new directory name if the name supplied is
Xinvalid.
X.PP
XReasonable care is taken to create a valid MSDOS directory name.  If an
Xinvalid name is specified,
X.I mmd
Xwill change the name (and display the new name if the verbose mode is
Xset).
X.PP
XAn error occurs if the directory already exists.
X.PP
XThe environmental variable MCWD may be used to establish a current
Xworking directory (relative to the MSDOS diskette).
X.SH SEE ALSO
Xmdir(1), mrd(1)
END_OF_FILE
if test 906 -ne `wc -c <'Mmd.1'`; then
    echo shar: \"'Mmd.1'\" unpacked with wrong size!
fi
# end of 'Mmd.1'
fi
if test -f 'Mrd.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Mrd.1'\"
else
echo shar: Extracting \"'Mrd.1'\" \(598 characters\)
sed "s/^X//" >'Mrd.1' <<'END_OF_FILE'
X.TH MRD 1 local
X.SH NAME
Xmrd \- remove a MSDOS sub directory
X.SH SYNOPSIS
X.B mrd
Xmsdosdirectory
X.SH DESCRIPTION
X.I Mrd
Xremoves a directory from a MSDOS formatted diskette.  Sub directories
Xare supported with either the '/' or '\e\' separator.  The use of
Xthe '\e\' separator will require the directory name to be enclosed in
Xquotes to protect it from the shell.
X.PP
XAn error occurs if the directory is not empty.
X.PP
XWildcards are not supported.
X.PP
XThe environmental variable MCWD may be used to establish a current
Xworking directory (relative to the MSDOS diskette).
X.SH SEE ALSO
Xmdir(1), mmd(1)
END_OF_FILE
if test 598 -ne `wc -c <'Mrd.1'`; then
    echo shar: \"'Mrd.1'\" unpacked with wrong size!
fi
# end of 'Mrd.1'
fi
if test -f 'Mread.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Mread.1'\"
else
echo shar: Extracting \"'Mread.1'\" \(1327 characters\)
sed "s/^X//" >'Mread.1' <<'END_OF_FILE'
X.TH MREAD 1 local
X.SH NAME
Xmread \- low level read (copy) a MSDOS file to Unix
X.SH SYNOPSIS
X.B mread
X[
X.B -tnm
X] msdosfile unixfile
X.PP
X.B mread
X[
X.B -tnm
X] msdosfile [ msdosfiles... ] unixdirectory
X.SH DESCRIPTION
XIn the first form,
X.I mread
Xcopies the specified MSDOS file to the named Unix file.  The second form
Xof the command copies multiple MSDOS files to the named Unix directory.
XMSDOS sub directories are supported with either the '/' or '\e\'
Xseparator.  The use of the '\e\' separator or wildcards will require the
Xnames to be enclosed in quotes to protect them from the shell.
X.PP
X.I Mread
Xwill allow the following command line options:
X.TP
X.B t
XText file transfer.
X.I Mread
Xwill translate incoming carriage return/line feeds to line feeds.
X.TP
X.B n
XNo warning.
X.I Mread
Xwill not warn the user when overwriting an existing file.
X.TP
X.B m
XPreserve the file modification times.
X.PP
XIf the target file already exists, and the
X.I -n
Xoption is not in effect,
X.I mread
Xasks whether or not to overwrite the file.
X.PP
XThe environmental variable MCWD may be used to establish a current
Xworking directory (relative to the MSDOS diskette).
X.SH SEE ALSO
Xmcopy(1), mdir(1), mtype(1), mwrite(1)
X.SH BUGS
XWildcards are only applied to filenames, not to directory names.
XUnlike MSDOS, the destination directory may not be omitted.
END_OF_FILE
if test 1327 -ne `wc -c <'Mread.1'`; then
    echo shar: \"'Mread.1'\" unpacked with wrong size!
fi
# end of 'Mread.1'
fi
if test -f 'Mren.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Mren.1'\"
else
echo shar: Extracting \"'Mren.1'\" \(1237 characters\)
sed "s/^X//" >'Mren.1' <<'END_OF_FILE'
X.TH MREN 1 local
X.SH NAME
Xmren \- rename an existing MSDOS file
X.SH SYNOPSIS
X.B mren
X[
X.B -v
X] sourcefile targetfile
X.SH DESCRIPTION
X.I Mren
Xrenames an existing file on a MSDOS formatted diskette.  Sub directories
Xare supported with either the '/' or '\e\' separator.  The use of
Xthe '\e\' separator or wildcards will require the names to be enclosed
Xin quotes to protect them from the shell.
X.PP
X.I Mren
Xwill allow the following command line option:
X.TP
X.B v
XVerbose mode.  Display the new file name if the name supplied is
Xinvalid.
X.PP
XReasonable care is taken to create a valid MSDOS filename.  If an invalid
XMSDOS target name is specified,
X.I mren
Xwill change the name (and prompt the user to accept or reject the new name
Xif the verbose mode is set).
X.PP
XThe path component of the target filename (if supplied) is ignored.  In
Xother words, you may not use
X.I mren
Xto move a file from one sub directory to another.
X.PP 
X.I Mren
Xmay also be used to rename directories.
X.PP
XThe environmental variable MCWD may be used to establish a current
Xworking directory (relative to the MSDOS diskette).
X.SH SEE ALSO
Xmwrite(1)
X.SH BUGS
XWildcards are only applied to filenames, not to directory names.
XMSDOS doesn't use ren to rename directories.
END_OF_FILE
if test 1237 -ne `wc -c <'Mren.1'`; then
    echo shar: \"'Mren.1'\" unpacked with wrong size!
fi
# end of 'Mren.1'
fi
if test -f 'Mtype.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Mtype.1'\"
else
echo shar: Extracting \"'Mtype.1'\" \(978 characters\)
sed "s/^X//" >'Mtype.1' <<'END_OF_FILE'
X.TH MTYPE 1 local
X.SH NAME
Xmtype \- display contents of a MSDOS file
X.SH SYNOPSIS
X.B mtype
X[
X.B -ts
X] msdosfile [ msdosfiles... ]
X.SH DESCRIPTION
X.I Mtype
Xdisplays the specified MSDOS file on the screen.  MSDOS sub directories
Xare supported with either the '/' or '\e\' separator.  The use of 
Xthe '\e\' separator or wildcards will require the names to be enclosed
Xin quotes to protect them from the shell.
X.PP
X.I Mtype
Xwill allow the following command line options:
X.TP
X.B t
XText file viewing.
X.I Mtype
Xwill translate incoming carriage return/line feeds to line feeds.
X.TP
X.B s
XStrip high bit.
X.I Mtype
Xwill strip the high bit from the data.  Useful for viewing Wordstar files.
X.PP
XThe environmental variable MCWD may be used to establish a current
Xworking directory (relative to the MSDOS diskette).
X.SH SEE ALSO
Xmdir(1), mread(1)
X.SH BUGS
XAllows multiple arguments, which does not follow the MSDOS convention.
XWildcards are only applied to filenames, not to directory names.
END_OF_FILE
if test 978 -ne `wc -c <'Mtype.1'`; then
    echo shar: \"'Mtype.1'\" unpacked with wrong size!
fi
# end of 'Mtype.1'
fi
if test -f 'Mwrite.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Mwrite.1'\"
else
echo shar: Extracting \"'Mwrite.1'\" \(1594 characters\)
sed "s/^X//" >'Mwrite.1' <<'END_OF_FILE'
X.TH MWRITE 1 local
X.SH NAME
Xmwrite \- low level write (copy) a Unix file to MSDOS
X.SH SYNOPSIS
X.B mwrite
X[
X.B -tnvm
X] unixfile msdosfile
X.PP
X.B mwrite
X[
X.B -tnvm
X] unixfile [ unixfiles... ] msdosdirectory
X.SH DESCRIPTION
XIn the first form,
X.I mwrite
Xcopies the specified Unix file to the named MSDOS file.  The second form
Xof the command copies multiple Unix files to the named MSDOS directory.
XMSDOS sub directories are are supported with either the '/' or '\e\'
Xseparator.  The use of the '\e\' separator will require the names to be
Xenclosed in quotes to protect them from the shell.
X.PP
X.I Mwrite
Xwill allow the following command line options:
X.TP
X.B t
XText file transfer.
X.I Mwrite
Xwill translate incoming line feeds to carriage return/line feeds.
X.TP
X.B n
XNo warning.
X.I Mwrite
Xwill not warn the user when overwriting an existing file.
X.TP
X.B v
XVerbose mode.  Display the new file name if the Unix file name requires
Xconversion.
X.TP
X.B m
XPreserve the file modification times.
X.PP
XIf the target file already exists, and the
X.I -n
Xoption is not in effect,
X.I mwrite
Xasks whether or not to overwrite the file.
X.PP
XReasonable care is taken to create a valid MSDOS filename.  If an
Xinvalid name is specified,
X.I mwrite
Xwill change the name (and display the new name if the verbose mode is
Xset).
X.PP
XThe environmental variable MCWD may be used to establish a current
Xworking directory (relative to the MSDOS diskette).
X.SH SEE ALSO
Xmcopy(1), mdir(1), mread(1)
X.SH BUGS
XWildcards are only applied to filenames, not to directory names.
XUnlike MSDOS, the destination directory may not be omitted.
END_OF_FILE
if test 1594 -ne `wc -c <'Mwrite.1'`; then
    echo shar: \"'Mwrite.1'\" unpacked with wrong size!
fi
# end of 'Mwrite.1'
fi
if test -f 'bootblk.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bootblk.h'\"
else
echo shar: Extracting \"'bootblk.h'\" \(625 characters\)
sed "s/^X//" >'bootblk.h' <<'END_OF_FILE'
X/*
X * Just enough of a high/low density 3.5" DOS boot block
X * to define the FS parameters,  should keep us out of Copyright
X * trouble!  If someone wants DOS bootable filesystems,
X * include the complete boot block for your machine,
X * and make sure to create the "hidden" files in mkdfs.c
X * (this is not easy!)
X */
Xstatic unsigned short hdboot[] = {
X0xeb34,0x9020,0x2020,0x2020,0x2020,0x2000,0x0201,0x0100,
X0x02e0,0x0040,0x0bf0,0x0900,0x1200,0x0200,0x0000,0x0000,
X} ;
X
Xstatic unsigned short ldboot[] = {
X0xeb34,0x9020,0x2020,0x2020,0x2020,0x2000,0x0202,0x0100,
X0x0270,0x00a0,0x05f9,0x0300,0x0900,0x0200,0x0000,0x0000,
X} ;
END_OF_FILE
if test 625 -ne `wc -c <'bootblk.h'`; then
    echo shar: \"'bootblk.h'\" unpacked with wrong size!
fi
# end of 'bootblk.h'
fi
if test -f 'convdate.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'convdate.c'\"
else
echo shar: Extracting \"'convdate.c'\" \(2461 characters\)
sed "s/^X//" >'convdate.c' <<'END_OF_FILE'
X/*
X * convdate(), convtime(), convstamp()
X */
X#include <stdio.h>
X/*
X * convert MSDOS directory datestamp to ASCII.
X */
X
Xchar *
Xconvdate(date_high, date_low)
Xunsigned date_high, date_low;
X{
X/*
X *	    hi byte     |    low byte
X *	|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
X *      | | | | | | | | | | | | | | | | |
X *      \   7 bits    /\4 bits/\ 5 bits /
X *         year +80      month     day
X */
X	static char ans[9];
X	unsigned char year, month_hi, month_low, day;
X
X	year = (date_high >> 1) + 80;
X	month_hi = (date_high & 0x1) << 3;
X	month_low = date_low >> 5;
X	day = date_low & 0x1f;
X	sprintf(ans, "%2d-%02d-%02d", month_hi+month_low, day, year);
X	return(ans);
X}
X
X/*
X * Convert MSDOS directory timestamp to ASCII.
X */
X
Xchar *
Xconvtime(time_high, time_low)
Xunsigned time_high, time_low;
X{
X/*
X *	    hi byte     |    low byte
X *	|7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
X *      | | | | | | | | | | | | | | | | |
X *      \  5 bits /\  6 bits  /\ 5 bits /
X *         hour      minutes     sec*2
X */
X	static char ans[7];
X	char am_pm;
X	unsigned char hour, min_hi, min_low;
X
X	hour = time_high >> 3;
X	am_pm = (hour >= 12) ? 'p' : 'a';
X	if (hour > 12)
X		hour = hour -12;
X	if (hour == 0)
X		hour = 12;
X	min_hi = (time_high & 0x7) << 3;
X	min_low = time_low >> 5;
X	sprintf(ans, "%2d:%02d%c", hour, min_hi+min_low, am_pm);
X	return(ans);
X}
X
X/*
X * Convert a MSDOS time & date stamp to the Unix time() format
X */
X
Xlong
Xconvstamp(time_field, date_field)
Xunsigned char *time_field, *date_field;
X{
X	extern long timezone;
X	int year, mon, mday, hour, min, sec, old_leaps;
X	long answer, sec_year, sec_mon, sec_mday, sec_hour, sec_min, sec_leap;
X	static int month[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304,
X	334};
X					/* disect the parts */
X	year = (date_field[1] >> 1) + 1980;
X	mon = (((date_field[1] & 0x1) << 3) + (date_field[0] >> 5));
X	mday = date_field[0] & 0x1f;
X	hour = time_field[1] >> 3;
X	min = (((time_field[1] & 0x7) << 3) + (time_field[0] >> 5));
X	sec = (time_field[0] & 0x1f) * 2;
X					/* how many previous leap years */
X	old_leaps = (year -1972) / 4;
X	sec_leap = old_leaps * 24 * 60 * 60;
X					/* back off 1 day if before 29 Feb */
X	if (!(year % 4) && mon < 3)
X		sec_leap -= 24 * 60 * 60;
X	sec_year = (year - 1970) * 365 * 24 * 60 * 60;
X	sec_mon = month[mon -1] * 24 * 60 * 60;
X	sec_mday = mday * 24 * 60 * 60;
X	sec_hour = hour * 60 * 60;
X	sec_min = min * 60;
X	
X	answer = sec_leap + sec_year + sec_mon + sec_mday + sec_hour + sec_min + sec + timezone;
X	return(answer);
X}
END_OF_FILE
if test 2461 -ne `wc -c <'convdate.c'`; then
    echo shar: \"'convdate.c'\" unpacked with wrong size!
fi
# end of 'convdate.c'
fi
if test -f 'devices.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'devices.c'\"
else
echo shar: Extracting \"'devices.c'\" \(1936 characters\)
sed "s/^X//" >'devices.c' <<'END_OF_FILE'
X#ifndef lint
Xstatic char RCSid[]="$Header: /auto/n/melon/b/viktor/src/nmt/RCS/devices.c,v 1.3 90/03/16 02:52:20 viktor Exp Locker: viktor $" ;
X#endif
X/*
X *  Device switch for "mtools",  each driver defines a device name,
X *  an initialization function, and extra "open" flags,  typically to allow
X *  NDELAY for opening floppies with non-default sectoring,  which otherwise
X *  yield EIO
X *
X * $Log:	devices.c,v $
X * Revision 1.3  90/03/16  02:52:20  viktor
X * *** empty log message ***
X * 
X * Revision 1.2  90/03/08  20:29:59  viktor
X * Added unixpc support.
X * 
X */
X#include "devices.h"
X
X#ifdef sun
X#include <fcntl.h>
X#endif
X
X#ifdef unixpc
X#include <sys/gdioctl.h>
X#include <fcntl.h>
Xint unixpc_fd_init() ;
X#endif
X
Xstruct device fd_devices[] = {
X
X#ifdef sun
X  {"/dev/rfd0c", (int (*)())0, 0 },
X#endif
X#ifdef unixpc
X  {"/dev/rfp020", unixpc_fd_init, O_NDELAY},
X#endif
X  {(char*)0, (int (*)())0, 0}
X} ;
X
X#ifdef unixpc
Xunixpc_fd_init(fd,ncyl,ntrack,nsect)
X     int fd,ncyl,ntrack,nsect;
X{
X  struct gdctl gdbuf;
X
X  if( ! ncyl && ! nsect && ! ntrack ) {
X    ncyl = 40;
X    /* Default to 1 track, will reset to 2 later if needed */
X    ntrack = 1;
X    nsect = 8;
X  }
X
X  if ( ioctl(fd,GDGETA,&gdbuf) == -1 ) {
X    perror("init: ioctl: GDGETA") ;
X    dismount(fd) ;
X  }
X
X  if (ncyl) gdbuf.params.cyls = ncyl;
X  if (ntrack) gdbuf.params.heads = ntrack;
X  if (nsect) gdbuf.params.psectrk = nsect;
X
X  gdbuf.params.pseccyl = gdbuf.params.psectrk * gdbuf.params.heads ;
X  gdbuf.params.flags = 1;		/* disk type flag */
X  gdbuf.params.step = 0;		/* step rate for controller */
X  gdbuf.params.sectorsz = 512;		/* sector size */
X
X  if (ioctl(fd, GDSETA, &gdbuf) < 0) {
X    perror("init: ioctl: GDSETA");
X    dismount(fd);
X  }
X}
X
X/*
X * Dismount the floppy.  Useful only if one of the above ioctls fail
X * and leaves the drive light turned on.
X */
Xvoid
Xdismount(fd)
X{
X	struct gdctl gdbuf;
X	void exit();
X
X	ioctl(fd, GDDISMNT, &gdbuf);
X	exit(1);
X}
X#endif
END_OF_FILE
if test 1936 -ne `wc -c <'devices.c'`; then
    echo shar: \"'devices.c'\" unpacked with wrong size!
fi
# end of 'devices.c'
fi
if test -f 'devices.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'devices.h'\"
else
echo shar: Extracting \"'devices.h'\" \(76 characters\)
sed "s/^X//" >'devices.h' <<'END_OF_FILE'
Xstruct device {
X  char *drv_dev;
X  int (*drv_ifunc)() ;
X  int drv_mode;
X} ;
END_OF_FILE
if test 76 -ne `wc -c <'devices.h'`; then
    echo shar: \"'devices.h'\" unpacked with wrong size!
fi
# end of 'devices.h'
fi
if test -f 'fixname.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'fixname.c'\"
else
echo shar: Extracting \"'fixname.c'\" \(1871 characters\)
sed "s/^X//" >'fixname.c' <<'END_OF_FILE'
X/*
X * Convert a Unix filename to a legal MSDOS name.  Returns a pointer to
X * the 'fixed' name.  Will truncate file and extension names, will
X * substitute the letter 'X' for any illegal character in the name.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include "msdos.h"
X
Xchar *
Xfixname(filename, verbose)
Xchar *filename;
Xint verbose;
X{
X	static char *dev[8] = {"CON", "AUX", "COM1", "LPT1", "PRN", "LPT2",
X	"LPT3", "NUL"};
X	char *s, *ans, *name, *ext, *strcpy(), *strpbrk(), *strrchr();
X	char buf[MAX_PATH], *malloc();
X	int dot, modified;
X	register int i;
X
X	strcpy(buf, filename);
X	name = buf;
X					/* zap the leading path */
X	if (s = strrchr(name, '/'))
X		name = s+1;
X	if (s = strrchr(name, '\\'))
X		name = s+1;
X
X	ext = "";
X	dot = 0;
X	for (i=strlen(buf)-1; i>=0; i--) {
X		if (buf[i] == '.' && !dot) {
X			dot = 1;
X			buf[i] = '\0';
X			ext = &buf[i+1];
X		}
X		if (islower(buf[i]))
X			buf[i] = toupper(buf[i]);
X	}
X	if (*name == '\0') {
X		name = "X";
X		if (verbose)
X			printf("\"%s\" Null name component, using \"%s.%s\"\n", filename, name, ext);
X	}
X	for (i=0; i<8; i++) {
X		if (!strcmp(name, dev[i])) {
X			*name = 'X';
X			if (verbose)
X				printf("\"%s\" Is a device name, using \"%s.%s\"\n", filename, name, ext);
X		}
X	}
X	if (strlen(name) > 8) {
X		*(name+8) = '\0';
X		if (verbose)
X			printf("\"%s\" Name too long, using, \"%s.%s\"\n", filename, name, ext);
X	}
X	if (strlen(ext) > 3) {
X		*(ext+3) = '\0';
X		if (verbose)
X			printf("\"%s\" Extension too long, using \"%s.%s\"\n", filename, name, ext);
X	}
X	modified = 0;
X	while (s = strpbrk(name, "^+=/[]:',?*\\<>|\". ")) {
X		modified++;
X		*s = 'X';
X	}
X	while (s = strpbrk(ext, "^+=/[]:',?*\\<>|\". ")) {
X		modified++;
X		*s = 'X';
X	}
X	if (modified && verbose)
X		printf("\"%s\" Contains illegal character(s), using \"%s.%s\"\n", filename, name, ext);
X
X	ans = malloc(12);
X	sprintf(ans, "%-8.8s%-3.3s", name, ext);
X	return(ans);
X}
END_OF_FILE
if test 1871 -ne `wc -c <'fixname.c'`; then
    echo shar: \"'fixname.c'\" unpacked with wrong size!
fi
# end of 'fixname.c'
fi
if test -f 'getfat.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'getfat.c'\"
else
echo shar: Extracting \"'getfat.c'\" \(1365 characters\)
sed "s/^X//" >'getfat.c' <<'END_OF_FILE'
X/*
X * Get and decode a FAT (file allocation table) entry.  The FAT entries
X * are 1.5 bytes long and switch nibbles (.5 byte) according to whether
X * or not the entry starts on a byte boundary.  Returns the cluster 
X * number on success or -1 on failure.
X */
X
X#include "msdos.h"
X
Xextern int fat_len;
Xextern unsigned char *fatbuf;
X
Xint
Xgetfat(num)
Xint num;
X{
X/*
X *	|    byte n     |   byte n+1    |   byte n+2    |
X *	|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
X *	| | | | | | | | | | | | | | | | | | | | | | | | |
X *	|  n.0  |  n.5  | n+1.0 | n+1.5 | n+2.0 | n+2.5 |
X *	    \_____  \____   \______/________/_____   /
X *	      ____\______\________/   _____/  ____\_/
X *	     /     \      \          /       /     \
X *	| n+1.5 |  n.0  |  n.5  | n+2.0 | n+2.5 | n+1.0 |
X *	|      FAT entry k      |    FAT entry k+1      |
X */
X	unsigned int fat_hi, fat_low, byte_1, byte_2;
X	int start, fat;
X					/* which bytes contain the entry */
X	start = num * 3 / 2;
X	if (start < 0 || start+1 > (fat_len * MSECSIZ))
X		return(-1);
X
X	byte_1 = *(fatbuf + start);
X	byte_2 = *(fatbuf + start + 1);
X					/* (odd) not on byte boundary */
X	if (num % 2) {
X		fat_hi = (byte_2 & 0xff) << 4;
X		fat_low  = (byte_1 & 0xf0) >> 4;
X	}
X					/* (even) on byte boundary */
X	else {
X		fat_hi = (byte_2 & 0xf) << 8;
X		fat_low  = byte_1 & 0xff;
X	}
X	fat = (fat_hi + fat_low) & 0xfff;
X	return(fat);
X}
END_OF_FILE
if test 1365 -ne `wc -c <'getfat.c'`; then
    echo shar: \"'getfat.c'\" unpacked with wrong size!
fi
# end of 'getfat.c'
fi
if test -f 'isdir.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'isdir.c'\"
else
echo shar: Extracting \"'isdir.c'\" \(1001 characters\)
sed "s/^X//" >'isdir.c' <<'END_OF_FILE'
X/*
X * Test to see if a filename is a directory.  Subdir() has to be
X * run first...  Returns 1 if true.
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xextern int dir_entries;
X
Xint
Xisdir(path)
Xchar *path;
X{
X	register int entry;
X	char *newname, *unixname(), *strncpy(), name[9], ext[4];
X	struct directory *dir, *search();
X	void free();
X					/* no path */
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			free(newname);
X			return(1);
X		}
X		free(newname);
X	}
X					/* if "." or ".." fails, then root */
X	if (!strcmp(path, ".") || !strcmp(path, ".."))
X		return(1);
X
X	return(0);
X}
END_OF_FILE
if test 1001 -ne `wc -c <'isdir.c'`; then
    echo shar: \"'isdir.c'\" unpacked with wrong size!
fi
# end of 'isdir.c'
fi
if test -f 'match.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'match.c'\"
else
echo shar: Extracting \"'match.c'\" \(1894 characters\)
sed "s/^X//" >'match.c' <<'END_OF_FILE'
X/*
X * Do shell-style pattern matching for '?', '\', '[..]', and '*' wildcards.
X * Not idiot proof!  Returns 1 if match, 0 if not.
X *
X * Ideas for this routine were taken from a program by Rich Salz, mirror!rs
X */
X
X#include <stdio.h>
X
Xint
Xmatch(s, p)
Xchar *s;				/* string to match */
Xchar *p;				/* pattern */
X{
X	int matched, reverse;
X	char first, last;
X
X	for ( ; *p != '\0'; s++, p++) {
X		switch (*p) {
X					/* Literal match with next character */
X		case '\\':
X			p++;
X		default:
X			if (*s != *p)
X				return(0);
X			break;
X					/* match any one character */
X		case '?':
X			if (*s == '\0')
X				return(0);
X			break;
X					/* match everything */
X		case '*':
X					/* if last char in pattern */
X			if (*++p == '\0')
X				return(1);
X					/* search for next char in pattern */
X			matched = 0;
X			while (*s != '\0') {
X				if (*s == *p) {
X					matched = 1;
X					if (!strcmp(s+1,p+1))
X						break;
X				}
X				s++;
X			}
X			if (!matched)
X				return(0);
X			s--;
X			p--;
X			break;
X					/* match range of characters */
X		case '[':
X			first = '\0';
X			matched = 0;
X			reverse = 0;
X			while (*++p != ']') {
X				if (*p == '^') {
X					reverse = 1;
X					p++;
X				}
X				first = *p;
X				if (first == ']' || first == '\0') {
X					fprintf(stderr, "match: Malformed regular expression\n");
X					return(0);
X				}
X					/* if 2nd char is '-' */
X				if (*(p+1) == '-') {
X					p++;
X					/* set last to 3rd char ... */
X					last = *++p;
X					if (last == ']' || last == '\0') {
X						fprintf(stderr, "match: Malformed regular expression\n");
X						return(0);
X					}
X					/* test the range of values */
X					if (*s>=first && *s<=last) {
X						matched = 1;
X						p++;
X						break;
X					}
X					return(0);
X				}
X				if (*s == *p)
X					matched = 1;
X			}
X			if (matched && reverse)
X				return(0);
X			if (!matched)
X				return(0);
X			break;
X		}
X	}
X					/* string ended prematurely ? */
X	if (*s != '\0')
X		return(0);
X	else
X		return(1);
X}
END_OF_FILE
if test 1894 -ne `wc -c <'match.c'`; then
    echo shar: \"'match.c'\" unpacked with wrong size!
fi
# end of 'match.c'
fi
if test -f 'mcopy.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mcopy.c'\"
else
echo shar: Extracting \"'mcopy.c'\" \(2912 characters\)
sed "s/^X//" >'mcopy.c' <<'END_OF_FILE'
X/*
X * A front-end to the mread/mwrite commands.
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
X#define NONE	0
X#define MREAD	1
X#define MWRITE	2
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	extern int optind;
X	extern char *optarg;
X	int i, oops, msdos_args, unix_args, destination;
X	char **nargv, *strcpy();
X	void exit();
X					/* get command line options */
X	msdos_args = 0;
X	unix_args = 0;
X	oops = 0;
X	while ((i = getopt(argc, argv, "tnvm")) != EOF) {
X		switch(i) {
X			case 't':
X			case 'n':
X			case 'v':
X			case 'm':
X				break;
X			default:
X				oops = 1;
X				break;
X		}
X	}
X
X	if (oops || (argc - optind) < 2) {
X		fprintf(stderr, "Usage: mcopy [-tnvm] a:msdosfile unixfile\n");
X		fprintf(stderr, "       mcopy [-tnvm] a:msdosfile [a:msdosfiles...] unixdirectory\n");
X		fprintf(stderr, "       mcopy [-tnm] unixfile a:msdosfile\n");
X		fprintf(stderr, "       mcopy [-tnm] unixfile [unixfiles...] a:msdosdirectory\n");
X		exit(1);
X	}
X					/* what is the destination drive? */
X	destination = NONE;
X					/* first file */
X	if (argv[optind][1] == ':') {
X		if (argv[optind][0] == 'a' || argv[optind][0] == 'A')
X			destination = MREAD;
X	}
X					/* last file */
X	if (destination == NONE && argv[argc-1][1] == ':') {
X		if (argv[argc-1][0] == 'a' || argv[argc-1][0] == 'A')
X			destination = MWRITE;
X	}
X	if (destination == NONE) {
X		fprintf(stderr, "mcopy: no 'a:' designation specified\n");
X		exit(1);
X	}
X					/* strip out the fake "drive code" */
X	for (i=optind; i<argc; i++) {
X		if (argv[i][1] == ':') {
X			switch(argv[i][0]) {
X				case 'a':
X				case 'A':
X					if (argv[i][2] == '\0')
X						strcpy(argv[i], ".");
X					else
X						strcpy(argv[i], &argv[i][2]);
X					msdos_args++;
X					break;
X				case 'c':
X				case 'C':
X					fprintf(stderr, "mcopy: 'c:' is not used to designate Unix files\n");
X					exit(1);
X				default:
X					fprintf(stderr, "mcopy: unknown drive '%c:'\n", argv[i][0]);
X					exit(1);
X			}
X			continue;
X		}
X					/* if no drive code, its a unix file */
X		unix_args++;
X	}
X					/* sanity checking */
X	if (!msdos_args || !unix_args) {
X		fprintf(stderr, "mcopy: unresloved destination\n");
X		exit(1);
X	}
X	if ((destination == MWRITE && msdos_args > 1) || (destination == MREAD && unix_args > 1)) {
X		fprintf(stderr, "mcopy: duplicate destination files\n");
X		exit(1);
X	}
X	/*
X	 * Copy the *argv[] array in case your Unix doesn't end the array
X	 * with a null when it passes it to main()
X	 */
X	nargv = (char **) malloc((argc+1) * sizeof(*argv));
X	nargv[argc] = NULL;
X	for(;--argc>=0;)
X		nargv[argc] = argv[argc];
X
X	if (destination == MWRITE) {
X		nargv[0] = "mwrite";
X		execvp("mwrite", nargv);
X		perror("execvp: mwrite") ;
X	}
X	else {
X		nargv[0] = "mread";
X		execvp("mread", nargv);
X		perror("execvp: mmread") ;
X	}
X}
END_OF_FILE
if test 2912 -ne `wc -c <'mcopy.c'`; then
    echo shar: \"'mcopy.c'\" unpacked with wrong size!
fi
# end of 'mcopy.c'
fi
if test -f 'mdel.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mdel.c'\"
else
echo shar: Extracting \"'mdel.c'\" \(2881 characters\)
sed "s/^X//" >'mdel.c' <<'END_OF_FILE'
X/*
X * Delete 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
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int i, ismatch, entry, start, nogo, verbose, fargn;
X	char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
X	char *strncpy(), *getpath(), *pathname, ans[10];
X	void exit(), zapit(), writefat(), writedir(), free();
X	struct directory *dir, *search();
X
X	if (init(2)) {
X		fprintf(stderr, "mdel: Cannot initialize diskette\n");
X		exit(1);
X	}
X
X	if (argc < 2) {
X		fprintf(stderr, "Usage: mdel [-v] msdosfile [msdosfiles...]\n");
X		exit(1);
X	}
X	if (!strcmp(argv[1], "-v")) {
X		verbose = 1;
X		fargn = 2;
X	}
X	else {
X		verbose = 0;
X		fargn = 1;
X	}
X	for (i=fargn; 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		nogo = 0;
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					/* see it if matches the pattern */
X			if (match(newfile, filename)) {
X				if (verbose)
X					printf("Removing %s\n", newfile);
X				ismatch = 1;
X				if (dir->attr & 0x01) {
X					while (!nogo) {
X						printf("mdel: \"%s\" is read only, erase anyway (y/n) ? ", newfile);
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					if (nogo) {
X						free(newfile);
X						continue;
X					}
X				}
X				start = dir->start[1]*0x100 + dir->start[0];
X				zapit(start);
X				dir->name[0] = 0xe5;
X				writedir(entry, dir);
X			}
X			free(newfile);
X		}
X		if (!ismatch)
X			fprintf(stderr, "mdel: File \"%s\" not found\n", filename);
X		free(filename);
X		free(pathname);
X	}
X					/* update the FAT sectors */
X	writefat();
X	close(fd);
X	exit(0);
X}
END_OF_FILE
if test 2881 -ne `wc -c <'mdel.c'`; then
    echo shar: \"'mdel.c'\" unpacked with wrong size!
fi
# end of 'mdel.c'
fi
if test -f 'mkentry.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mkentry.c'\"
else
echo shar: Extracting \"'mkentry.c'\" \(2539 characters\)
sed "s/^X//" >'mkentry.c' <<'END_OF_FILE'
X/*
X * mk_entry(), grow()
X */
X
X#include <stdio.h>
X#include <time.h>
X#include "msdos.h"
X
Xextern int fd, dir_start, dir_len, clus_size, dir_entries;
Xextern int dir_chain[25];
X
X/*
X * Make a directory entry.  Builds a directory entry based on the
X * name, attribute, starting cluster number, and size.  Returns a pointer
X * to the static directory structure.
X */
X
Xstruct directory *
Xmk_entry(filename, attr, fat, size, date)
Xchar *filename;
Xunsigned char attr;
Xint fat;
Xlong size, date;
X{
X	int i;
X	char *strncpy();
X	static struct directory ndir;
X	struct tm *now, *localtime();
X	unsigned char hour, min_hi, min_low, sec;
X	unsigned char year, month_hi, month_low, day;
X
X	now = localtime(&date);
X	strncpy((char *) ndir.name, filename, 8);
X	strncpy((char *) ndir.ext, filename+8, 3);
X	ndir.attr = attr;
X	for (i=0; i<10; i++)
X		ndir.reserved[i] = '\0';
X	hour = now->tm_hour << 3;
X	min_hi = now->tm_min >> 3;
X	min_low = now->tm_min << 5;
X	sec = now->tm_sec / 2;
X	ndir.time[1] = hour + min_hi;
X	ndir.time[0] = min_low + sec;
X	year = (now->tm_year - 80) << 1;
X	month_hi = (now->tm_mon+1) >> 3;
X	month_low = (now->tm_mon+1) << 5;
X	day = now->tm_mday;
X	ndir.date[1] = year + month_hi;
X	ndir.date[0] = month_low + day;
X	ndir.start[1] = fat / 0x100;
X	ndir.start[0] = fat % 0x100;
X	ndir.size[3] = 0;		/* can't be THAT large */
X	ndir.size[2] = size / 0x10000L;
X	ndir.size[1] = (size % 0x10000L) / 0x100;
X	ndir.size[0] = (size % 0x10000L) % 0x100;
X	return(&ndir);
X}
X
X/*
X * Make a subdirectory grow in length.  Only subdirectories (not root) 
X * may grow.  Returns a 0 on success or 1 on failure (disk full).
X */
X
Xint
Xgrow(fat)
Xint fat;
X{
X	int i, next, last, num, sector, buflen;
X	unsigned char tbuf[CLSTRBUF];
X	void perror(), exit(), move();
X
X	last = nextfat(0);
X	if (last == -1)
X		return(1);
X
X	while (1) {
X		next = getfat(fat);
X		if (next == -1) {
X			fprintf(stderr, "grow: FAT problem\n");
X			exit(1);
X		}
X					/* end of cluster chain */
X		if (next >= 0xff8)
X			break;
X		fat = next;
X	}
X					/* mark the end of the chain */
X	putfat(fat, (unsigned int) last);
X	putfat(last, 0xfff);
X					/* zero the buffer */
X	buflen = clus_size * MSECSIZ;
X	for (i=0; i<buflen; i++)
X		tbuf[i] = '\0';
X
X					/* write the cluster */
X	sector = (last - 2) * clus_size + dir_start + dir_len;
X	move(sector);
X	if (write(fd, (char *) tbuf, buflen) != buflen) {
X		perror("grow: write");
X		exit(1);
X	}
X					/* fix up the globals.... */
X	num = dir_entries / 16;
X	dir_entries += clus_size * 16;
X	dir_chain[num] = sector;
X	if (clus_size == 2)
X		dir_chain[num+1] = sector +1;
X	return(0);
X}
END_OF_FILE
if test 2539 -ne `wc -c <'mkentry.c'`; then
    echo shar: \"'mkentry.c'\" unpacked with wrong size!
fi
# end of 'mkentry.c'
fi
if test -f 'msdos.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'msdos.h'\"
else
echo shar: Extracting \"'msdos.h'\" \(2113 characters\)
sed "s/^X//" >'msdos.h' <<'END_OF_FILE'
X/*
X * msdos common header file
X */
X
X#define MSECSIZ	512			/* sector size */
X#define MDIRSIZ	32			/* directory size */
X#define CLSTRBUF 1024			/* largest cluster size */
X#define MAX_PATH 128
X
Xstruct directory {
X	unsigned char	name[8];	/* file name */
X	unsigned char	ext[3];		/* file extent */
X	unsigned char	attr;		/* attribute byte */
X	unsigned char	reserved[10];	/* ?? */
X	unsigned char	time[2];		
X	unsigned char	date[2];
X	unsigned char	start[2];	/* starting cluster number */
X	unsigned char	size[4];	/* size of the file */
X};
X
Xstruct dos_word {
X  unsigned char dw_low ;		/* LSB */
X  unsigned char dw_high ;		/* MSB */
X} ;
X
Xstruct superblock {
X  unsigned char jump[3] ;       /* Jump to boot code */
X  unsigned char banner[8];      /* OEM name & version */
X  struct dos_word secsiz;       /* Bytes per sector hopefully 512 */
X  unsigned char clsiz ;         /* Cluster size in sectors */
X  struct dos_word nrsvsect;     /* Number of reserved (boot) sectors */
X  unsigned char nfat;           /* Number of FAT tables hopefully 2 */
X  struct dos_word dirents;      /* Number of directory slots */
X  struct dos_word psect;        /* Total sectors on disk */
X  unsigned char descr;          /* Media descriptor=first byte of FAT */
X  struct dos_word fatlen;       /* Sectors in FAT */
X  struct dos_word nsect;        /* Sectors/track */
X  struct dos_word ntrack;       /* tracks/cyl */
X  struct dos_word nhs;          /* number of hidden sectors ? */
X} ;
X
Xunion bootblock {
X  char dummy[MSECSIZ] ;
X  struct superblock sb ;
X} ;
X
X#define WORD_VAL(x) (x.dw_low + (x.dw_high <<8))
X
X#define SECSIZ(x)	WORD_VAL(x.secsiz)
X#define CLSIZ(x)	(x.clsiz)
X#define FSSIZ(x)	WORD_VAL(x.psect)
X#define DIRENTS(x)	WORD_VAL(x.dirents)
X#define FATLEN(x)	WORD_VAL(x.fatlen)
X#define DIRLEN(x)	((DIRENTS(x)*MDIRSIZ-1)/MSECSIZ+1)
X#define FATOFF(x)	WORD_VAL(x.nrsvsect)
X#define DIROFF(x)	(FATOFF(x)+FATLEN(x)*x.nfat)
X#define NCLUST(x)	(FSSIZ(x)-DIROFF(x)-DIRLEN(x)-WORD_VAL(x.nhs))/CLSIZ(x)
X#define NSECT(x)	WORD_VAL(x.nsect)
X#define NTRACK(x)	WORD_VAL(x.ntrack)
X#define NCYL(x)		(FSSIZ(x)/(NTRACK(x)*NSECT(x)))
X#define FATCODE(x)	(x.descr)
END_OF_FILE
if test 2113 -ne `wc -c <'msdos.h'`; then
    echo shar: \"'msdos.h'\" unpacked with wrong size!
fi
# end of 'msdos.h'
fi
if test -f 'putfat.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'putfat.c'\"
else
echo shar: Extracting \"'putfat.c'\" \(2561 characters\)
sed "s/^X//" >'putfat.c' <<'END_OF_FILE'
X/*
X * putfat(), writedir(), zapit()
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xextern int fd, fat_len, dir_chain[25];
Xextern unsigned char *fatbuf;
X
X/*
X * Puts a code into the FAT table.  Is the opposite of getfat().  No
X * sanity checking is done on the code.  Returns a 1 on error.
X */
X
Xint
Xputfat(num, code)
Xint num;
Xunsigned int code;
X{
X/*
X *	|    byte n     |   byte n+1    |   byte n+2    |
X *	|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
X *	| | | | | | | | | | | | | | | | | | | | | | | | |
X *	|  n.0  |  n.5  | n+1.0 | n+1.5 | n+2.0 | n+2.5 |
X *	    \_____  \____   \______/________/_____   /
X *	      ____\______\________/   _____/  ____\_/
X *	     /     \      \          /       /     \
X *	| n+1.5 |  n.0  |  n.5  | n+2.0 | n+2.5 | n+1.0 |
X *	|      FAT entry k      |    FAT entry k+1      |
X */
X	int start;
X					/* which bytes contain the entry */
X	start = num * 3 / 2;
X	if (start < 0 || start+1 > (fat_len * MSECSIZ))
X		return(1);
X					/* (odd) not on byte boundary */
X	if (num % 2) {
X		*(fatbuf+start) = (*(fatbuf+start) & 0x0f) + ((code << 4) & 0xf0);
X		*(fatbuf+start+1) = (code >> 4) & 0xff;
X	}
X					/* (even) on byte boundary */
X	else {
X		*(fatbuf+start) = code & 0xff;
X		*(fatbuf+start+1) = (*(fatbuf+start+1) & 0xf0) + ((code >> 8) & 0x0f);
X	}
X	return(0);
X}
X
X/*
X * Write a directory entry.  The first argument is the directory entry
X * number to write to.  The second is a pointer to the directory itself.
X * All errors are fatal.
X */
X
Xvoid
Xwritedir(num, dir)
Xint num;
Xstruct directory *dir;
X{
X	int skip, entry;
X	struct directory dirs[16];
X	void exit(), perror(), move();
X					/* which sector */
X	skip = dir_chain[num / 16];
X
X	move(skip);
X					/* read the sector */
X	if (read(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) {
X		perror("writedir: read");
X		exit(1);
X	}
X					/* which entry in sector */
X	entry = num % 16;
X					/* copy the structure */
X	dirs[entry] = *dir;
X	move(skip);
X					/* write the sector */
X	if (write(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) {
X		perror("writedir: write");
X		exit(1);
X	}
X	return;
X}
X
X/*
X * Remove a string of FAT entries (delete the file).  The argument is
X * the beginning of the string.  Does not consider the file length, so
X * if FAT is corrupted, watch out!  All errors are fatal.
X */
X
Xvoid
Xzapit(fat)
Xint fat;
X{
X	int next;
X
X	while (1) {
X					/* get next cluster number */
X		next = getfat(fat);
X					/* mark current cluster as empty */
X		if (putfat(fat, 0) || next == -1) {
X			fprintf(stderr, "zapit: FAT problem\n");
X			exit(1);
X		}
X		if (next >= 0xff8)
X			break;
X		fat = next;
X	}
X	return;
X}
END_OF_FILE
if test 2561 -ne `wc -c <'putfat.c'`; then
    echo shar: \"'putfat.c'\" unpacked with wrong size!
fi
# end of 'putfat.c'
fi
if test -f 'search.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'search.c'\"
else
echo shar: Extracting \"'search.c'\" \(1083 characters\)
sed "s/^X//" >'search.c' <<'END_OF_FILE'
X/*
X * Search and extract a directory structure.  The argument is the
X * relative directory entry number (no sanity checking).  It returns a
X * pointer to the directory structure at that location.  Attempts to
X * optimize by trying to determine if the buffer needs to be re-read.
X * A call to writedir() will scribble on the real buffer, so watch out!
X */
X
X#include <stdio.h>
X#include "msdos.h"
X				/* dir_chain contains the list of sectors */
X				/* that make up the current directory */
Xextern int fd, dir_chain[25];
X
Xstruct directory *
Xsearch(num)
Xint num;
X{
X	int skip, entry;
X	static int last;
X	static struct directory dirs[16];
X	void exit(), perror(), move();
X
X					/* first call disables optimzation */
X	if (num == 0)
X		last = 0;
X					/* which sector */
X	skip = dir_chain[num / 16];
X					/* don't read it if same sector */
X	if (skip != last) {
X		move(skip);
X					/* read the sector */
X		if (read(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) {
X			perror("mread: read");
X			exit(1);
X		}
X	}
X	last = skip;
X					/* which entry in sector */
X	entry = num % 16;
X	return(&dirs[entry]);
X}
END_OF_FILE
if test 1083 -ne `wc -c <'search.c'`; then
    echo shar: \"'search.c'\" unpacked with wrong size!
fi
# end of 'search.c'
fi
if test -f 'unixname.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'unixname.c'\"
else
echo shar: Extracting \"'unixname.c'\" \(2215 characters\)
sed "s/^X//" >'unixname.c' <<'END_OF_FILE'
X/*
X * unixname(), getname(), getpath()
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include "msdos.h"
X
X/*
X * Get rid of spaces in a MSDOS 'raw' name (one that has come from the
X * directory structure) so that it can be used for regular expression
X * matching with a unix file name.  Also used to 'unfix' a name that has
X * been altered by fixname().  Returns a pointer to the unix style name.
X */
X
Xchar *
Xunixname(name, ext)
Xchar *name, *ext;
X{
X	char *s, tname[9], text[4], *strcpy(), *strcat(), *strchr();
X	char *ans, *malloc();
X
X	strcpy(tname, name);
X	if (s = strchr(tname, ' '))
X		*s = '\0';
X
X	strcpy(text, ext);
X	if (s = strchr(text, ' '))
X		*s = '\0';
X
X	ans = malloc(13);
X
X	if (*text) {
X		strcpy(ans, tname);
X		strcat(ans, ".");
X		strcat(ans, text);
X	}
X	else
X		strcpy(ans, tname);
X	return(ans);
X}
X
X/*
X * Get name component of filename.  Translates name to upper case.  Returns
X * pointer to new name.
X */
X
Xchar *
Xgetname(filename)
Xchar *filename;
X{
X	char *s, *ans, *malloc(), *temp, *strcpy(), *strrchr();
X	char buf[MAX_PATH];
X
X	strcpy(buf, filename);
X	temp = buf;
X					/* find the last separator */
X	if (s = strrchr(temp, '/'))
X		temp = s+1;
X	if (s = strrchr(temp, '\\'))
X		temp = s+1;
X					/* xlate to upper case */
X	for (s = temp; *s; ++s) {
X		if (islower(*s))
X			*s = toupper(*s);
X	}
X
X	ans = malloc((unsigned int) strlen(temp)+1);
X	strcpy(ans, temp);
X	return(ans);
X}
X
X/*
X * Get the path component of the filename.  Translates to upper case.
X * Returns pointer to path.  Doesn't alter leading separator, always
X * strips trailing separator (unless it is the path itself).
X */
X
Xchar *
Xgetpath(filename)
Xchar *filename;
X{
X	char *s, *temp, *ans, *malloc(), *strcpy(), *strrchr();
X	char buf[MAX_PATH];
X	int has_sep;
X
X	strcpy(buf, filename);
X	temp = buf;
X					/* find last separator */
X	has_sep = 0;
X	if (s = strrchr(temp, '/')) {
X		has_sep++;
X		temp = s;
X	}
X	if (s = strrchr(temp, '\\')) {
X		has_sep++;
X		temp = s;
X	}
X
X	*temp = '\0';
X					/* translate to upper case */
X	for (s = buf; *s; ++s) {
X		if (islower(*s))
X			*s = toupper(*s);
X	}
X					/* if separator alone, put it back */
X	if (!strlen(buf) && has_sep)
X		strcpy(buf, "/");
X
X	ans = malloc((unsigned int) strlen(buf)+1);
X	strcpy(ans, buf);
X	return(ans);
X}
END_OF_FILE
if test 2215 -ne `wc -c <'unixname.c'`; then
    echo shar: \"'unixname.c'\" unpacked with wrong size!
fi
# end of 'unixname.c'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
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


