[comp.sys.att] Mtools

egray@fthood.UUCP (08/06/87)

				MTOOLS v1.2

This is a collection of MSDOS tools to allow you to read and write to
MSDOS formatted diskettes from your AT&T Unix PC 7300.  These commands
are intended to replace the 'md_write' and 'msdos' commands that run 
under the User Agent.

Mtools offers a significant advantage over the programs supplied with
your PC 7300.  For example, you can copy several files (or and entire
diskette) with a single command, rather than the UA way of high lighting
and clicking each file one at a time.  The tools closely emulate MSDOS
so that you don't have to learn another command interpreter... you can
just close your eyes, pretend you're on a MSDOS machine, and everything
will work as you'd expect.

The following MSDOS commands are emulated:

Mtool 		MSDOS
name		equivalent	Description
-----		----		-----------
mdel		DEL/ERASE	delete a MSDOS file
mdir		DIR		display a MSDOS directory
mmd		MD/MKDIR	make a MSDOS sub directory
mrd		RD/RMDIR	remove a MSDOS sub directory
mread		COPY		read (copy) a MSDOS file to Unix
mren		REN/RENAME	rename an existing MSDOS file
mtype		TYPE		display contents of a MSDOS file
mwrite		COPY		write (copy) a Unix file to MSDOS
*		CD		change working directory

	* by use of an environmental variable

Emmet P. Gray				US Army, HQ III Corps & Fort Hood
...!ihnp4!uiucuxc!fthood!egray		Attn: AFZF-DE-ENV
					Directorate of Engineering & Housing
					Environmental Management Office
					Fort Hood, TX 76544-5057

----------------------------------------------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	Readme
#	Makefile
#	Mdel.1
#	Mdir.1
#	Mmd.1
#	Mrd.1
#	Mread.1
#	Mren.1
#	Mtype.1
#	Mwrite.1
#	mklower.sh
#	msdos.h
#	convdate.c
#	fixname.c
#	getfat.c
#	init.c
#	isdir.c
#	match.c
#	mdel.c
#	mdir.c
# This archive created: Thu Aug  6 07:45:29 1987
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'Readme'" '(3301 characters)'
if test -f 'Readme'
then
	echo shar: "will not over-write existing file 'Readme'"
else
sed 's/^X//' << \SHAR_EOF > 'Readme'
X				MTOOLS v1.2
X
XThis is a collection of MSDOS tools to allow you to read and write to
XMSDOS formatted diskettes from an AT&T Unix PC 7300.
X
XThe following MSDOS commands are emulated:
X
XMtool 		MSDOS
Xname		equivalent	Description
X-----		----		-----------
Xmdel		DEL/ERASE	delete a MSDOS file
Xmdir		DIR		display a MSDOS directory
Xmmd		MD/MKDIR	make a MSDOS sub directory
Xmrd		RD/RMDIR	remove a MSDOS sub directory
Xmread		COPY		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		write (copy) a Unix file to MSDOS
X*		CD		change working directory
X
X	* by use of the environmental variable MCWD
X
XThe standard format of the floppy disk drive associated with the device
X/dev/rfp020 is:
X
X	512 bytes / sector		512 x 8 x 40 x 2 = 320k
X	8 sectors / track
X	40 tracks / side
X	2 sides
X
XHowever, the formats of 5.25 inch 40 track IBM PC 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
XThe application software has the ability to detect the type of media and
Xto switch to the proper format as appropriate.
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 first set their working directory, ie:
X
X	MCWD=/TMP
X	export MCWD
X
XWildcards are only applied to filenames and not to directory names.
XFor example '/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
Xwhen transferring 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).  Likewise,
Xif you forget to apply the text mode (to a Unix text file) then if the
Xfile is used under MSDOS, it will be missing carriage returns.  However,
Xif you aren't going to use the files on your Unix system (you just
Xintend to hold the files and then transfer them back to MSDOS later) then
Xyou shouldn't use the text mode during either mread or mwrite.  This is
Xbecause, the text mode is only useful if the files are gonna be used
Xunder Unix.
X
XMwrite adds an EOF marker to every file (not just text files).  Mread
Xignores all EOF markers.
X
XThe MSDOS 'copy' command had to be broken down into two separate Unix
Xcommands since the MSDOS device designations (A: or C:) would be
Xclumsy to implement.
X
XMtools is also available in a 'generic' version and in a version written
Xespecially for Masscomp computers.
X
XEmmet P. Gray				US Army, HQ III Corps & Fort Hood
X...!ihnp4!uiucuxc!fthood!egray		Attn: AFZF-DE-ENV
X					Directorate of Engineering & Housing
X					Environmental Management Office
X					Fort Hood, TX 76544-5057
SHAR_EOF
if test 3301 -ne "`wc -c < 'Readme'`"
then
	echo shar: "error transmitting 'Readme'" '(should have been 3301 characters)'
fi
fi
echo shar: "extracting 'Makefile'" '(3068 characters)'
if test -f 'Makefile'
then
	echo shar: "will not over-write existing file 'Makefile'"
else
sed 's/^X//' << \SHAR_EOF > 'Makefile'
X#
X#       Makefile for MSDOS tools
X#
X
Xinclude $(MAKEINC)/Makepre.h
XCC = cc
XCFLAGS = -O
XLINT = lint -x
XSHAR = shar -a
XBINDIR = /usr/local/bin
XPROGS = mdir mread mwrite mdel mtype mmd mrd mren
X
XMDIR = mdir.o getfat.o init.o search.o match.o convdate.o unixname.o subdir.o \
X	isdir.o
XMREAD = mread.o getfat.o init.o search.o match.o unixname.o subdir.o
XMWRITE = mwrite.o getfat.o init.o search.o fixname.o unixname.o putfat.o \
X	subdir.o mkentry.o isdir.o
XMDEL = mdel.o getfat.o init.o search.o match.o unixname.o putfat.o subdir.o
XMTYPE = mtype.o getfat.o init.o search.o match.o unixname.o subdir.o
XMMD = mmd.o getfat.o init.o search.o fixname.o unixname.o putfat.o subdir.o \
X	mkentry.o
XMRD = mrd.o getfat.o init.o search.o unixname.o putfat.o subdir.o
XMREN = mren.o getfat.o init.o search.o fixname.o unixname.o putfat.o subdir.o \
X	isdir.o
X
Xall:	$(PROGS)
X
Xmdir:	$(MDIR)
X	$(LD) $(LDFLAGS) $(SHAREDLIB) $(MDIR) -o mdir
X
Xmread:	$(MREAD)
X	$(LD) $(LDFLAGS) $(SHAREDLIB) $(MREAD) -o mread
X
Xmwrite:	$(MWRITE)
X	$(LD) $(LDFLAGS) $(SHAREDLIB) $(MWRITE) -o mwrite
X
Xmdel:	$(MDEL)
X	$(LD) $(LDFLAGS) $(SHAREDLIB) $(MDEL) -o mdel
X
Xmtype:	$(MTYPE)
X	$(LD) $(LDFLAGS) $(SHAREDLIB) $(MTYPE) -o mtype
X
Xmmd:	$(MMD)
X	$(LD) $(LDFLAGS) $(SHAREDLIB) $(MMD) -o mmd
X
Xmrd:	$(MRD)
X	$(LD) $(LDFLAGS) $(SHAREDLIB) $(MRD) -o mrd
X
Xmren:	$(MREN)
X	$(LD) $(LDFLAGS) $(SHAREDLIB) $(MREN) -o mren
X
Xinstall: $(PROGS)
X	cp mdir $(BINDIR)/mdir
X	strip $(BINDIR)/mdir
X	rm mdir
X#	cp Mdir.1 /usr/man/man1/mdir.1
X	cp mread $(BINDIR)/mread
X	strip $(BINDIR)/mread
X	rm mread
X#	cp Mread.1 /usr/man/man1/mread.1
X	cp mwrite $(BINDIR)/mwrite
X	strip $(BINDIR)/mwrite
X	rm mwrite
X#	cp Mwrite.1 /usr/man/man1/mwrite.1
X	cp mdel $(BINDIR)/mdel
X	strip $(BINDIR)/mdel
X	rm mdel
X#	cp Mdel.1 /usr/man/man1/mdel.1
X	cp mtype $(BINDIR)/mtype
X	strip $(BINDIR)/mtype
X	rm mtype
X#	cp Mtype.1 /usr/man/man1/mtype.1
X	cp mmd $(BINDIR)/mmd
X	strip $(BINDIR)/mmd
X	rm mmd
X#	cp Mmd.1 /usr/man/man1/mmd.1
X	cp mrd $(BINDIR)/mrd
X	strip $(BINDIR)/mrd
X	rm mrd
X#	cp Mrd.1 /usr/man/man1/mrd.1
X	cp mren $(BINDIR)/mren
X	strip $(BINDIR)/mren
X	rm mren
X#	cp Mren.1 /usr/man/man1/mren.1
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
Xshar:
X	$(SHAR) Readme Makefile Mdel.1 Mdir.1 Mmd.1 Mrd.1 Mread.1 Mren.1 \
X	Mtype.1 Mwrite.1 mklower.sh msdos.h convdate.c fixname.c getfat.c \
X	init.c isdir.c match.c mdel.c mdir.c > mtools1
X	$(SHAR) mkentry.c mmd.c mrd.c mread.c mren.c mtype.c mwrite.c \
X	putfat.c search.c subdir.c unixname.c > mtools2
SHAR_EOF
if test 3068 -ne "`wc -c < 'Makefile'`"
then
	echo shar: "error transmitting 'Makefile'" '(should have been 3068 characters)'
fi
fi
echo shar: "extracting 'Mdel.1'" '(738 characters)'
if test -f 'Mdel.1'
then
	echo shar: "will not over-write existing file 'Mdel.1'"
else
sed 's/^X//' << \SHAR_EOF > 'Mdel.1'
X.TH MDEL 1 local
X.SH NAME
Xmdel \- delete a MSDOS file
X.SH SYNOPSIS
X.B mdel msdosfile
X[
X.B msdosfiles...
X]
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 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
XDoes not follow the MSDOS convention of allowing only one file argument.
XWildcards are only applied to filenames, not to directory names.
SHAR_EOF
if test 738 -ne "`wc -c < 'Mdel.1'`"
then
	echo shar: "error transmitting 'Mdel.1'" '(should have been 738 characters)'
fi
fi
echo shar: "extracting 'Mdir.1'" '(992 characters)'
if test -f 'Mdir.1'
then
	echo shar: "will not over-write existing file 'Mdir.1'"
else
sed 's/^X//' << \SHAR_EOF > 'Mdir.1'
X.TH MDIR 1 local
X.SH NAME
Xmdir \- display a MSDOS directory
X.SH SYNOPSIS
X.B mdir
X[
X.B -w
X]
X.B msdosdirectory
X.PP
X.B mdir
X[
X.B -w
X]
X.B  msdosfile
X[
X.B msdosfiles...
X] 
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 in
Xquotes to protect them from the shell.
X.PP
X.I Mdir
Xwill accept the following command line option:
X.TP
X.B w
XWide output.  This option will print the file names across the page without
Xdisplaying 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
XDoes not follow the MSDOS convention of allowing only one directory
Xargument.  Wildcards are only applied to filenames, not to directory names.
SHAR_EOF
if test 992 -ne "`wc -c < 'Mdir.1'`"
then
	echo shar: "error transmitting 'Mdir.1'" '(should have been 992 characters)'
fi
fi
echo shar: "extracting 'Mmd.1'" '(723 characters)'
if test -f 'Mmd.1'
then
	echo shar: "will not over-write existing file 'Mmd.1'"
else
sed 's/^X//' << \SHAR_EOF > 'Mmd.1'
X.TH MMD 1 local
X.SH NAME
Xmmd \- make a MSDOS sub directory
X.SH SYNOPSIS
X.B mmd msdosdirectory
X.SH DESCRIPTION
X.I Mmd
Xmakes a new directory on a MSDOS formatted diskette.  Sub directories are
Xsupported with either the '/' or '\e\' separator.  The use of
Xthe '\e\' separator will require the directory name to be enclosed in quotes
Xto protect it from the shell.
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. 
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)
SHAR_EOF
if test 723 -ne "`wc -c < 'Mmd.1'`"
then
	echo shar: "error transmitting 'Mmd.1'" '(should have been 723 characters)'
fi
fi
echo shar: "extracting 'Mrd.1'" '(598 characters)'
if test -f 'Mrd.1'
then
	echo shar: "will not over-write existing file 'Mrd.1'"
else
sed 's/^X//' << \SHAR_EOF > 'Mrd.1'
X.TH MRD 1 local
X.SH NAME
Xmrd \- remove a MSDOS sub directory
X.SH SYNOPSIS
X.B mrd msdosdirectory
X.SH DESCRIPTION
X.I Mrd
Xremoves a directory from a MSDOS formatted diskette.  Sub directories are
Xsupported with either the '/' or '\e\' separator.  The use of
Xthe '\e\' separator will require the directory name to be enclosed in quotes
Xto 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)
SHAR_EOF
if test 598 -ne "`wc -c < 'Mrd.1'`"
then
	echo shar: "error transmitting 'Mrd.1'" '(should have been 598 characters)'
fi
fi
echo shar: "extracting 'Mread.1'" '(1226 characters)'
if test -f 'Mread.1'
then
	echo shar: "will not over-write existing file 'Mread.1'"
else
sed 's/^X//' << \SHAR_EOF > 'Mread.1'
X.TH MREAD 1 local
X.SH NAME
Xmread \- read (copy) a MSDOS file to Unix
X.SH SYNOPSIS
X.B mread
X[
X.B -t
X|
X.B -n
X]
X.B msdosfile unixfile
X.PP
X.B mread
X[
X.B -t
X|
X.B -n
X]
X.B  msdosfile
X[
X.B msdosfiles...
X]
X.B 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\' separator.
XThe use of the '\e\' separator or wildcards will require the names to be
Xenclosed in quotes to protect them from the shell.
X.PP
X.I Mread
Xwill accept 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.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
Xmdir(1), mtype(1), mwrite(1)
X.SH BUGS
XWildcards are only applied to filenames, not to directory names.
SHAR_EOF
if test 1226 -ne "`wc -c < 'Mread.1'`"
then
	echo shar: "error transmitting 'Mread.1'" '(should have been 1226 characters)'
fi
fi
echo shar: "extracting 'Mren.1'" '(1012 characters)'
if test -f 'Mren.1'
then
	echo shar: "will not over-write existing file 'Mren.1'"
else
sed 's/^X//' << \SHAR_EOF > 'Mren.1'
X.TH MREN 1 local
X.SH NAME
Xmren \- rename an existing MSDOS file
X.SH SYNOPSIS
X.B mren sourcefile targetfile
X.SH DESCRIPTION
X.I Mren
Xrenames an existing file on a MSDOS formatted diskette.  Sub directories are
Xsupported with either the '/' or '\e\' separator.  The use of the '\e\'
Xseparator or wildcards will require the names to be enclosed in quotes to
Xprotect them from the shell.
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.
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.
SHAR_EOF
if test 1012 -ne "`wc -c < 'Mren.1'`"
then
	echo shar: "error transmitting 'Mren.1'" '(should have been 1012 characters)'
fi
fi
echo shar: "extracting 'Mtype.1'" '(994 characters)'
if test -f 'Mtype.1'
then
	echo shar: "will not over-write existing file 'Mtype.1'"
else
sed 's/^X//' << \SHAR_EOF > 'Mtype.1'
X.TH MTYPE 1 local
X.SH NAME
Xmtype \- display contents of a MSDOS file
X.SH SYNOPSIS
X.B mtype
X[
X.B -t
X|
X.B -s
X]
X.B msdosfile
X[
X.B msdosfiles...
X]
X.SH DESCRIPTION
X.I Mtype
Xdisplays the specified MSDOS file on the screen.  MSDOS sub directories are
Xsupported with either the '/' or '\e\' separator.  The use of the '\e\'
Xseparator or wildcards will require the names to be enclosed in quotes to
Xprotect them from the shell.
X.PP
X.I Mtype
Xwill accept 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
XDoes not follow the MSDOS convention of allowing only one file
Xargument.  Wildcards are only applied to filenames, not to directory names.
SHAR_EOF
if test 994 -ne "`wc -c < 'Mtype.1'`"
then
	echo shar: "error transmitting 'Mtype.1'" '(should have been 994 characters)'
fi
fi
echo shar: "extracting 'Mwrite.1'" '(1368 characters)'
if test -f 'Mwrite.1'
then
	echo shar: "will not over-write existing file 'Mwrite.1'"
else
sed 's/^X//' << \SHAR_EOF > 'Mwrite.1'
X.TH MWRITE 1 local
X.SH NAME
Xmwrite \- write (copy) a Unix file to MSDOS
X.SH SYNOPSIS
X.B mwrite
X[
X.B -t
X|
X.B -n
X]
X.B unixfile msdosfile
X.PP
X.B mwrite
X[
X.B -t
X|
X.B -n
X]
X.B unixfile
X[
X.B unixfiles...
X]
X.B 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\' separator.
XThe use of the '\e\' separator will require the names to be enclosed in
Xquotes to protect them from the shell.
X.PP
X.I Mwrite
Xwill accept 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.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 invalid
Xname is specified,
X.I mwrite
Xwill change the name and display the new name.
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
XWildcards are only applied to filenames, not to directory names.
SHAR_EOF
if test 1368 -ne "`wc -c < 'Mwrite.1'`"
then
	echo shar: "error transmitting 'Mwrite.1'" '(should have been 1368 characters)'
fi
fi
echo shar: "extracting 'mklower.sh'" '(295 characters)'
if test -f 'mklower.sh'
then
	echo shar: "will not over-write existing file 'mklower.sh'"
else
sed 's/^X//' << \SHAR_EOF > 'mklower.sh'
Xfor file in $*
Xdo
X	newfile=`echo $file | tr '[A-Z]' '[a-z]'`
X	if [ $file != $newfile ] ;then
X		if [ -r $newfile ] ;then
X			echo $newfile "already exists, overwrite [yN] : \c"
X			read ans
X			if [ "$ans" != "y" ] ;then
X				continue
X			fi
X		fi
X		echo mv $file $newfile
X		mv $file $newfile
X	fi
Xdone
SHAR_EOF
if test 295 -ne "`wc -c < 'mklower.sh'`"
then
	echo shar: "error transmitting 'mklower.sh'" '(should have been 295 characters)'
fi
fi
echo shar: "extracting 'msdos.h'" '(536 characters)'
if test -f 'msdos.h'
then
	echo shar: "will not over-write existing file 'msdos.h'"
else
sed 's/^X//' << \SHAR_EOF > 'msdos.h'
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	FLOPPY	"/dev/rfp020"
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};
SHAR_EOF
if test 536 -ne "`wc -c < 'msdos.h'`"
then
	echo shar: "error transmitting 'msdos.h'" '(should have been 536 characters)'
fi
fi
echo shar: "extracting 'convdate.c'" '(1314 characters)'
if test -f 'convdate.c'
then
	echo shar: "will not over-write existing file 'convdate.c'"
else
sed 's/^X//' << \SHAR_EOF > 'convdate.c'
X/*
X * convdate(), convtime()
X */
X
X/*
X * convert MSDOS directory datestamp to ASCII
X */
X
Xchar *
Xconvdate(date_high, date_low)
Xunsigned date_high;
Xunsigned date_low;
X{
X/*
X *	    hi byte     |    low byte
X *	|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
X *      | | | | | | | | | | | | | | | | |
X *      \   7 bits    /\4 bits/\ 5 bits /
X *         year +80      month     day
X */
X	static char buffer[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(buffer, "%2d-%02d-%02d", month_hi+month_low, day, year);
X	return(buffer);
X}
X
X/*
X * Convert MSDOS directory timestamp to ASCII
X */
X
Xchar *
Xconvtime(time_high, time_low)
Xunsigned time_high;
Xunsigned time_low;
X{
X/*
X *	    hi byte     |    low byte
X *	|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
X *      | | | | | | | | | | | | | | | | |
X *      \  5 bits /\  6 bits  /\ 5 bits /
X *         hour      minutes     sec*2
X */
X	static char buffer[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(buffer, "%2d:%02d%c", hour, min_hi+min_low, am_pm);
X	return(buffer);
X}
SHAR_EOF
if test 1314 -ne "`wc -c < 'convdate.c'`"
then
	echo shar: "error transmitting 'convdate.c'" '(should have been 1314 characters)'
fi
fi
echo shar: "extracting 'fixname.c'" '(1654 characters)'
if test -f 'fixname.c'
then
	echo shar: "will not over-write existing file 'fixname.c'"
else
sed 's/^X//' << \SHAR_EOF > 'fixname.c'
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
Xchar *
Xfixname(name)
Xchar *name;
X{
X	static char *dev[8] = {"CON", "AUX", "COM1", "LPT1", "PRN", "LPT2",
X	"LPT3", "NUL"};
X	char *s, *temp, *ext, *malloc(), *strcpy(), *strpbrk(), *strrchr();
X	int i, dot, modified;
X	static char ans[12];
X
X	temp = malloc(strlen(name)+1);
X	strcpy(temp, name);
X					/* zap the leading path */
X	if (s = strrchr(temp, '/'))
X		temp = s+1;
X	if (s = strrchr(temp, '\\'))
X		temp = s+1;
X
X	ext = NULL;
X	dot = 0;
X	for (s = temp; *s; ++s) {
X		if (*s == '.' && !dot) {
X			dot = 1;
X			*s = NULL;
X			ext = s + 1;
X		}
X		if (islower(*s))
X			*s = toupper(*s);
X	}
X	if (*temp == NULL) {
X		temp = "X";
X		printf("'%s' Null name component, using '%s.%s'\n", name, temp, ext);
X	}
X	for (i=0; i<8; i++) {
X		if (!strcmp(temp, dev[i])) {
X			*temp = 'X';
X			printf("'%s' Is a device name, using '%s.%s'\n", name, temp, ext);
X		}
X	}
X	if (strlen(temp) > 8) {
X		*(temp+8) = NULL;
X		printf("'%s' Name too long, using, '%s.%s'\n", name, temp, ext);
X	}
X	if (strlen(ext) > 3) {
X		*(ext+3) = NULL;
X		printf("'%s' Extension too long, using '%s.%s'\n", name, temp, ext);
X	}
X	modified = 0;
X	while (s = strpbrk(temp, "^+=/[]:',?*\\<>|\". ")) {
X		modified++;
X		*s = 'X';
X	}
X	while (s = strpbrk(ext, "^+=/[]:',?*\\<>|\". ")) {
X		modified++;
X		*s = 'X';
X	}
X	if (modified)
X		printf("'%s' Contains illegal character\(s\), using '%s.%s'\n", name, temp, ext);
X	sprintf(ans, "%-8.8s%-3.3s", temp, ext);
X	return(ans);
X}
SHAR_EOF
if test 1654 -ne "`wc -c < 'fixname.c'`"
then
	echo shar: "error transmitting 'fixname.c'" '(should have been 1654 characters)'
fi
fi
echo shar: "extracting 'getfat.c'" '(1377 characters)'
if test -f 'getfat.c'
then
	echo shar: "will not over-write existing file 'getfat.c'"
else
sed 's/^X//' << \SHAR_EOF > 'getfat.c'
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;
X	static int 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}
SHAR_EOF
if test 1377 -ne "`wc -c < 'getfat.c'`"
then
	echo shar: "error transmitting 'getfat.c'" '(should have been 1377 characters)'
fi
fi
echo shar: "extracting 'init.c'" '(5066 characters)'
if test -f 'init.c'
then
	echo shar: "will not over-write existing file 'init.c'"
else
sed 's/^X//' << \SHAR_EOF > 'init.c'
X/*
X * Initialize a MSDOS diskette.  Get the media signature (1st FAT
X * entry) and alter the floppy disk controller via 'gdisk' ioctl calls
X * to match the format of the disk.  Sets a bunch of global variables.
X * Returns 0 on success, or 1 on failure.
X */
X
X#include <stdio.h>
X#include <sys/gdioctl.h>
X#include <ctype.h>
X#include "msdos.h"
X
Xextern int fd, dir_len, dir_start, clus_size, fat_len, num_clus;
Xextern unsigned char *fatbuf;
Xextern char *mcwd;
X
Xint
Xinit(mode)
Xint mode;
X{
X	int code = 0, buflen;
X	unsigned char read_fat(), fat;
X	char *getenv(), *fixmcwd(), *malloc();
X	long lseek();
X	void perror(), exit();
X	struct gdctl gdbuf;
X
X	if ((fd = open(FLOPPY, mode)) < 0) {
X		perror("init: open");
X		exit(1);
X	}
X					/* get the disk controller info */
X	if (ioctl(fd, GDGETA, &gdbuf) < 0) {
X		perror("init: ioctl");
X		dismount();
X	}
X					/* assume some defaults */
X	gdbuf.params.cyls = 40;		/* number of cylinders */
X	gdbuf.params.heads = 1;		/* number of heads */
X	gdbuf.params.psectrk = 8;	/* physical sectors per track */
X	gdbuf.params.pseccyl = 8;	/* physical sectors per cylinder */
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					/* set the default parameters */
X	if (ioctl(fd, GDSETA, &gdbuf) < 0) {
X		perror("init: ioctl");
X		dismount();
X	}
X					/* read media signature (1st FAT) */
X	fat = read_fat();
X	switch(fat) {
X		case 0xfe:		/* 40 trk, 8 sect, 1 side */
X			dir_start = 3;
X			dir_len = 4;
X			clus_size = 1;
X			fat_len = 1;
X			num_clus = 313;
X			gdbuf.params.heads = 1;
X			gdbuf.params.psectrk = 8;
X			gdbuf.params.pseccyl = 8;
X			break;
X		case 0xff:		/* 40 trk, 8 sect, 2 sides */
X			dir_start = 3;
X			dir_len = 7;
X			clus_size = 2;
X			fat_len = 1;
X			num_clus = 315;
X			gdbuf.params.heads = 2;
X			gdbuf.params.psectrk = 8;
X			gdbuf.params.pseccyl = 16;
X			break;
X		case 0xfc:		/* 40 trk, 9 sect, 1 side */
X			dir_start = 5;
X			dir_len = 4;
X			clus_size = 1;
X			fat_len = 2;
X			num_clus = 351;
X			gdbuf.params.heads = 1;
X			gdbuf.params.psectrk = 9;
X			gdbuf.params.pseccyl = 9;
X			break;
X		case 0xfd:		/* 40 trk, 9 sect, 2 sides */
X			dir_start = 5;
X			dir_len = 7;
X			clus_size = 2;
X			fat_len = 2;
X			num_clus = 354;
X			gdbuf.params.heads = 2;
X			gdbuf.params.psectrk = 9;
X			gdbuf.params.pseccyl = 18;
X			break;
X		default:
X			fprintf(stderr, "Unknown format '%02x'\n", fat);
X			code = 1;
X			break;
X	}
X	if (code)
X		return(1);
X					/* set the new-found parameters */
X	if (ioctl(fd, GDSETA, &gdbuf) < 0) {
X		perror("init: ioctl");
X		dismount();
X	}
X
X	buflen = fat_len * MSECSIZ;
X	fatbuf = (unsigned char *) malloc(buflen);
X	move(1);
X					/* read the FAT sectors */
X	if (read(fd, fatbuf, buflen) != buflen) {
X		perror("init: read");
X		exit(1);
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		fprintf(stderr, "Environmental variable MCWD needs updating\n");
X		exit(1);
X	}
X	return(0);
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 */
X
Xdismount()
X{
X	struct gdctl gdbuf;
X	void exit();
X
X	ioctl(fd, GDDISMNT, &gdbuf);
X	exit(1);
X}
X
X/*
X * Move the read/write head to the next location.  Tries to optimize
X * the movement by moving relative to current location.  The argument
X * is a logical sector number.  All errors are fatal.
X */
X
Xmove(sector)
Xint sector;
X{
X	long cur_loc, next, lseek();
X	void exit(), perror();
X					/* get current location */
X	if ((cur_loc = lseek(fd, 0L, 1)) < 0) {
X		perror("move: lseek");
X		exit(1);
X	}
X	next = (long) (MSECSIZ * sector) - cur_loc;
X					/* we're already there */
X	if (next == 0L)
X		return;
X					/* move to next location */
X	if (lseek(fd, next, 1) < 0) {
X		perror("move: lseek");
X		exit(1);
X	}
X	return;
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, *strcpy(), *strcat(), *malloc();
X	static char *ans;
X
X	ans = malloc(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 = NULL;
X	return(ans);
X}
X
X/*
X * Read the first byte of the FAT table.  This code serves as a media
X * signature for the diskette.
X */
X
Xunsigned char
Xread_fat()
X{
X	unsigned char buf[MSECSIZ];
X	static unsigned char ans;
X					/* move to boot sector */
X	if (lseek(fd, (long) MSECSIZ, 0) < 0) {
X		perror("init: lseek");
X		exit(1);
X	}
X					/* read the first FAT sector */
X	if (read(fd, buf, MSECSIZ) != MSECSIZ) {
X		fprintf(stderr, "Drive empty or latch not closed\n");
X		exit(1);
X	}
X	ans = buf[0];
X	return(ans);
X}
SHAR_EOF
if test 5066 -ne "`wc -c < 'init.c'`"
then
	echo shar: "error transmitting 'init.c'" '(should have been 5066 characters)'
fi
fi
echo shar: "extracting 'isdir.c'" '(917 characters)'
if test -f 'isdir.c'
then
	echo shar: "will not over-write existing file 'isdir.c'"
else
sed 's/^X//' << \SHAR_EOF > 'isdir.c'
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	int entry;
X	char *newname, *unixname(), *strncpy(), name[9], ext[4];
X	struct directory *dir, *search();
X					/* no path */
X	if (*path == NULL)
X		return(0);
X
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == NULL)
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		strncpy(name, dir->name, 8);
X		name[8] = NULL;
X		strncpy(ext, dir->ext, 3);
X		ext[3] = NULL;
X		newname = unixname(name, ext);
X		if (!strcmp(newname, path))
X			return(1);
X	}
X					/* if "." or ".." fails, then root */
X	if (!strcmp(path, ".") || !strcmp(path, ".."))
X		return(1);
X	return(0);
X}
SHAR_EOF
if test 917 -ne "`wc -c < 'isdir.c'`"
then
	echo shar: "error transmitting 'isdir.c'" '(should have been 917 characters)'
fi
fi
echo shar: "extracting 'match.c'" '(1894 characters)'
if test -f 'match.c'
then
	echo shar: "will not over-write existing file 'match.c'"
else
sed 's/^X//' << \SHAR_EOF > 'match.c'
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 != NULL; 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 == NULL)
X				return(0);
X			break;
X					/* match everything */
X		case '*':
X					/* if last char in pattern */
X			if (*++p == NULL)
X				return(1);
X					/* search for next char in pattern */
X			matched = 0;
X			while (*s != NULL) {
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 = NULL;
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 == NULL) {
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 == NULL) {
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 != NULL)
X		return(0);
X	else
X		return(1);
X}
SHAR_EOF
if test 1894 -ne "`wc -c < 'match.c'`"
then
	echo shar: "error transmitting 'match.c'" '(should have been 1894 characters)'
fi
fi
echo shar: "extracting 'mdel.c'" '(2580 characters)'
if test -f 'mdel.c'
then
	echo shar: "will not over-write existing file 'mdel.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mdel.c'
X/*
X * Delete a MSDOS file
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!ihnp4!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#define VERBOSE
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, subdir();
X	char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
X	char *strncpy(), *getpath(), *pathname, ans[10];
X	void exit();
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 <MSDOS file> [<MSDOS files...>]\n");
X		exit(1);
X	}
X
X	for (i=1; i<argc; i++) {
X		filename = getname(argv[i]);
X		pathname = getpath(argv[i]);
X		if (subdir(pathname))
X			continue;
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] == NULL)
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			strncpy(tname, dir->name, 8);
X			strncpy(text, dir->ext, 3);
X			newfile = unixname(tname, text);
X					/* see it if matches the pattern */
X			if (match(newfile, filename)) {
X#ifdef VERBOSE
X				printf("Removing %s\n", newfile);
X#endif
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						continue;
X				}
X				start = dir->start[1]*0x100 + dir->start[0];
X				zapit(start);
X				dir->name[0] = 0xe5;
X				writedir(entry, dir);
X			}
X		}
X		if (!ismatch) {
X			fprintf(stderr, "mdel: File '%s' not found\n", filename);
X			continue;
X		}
X	}
X					/* update the FAT sectors */
X	writefat();
X	close(fd);
X	exit(0);
X}
SHAR_EOF
if test 2580 -ne "`wc -c < 'mdel.c'`"
then
	echo shar: "error transmitting 'mdel.c'" '(should have been 2580 characters)'
fi
fi
echo shar: "extracting 'mdir.c'" '(4402 characters)'
if test -f 'mdir.c'
then
	echo shar: "will not over-write existing file 'mdir.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mdir.c'
X/*
X * Display a MSDOS directory
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!ihnp4!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, subdir(), fargn, wide;
X	long size;
X	char name[9], ext[4], *date, *time, *convdate(), *convtime();
X	char *strncpy(), *dirname, *getname(), *getpath(), *pathname, sep;
X	char *newfile, *filename, *malloc(), *unixname(), volume[12];
X	char *strcpy(), *strcat();
X	void exit();
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	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X		strncpy(name, dir->name, 8);
X		strncpy(ext, dir->ext, 3);
X					/* if empty */
X		if (dir->name[0] == NULL)
X			break;
X					/* if not volume label */
X		if (!(dir->attr & 0x08))
X			continue;
X		strcpy(volume, name);
X		strcat(volume, ext);
X		break;
X	}
X	if (volume[0] == NULL)
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	if (argc == fargn) {
X		argv[argc] = ".";
X		argc++;
X	}
X	files = 0;
X	for (i=fargn; i<argc; i++) {
X		filename = getname(argv[i]);
X		pathname = getpath(argv[i]);
X					/* move to first guess subdirectory */
X					/* required by isdir() */
X		if (subdir(pathname))
X			continue;
X		if (isdir(filename)) {
X			dirname = malloc(strlen(argv[i])+1);
X			strcpy(dirname, pathname);
X			if (strcmp(pathname,"/") && strcmp(pathname, "\\")) {
X				if (*pathname != NULL)
X					strcat(dirname, "/");
X			}
X			strcat(dirname, filename);
X					/* move to real subdirectory */
X			if (subdir(dirname))
X				continue;
X			filename = "*";
X		} else
X			dirname = pathname;
X
X		if (*filename == NULL)
X			filename = "*";
X		if (*dirname == '/' || *dirname == '\\')
X			printf(" Directory for %s\n\n", dirname);
X		else if (!strcmp(dirname, "."))
X			printf(" Directory for %s\n\n", mcwd);
X		else {
X			if (strlen(mcwd) == 1 || !strlen(dirname))
X				sep = NULL;
X			else
X				sep = '/';
X			printf(" Directory for %s%c%s\n\n", mcwd, sep, dirname);
X		}
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X			strncpy(name, dir->name, 8);
X			strncpy(ext, dir->ext, 3);
X			newfile = unixname(name, ext);
X					/* if empty */
X			if (dir->name[0] == NULL)
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			if (!match(newfile, filename))
X				continue;
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("%-15.15s", name);
X				else
X					printf("%8s     <DIR>      %s  %s\n", name, 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	blocks = getfree() * MSECSIZ;
X	if (!files)
X		printf("File '%s' not found\n", filename);
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 getfree()
X{
X	int i;
X	static int 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}
SHAR_EOF
if test 4402 -ne "`wc -c < 'mdir.c'`"
then
	echo shar: "error transmitting 'mdir.c'" '(should have been 4402 characters)'
fi
fi
exit 0
#	End of shell]-NZ+DZ+D

egray@fthood.UUCP (08/06/87)

This is part 2 (of 2) of the Mtools v1.2  distribution

Emmet P. Gray				US Army, HQ III Corps & Fort Hood
...!ihnp4!uiucuxc!fthood!egray		Attn: AFZF-DE-ENV
					Directorate of Engineering & Housing
					Environmental Management Office
					Fort Hood, TX 76544-5057
-------------------------------------------------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	mkentry.c
#	mmd.c
#	mrd.c
#	mread.c
#	mren.c
#	mtype.c
#	mwrite.c
#	putfat.c
#	search.c
#	subdir.c
#	unixname.c
# This archive created: Thu Aug  6 07:46:07 1987
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'mkentry.c'" '(2521 characters)'
if test -f 'mkentry.c'
then
	echo shar: "will not over-write existing file 'mkentry.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mkentry.c'
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 directory structure.
X */
X
Xstruct directory *
Xmk_entry(filename, attr, fat, size)
Xchar *filename;
Xunsigned char attr;
Xint fat;
Xlong size;
X{
X	long clock, time();
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	time(&clock);
X	now = localtime(&clock);
X	strncpy(ndir.name, filename, 8);
X	strncpy(ndir.ext, filename+8, 3);
X	ndir.attr = attr;
X	for (i=0; i<10; i++)
X		ndir.reserved[i] = NULL;
X	hour = now->tm_hour << 3;
X	min_hi = now->tm_min >> 3;
X	min_low = now->tm_min << 5;
X	sec = 0;
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, getfat(), nextfat(), num, sector, buflen;
X	static unsigned char tbuf[CLSTRBUF];
X	void perror(), exit();
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, last);
X	putfat(last, 0xfff);
X					/* zero the buffer */
X	buflen = clus_size * MSECSIZ;
X	for (i=0; i<buflen; i++)
X		tbuf[i] = NULL;
X
X					/* write the cluster */
X	sector = (last - 2) * clus_size + dir_start + dir_len;
X	move(sector);
X	if (write(fd, 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}
SHAR_EOF
if test 2521 -ne "`wc -c < 'mkentry.c'`"
then
	echo shar: "error transmitting 'mkentry.c'" '(should have been 2521 characters)'
fi
fi
echo shar: "extracting 'mmd.c'" '(3761 characters)'
if test -f 'mmd.c'
then
	echo shar: "will not over-write existing file 'mmd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mmd.c'
X/*
X * Make a MSDOS sub directory
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!ihnp4!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, subdir();
X	char *filename, *newfile, *fixname(), *strncpy(), *unixname();
X	char *getpath(), *pathname, tname[9], text[4], *fixed;
X	void exit();
X	struct directory *dir, *search(), *mk_entry();
X
X	if (init(2)) {
X		fprintf(stderr, "mmd: Cannot initialize diskette\n");
X		exit(1);
X	}
X					/* only 1 directory ! */
X	if (argc != 2) {
X		fprintf(stderr, "Usage: mmd <MSDOS directory>\n");
X		exit(1);
X	}
X	fixed = fixname(argv[1]);
X	filename = unixname(fixed, fixed+8);
X	pathname = getpath(argv[1]);
X	if (strcmp(fixed+8, "   ")) {
X		fprintf(stderr, "mmd: Directory names cannot have extensions\n");
X		exit(1);
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] == NULL) {
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		strncpy(tname, dir->name, 8);
X		strncpy(text, dir->ext, 3);
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	}
X					/* no '.' entry means root directory */
X	if (dot == 0 && slot < 0) {
X		printf(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	fat = nextfat(0);
X	if (fat == -1) {
X		fprintf(stderr, "mmd: Disk full\n");
X		exit(1);
X	}
X					/* make directory entry */
X	dir = mk_entry(fixed, 0x10, fat, 0L);
X	if (dir != NULL) {
X		writedir(slot, dir);
X					/* write the cluster */
X		putfat(fat, 0xfff);
X		putcluster(fat, dot);
X	}
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
Xputcluster(dot, dot_dot)
Xint dot;
Xint dot_dot;
X{
X	long start;
X	void exit(), perror();
X	int buflen;
X	static struct directory dirs[32];
X	struct directory *mk_entry();
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	dirs[0] = *mk_entry(".          ", 0x10, dot, 0L);
X	dirs[1] = *mk_entry("..         ", 0x10, dot_dot, 0L);
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	static 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}
SHAR_EOF
if test 3761 -ne "`wc -c < 'mmd.c'`"
then
	echo shar: "error transmitting 'mmd.c'" '(should have been 3761 characters)'
fi
fi
echo shar: "extracting 'mrd.c'" '(3159 characters)'
if test -f 'mrd.c'
then
	echo shar: "will not over-write existing file 'mrd.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mrd.c'
X/*
X * Delete a MSDOS sub directory
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!ihnp4!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, isempty();
X	char *filename, *newfile, text[4], tname[9], *getname();
X	char *strncpy(), *pathname, *getpath(), *unixname();
X	void exit();
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 <MSDOS directory>\n");
X		exit(1);
X	}
X
X	filename = getname(argv[1]);
X	pathname = getpath(argv[1]);
X	if (subdir(pathname))
X		exit(1);
X	ismatch = 0;
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == NULL)
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		strncpy(tname, dir->name, 8);
X		strncpy(text, dir->ext, 3);
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	}
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	int i, next, buflen, sector, getfat();
X	static unsigned char tbuf[CLSTRBUF];
X	void perror(), exit();
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, 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] != NULL && 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}
SHAR_EOF
if test 3159 -ne "`wc -c < 'mrd.c'`"
then
	echo shar: "error transmitting 'mrd.c'" '(should have been 3159 characters)'
fi
fi
echo shar: "extracting 'mread.c'" '(4692 characters)'
if test -f 'mread.c'
then
	echo shar: "will not over-write existing file 'mread.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mread.c'
X/*
X * Read (copy) a MSDOS file to Unix
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!ihnp4!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 <sys/types.h>
X#include <sys/stat.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 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, subdir(), single, c, oops;
X	char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
X	char *strncpy(), *pathname, *getpath(), *target, *tmp, *malloc();
X	char *strcat(), *strcpy();
X	void perror(), exit();
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	while ((c = getopt(argc, argv, "tn")) != EOF) {
X		switch(c) {
X			case 't':
X				textmode = 1;
X				break;
X			case 'n':
X				nowarn = 1;
X				break;
X			default:
X				oops = 1;
X				break;
X		}
X	}
X
X	if (oops || (argc - optind) < 2) {
X		fprintf(stderr, "Usage: mread [-t|-n] <MSDOS file> <Unix file>\n");
X		fprintf(stderr, "    or mread [-t|-n] <MSDOS file> [<MSDOS files...>] <Unix directory>\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 & 040000)
X			single = 0;	
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			continue;
X		ismatch = 0;
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X					/* if empty */
X			if (dir->name[0] == NULL)
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			strncpy(tname, dir->name, 8);
X			strncpy(text, dir->ext, 3);
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 single file */
X			if (single) {
X				if (!strcmp(newfile, filename)) {
X					readit(fat, target);
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					tmp = malloc(strlen(target)+1+strlen(newfile)+1);
X					strcpy(tmp, target);
X					strcat(tmp, "/");
X					strcat(tmp, newfile);
X					readit(fat, tmp);
X					ismatch = 1;
X				}
X			}
X		}
X		if (!ismatch) {
X			fprintf(stderr, "mread: File '%s' not found\n", filename);
X			continue;
X		}
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
Xreadit(fat, target)
Xint fat;
Xchar *target;
X{
X	char ans[10];
X	void exit();
X	FILE *fp;
X
X	current = 0L;
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		}
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	while (1) {
X		getcluster(fat, fp);
X					/* get next cluster number */
X		fat = getfat(fat);
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	fclose(fp);
X	return;
X}
X
X/*
X * Read the named cluster, write to the Unix file descriptor.
X */
X
Xgetcluster(num, fp)
Xint num;
XFILE *fp;
X{
X	int i, buflen, start;
X	void exit(), perror();
X	static unsigned char buf[CLSTRBUF];
X
X	start = (num - 2)*clus_size + dir_start + dir_len;
X	move(start);
X
X	buflen = clus_size * MSECSIZ;
X	if (read(fd, 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		fputc(buf[i], fp);
X	}
X	return;
X}
SHAR_EOF
if test 4692 -ne "`wc -c < 'mread.c'`"
then
	echo shar: "error transmitting 'mread.c'" '(should have been 4692 characters)'
fi
fi
echo shar: "extracting 'mren.c'" '(2628 characters)'
if test -f 'mren.c'
then
	echo shar: "will not over-write existing file 'mren.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mren.c'
X/*
X * Rename an existing MSDOS file
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!ihnp4!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, subdir(), nogo, isdir();
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();
X	struct directory *dir, *search();
X
X	if (init(2)) {
X		fprintf(stderr, "mren: Cannot initialize diskette\n");
X		exit(1);
X	}
X	if (argc != 3) {
X		fprintf(stderr, "Usage: mren <MSDOS source file> <MSDOS target file>\n");
X		exit(1);
X	}
X	filename = getname(argv[1]);
X	pathname = getpath(argv[1]);
X	if (subdir(pathname))
X		exit(1);
X
X	temp = getname(argv[2]);
X	target = fixname(argv[2]);
X	if (isdir(filename) && strcmp(target+8, "   ")) {
X		strcpy(target+8, "   ");
X		fprintf(stderr, "mren: Directory names may not have extentions\n");
X	}
X	new = unixname(target, target+8);
X	nogo = 0;
X					/* the name supplied may be altered */
X	if (strcmp(temp, new)) {
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] == NULL)
X			break;
X					/* if erased */
X		if (dir->name[0] == 0xe5)
X			continue;
X					/* you may rename a directory */
X		strncpy(tname, dir->name, 8);
X		strncpy(text, dir->ext, 3);
X		newfile = unixname(tname, text);
X		if (!strcmp(filename, newfile)) {
X			ismatch = 1;
X			strncpy(dir->name, target, 8);
X			strncpy(dir->ext, target+8, 3);
X			writedir(entry, dir);
X		}
X	}
X	if (!ismatch) {
X		fprintf(stderr, "mren: File '%s' not found\n", filename);
X		exit(1);
X	}
X	close(fd);
X	exit(0);
X}
SHAR_EOF
if test 2628 -ne "`wc -c < 'mren.c'`"
then
	echo shar: "error transmitting 'mren.c'" '(should have been 2628 characters)'
fi
fi
echo shar: "extracting 'mtype.c'" '(3479 characters)'
if test -f 'mtype.c'
then
	echo shar: "will not over-write existing file 'mtype.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mtype.c'
X/*
X * Display contents of a MSDOS file
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!ihnp4!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;
Xstripmode = 0;
Xtextmode = 0;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	extern int optind;
X	extern char *optarg;
X	int fat, i, ismatch, entry, subdir(), c, oops;
X	char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
X	char *strncpy(), *pathname, *getpath();
X	void exit();
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 [-s|-t] <MSDOS file> [<MSDOS files...>]\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			continue;
X		ismatch = 0;
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X					/* if empty */
X			if (dir->name[0] == NULL)
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			strncpy(tname, dir->name, 8);
X			strncpy(text, dir->ext, 3);
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		}
X		if (!ismatch) {
X			fprintf(stderr, "mtype: File '%s' not found\n", filename);
X			continue;
X		}
X	}
X	close(fd);
X	exit(0);
X}
X
X/*
X * Decode the FAT chain given the begining FAT entry.
X */
X
Xreadit(fat)
Xint fat;
X{
X	current = 0L;
X
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 name cluster, output to the stdout.
X */
X
Xgetcluster(num)
Xint num;
X{
X	int i, buflen, start;
X	void exit(), perror();
X	static unsigned char buf[CLSTRBUF];
X
X	start = (num - 2)*clus_size + dir_start + dir_len;
X	move(start);
X
X	buflen = clus_size * MSECSIZ;
X	if (read(fd, 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 (stripmode)
X			putchar(buf[i] & 0x7f);
X		else
X			putchar(buf[i]);
X	}
X	return;
X}
SHAR_EOF
if test 3479 -ne "`wc -c < 'mtype.c'`"
then
	echo shar: "error transmitting 'mtype.c'" '(should have been 3479 characters)'
fi
fi
echo shar: "extracting 'mwrite.c'" '(7271 characters)'
if test -f 'mwrite.c'
then
	echo shar: "will not over-write existing file 'mwrite.c'"
else
sed 's/^X//' << \SHAR_EOF > 'mwrite.c'
X/*
X * Write (copy) a Unix file to MSDOS
X *
X * Emmet P. Gray			US Army, HQ III Corps & Fort Hood
X * ...!ihnp4!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 <sys/types.h>
X#include <sys/stat.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
Xint full = 0;
Xint textmode = 0;
Xint nowarn = 0;
Xlong filesize;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	extern int optind;
X	extern char *optarg;
X	int i, entry, ismatch, nogo, slot, start, dot, subdir(), single;
X	int isdir(), root, c, oops;
X	char *filename, *newfile, tname[9], text[4], *fixname(), *getname();
X	char *unixname(), ans[10], *strncpy(), *pathname, *getpath(), *fixed;
X	char *tmp, *malloc(), *strcat(), *strcpy();
X	void exit();
X	struct directory *dir, *search(), *writeit();
X
X	if (init(2)) {
X		fprintf(stderr, "mwrite: Cannot initialize diskette\n");
X		exit(1);
X	}
X					/* get command line options */
X	oops = 0;
X	while ((c = getopt(argc, argv, "tn")) != EOF) {
X		switch(c) {
X			case 't':
X				textmode = 1;
X				break;
X			case 'n':
X				nowarn = 1;
X				break;
X			default:
X				oops = 1;
X				break;
X		}
X	}
X
X	if (oops || (argc - optind) < 2) {
X		fprintf(stderr, "Usage: mwrite [-t|-n] <Unix file> <MSDOS file>\n");
X		fprintf(stderr, "    or mwrite [-t|-n] <Unix file> [<Unix files...>] <MSDOS directory>\n");
X		exit(1);
X	}
X	root = 0;
X	if (!strcmp(argv[argc-1], "/") || !strcmp(argv[argc-1], "\\"))
X		root = 1;
X	filename = getname(argv[argc-1]);
X	pathname = getpath(argv[argc-1]);
X					/* test if path is ok first */
X	if (subdir(pathname))
X		exit(1);
X					/* test if last argv is a dir */
X	if (isdir(filename) || root) {
X		if (!strlen(pathname)) {
X					/* don't alter the presence or */
X					/* absence of a leading separator */
X			tmp = malloc(strlen(filename)+1);
X			strcpy(tmp, filename);
X		}
X		else {
X			tmp = malloc(strlen(pathname)+1+strlen(filename)+1);
X			strcpy(tmp, pathname);
X			strcat(tmp, "/");
X			strcat(tmp, filename);
X		}
X					/* subdir is not recursive */
X		subdir(tmp);
X		single = 0;
X	}
X	else
X		single = 1;
X
X	for (i=optind; i<argc-1; i++) {
X		if (single) {
X			fixed = fixname(argv[argc-1]);
X			filename = unixname(fixed, fixed+8);
X		}
X		else {
X			fixed = fixname(argv[i]);
X			filename = unixname(fixed, fixed+8);
X			printf("Copying %s\n", filename);
X		}
X					/* see if exists and get slot */
X		ismatch = 0;
X		slot = -1;
X		dot = 0;
X		nogo = 0;
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X					/* is empty */
X			if (dir->name[0] == NULL) {
X				if (slot < 0)
X					slot = entry;
X				break;
X			}
X					/* is erased */
X			if (dir->name[0] == 0xe5) {
X				if (slot < 0)
X					slot = entry;
X				continue;
X			}
X			strncpy(tname, dir->name, 8);
X			strncpy(text, dir->ext, 3);
X			newfile = unixname(tname, text);
X					/* save the '.' entry info */
X			if ((dir->attr & 0x10) && !strcmp(".", newfile)) {
X				dot = dir->start[1]*0x100 + dir->start[0];
X				continue;
X			}
X					/* is dir or volume lable */
X			if ((dir->attr & 0x10) || (dir->attr & 0x08))
X				continue;
X					/* if file exists, delete it first */
X			if (!strcmp(filename, newfile)) {
X				ismatch = 1;
X				start = dir->start[1]*0x100 + dir->start[0];
X				if (nowarn) {
X					zapit(start);
X					dir->name[0] = 0xe5;
X					writedir(entry, dir);
X					if (slot < 0)
X						slot = entry;
X				} else {
X					while (1) {
X						printf("File '%s' exists, overwrite (y/n) ? ", filename);
X						gets(ans);
X						if (ans[0] == 'n' || ans[0] == 'N') {
X							nogo = 1;
X							break;
X						}
X						if (ans[0] == 'y' || ans[0] == 'Y') {
X							zapit(start);
X							dir->name[0] = 0xe5;
X							writedir(entry, dir);
X							if (slot < 0)
X								slot = entry;
X							break;
X						}
X					}
X				}
X			}
X			if (ismatch)
X				break;
X		}
X		if (nogo)		/* chickened out... */
X			continue;
X					/* no '.' entry means root directory */
X		if (dot == 0 && slot < 0) {
X			printf(stderr, "mwrite: 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, "mwrite: Disk full\n");
X				exit(1);
X			}
X					/* first entry in 'new' directory */
X			slot = entry;
X		}
X					/* write the file */
X		dir = writeit(fixed, argv[i]);
X		if (dir != NULL)
X			writedir(slot, dir);
X
X		if (full) {
X			fprintf(stderr, "mwrite: Disk Full\n");
X			break;
X		}
X		if (single)
X			break;
X	}
X					/* write FAT sectors */
X	writefat();
X	close(fd);
X	exit(0);
X}
X
X/*
X * Open the named file for write, create the cluster chain, return the
X * directory structure.
X */
X
Xstruct directory *
Xwriteit(fixed, path)
Xchar *fixed;
Xchar *path;
X{
X	FILE *fp;
X	int fat, firstfat, oldfat, nextfat(), putcluster(), putfat();
X	long size;
X	struct directory *mk_entry();
X	static struct directory *dir;
X	struct stat stbuf;
X
X	if (stat(path, &stbuf) < 0) {
X		fprintf(stderr, "mwrite: Can't stat '%s'\n", path);
X		return(NULL);
X	}
X	filesize = stbuf.st_size;
X	if (!(fp = fopen(path, "r"))) {
X		fprintf(stderr, "mwrite: Can't open '%s' for read\n", path);
X		return(NULL);
X	}
X	size = 0L;
X	firstfat = nextfat(0);
X	if (firstfat == -1) {
X		full = 1;
X		return(NULL);
X	}
X	fat = firstfat;
X	while (1) {
X		size += putcluster(fat, fp);
X		if (size >= filesize) {
X			putfat(fat, 0xfff);
X			break;
X		}
X		oldfat = fat;
X					/* get next free cluster */
X		fat = nextfat(oldfat);
X		if (fat == -1) {
X			putfat(oldfat, 0xfff);
X			full = 1;
X			break;
X		}
X		putfat(oldfat, fat);
X	}
X	fclose(fp);
X	dir = mk_entry(fixed, 0, firstfat, size);
X	return(dir);
X}
X
X/*
X * Write to the cluster from the named Unix file descriptor.
X */
X
Xint
Xputcluster(num, fp)
Xint num;
XFILE *fp;
X{
X	long start;
X	void exit(), perror();
X	int buflen, c;
X	static int current;
X	static unsigned char tbuf[CLSTRBUF];
X
X	start = (num - 2)*clus_size + dir_start + dir_len;
X	move(start);
X
X	buflen = clus_size * MSECSIZ;
X					/* '\n' to '\r\n' translation */
X	if (textmode) {
X		current = 0;
X		while (current < buflen) {
X			if ((c = fgetc(fp)) == EOF) {
X					/* put a file EOF marker */
X				tbuf[current] = 0x1a;
X				break;
X			}
X			if (c == '\n') {
X				tbuf[current++] = '\r';
X				if (current == buflen)
X					break;
X				tbuf[current++] = '\n';
X					/* make the file appear larger */
X				filesize++;
X			}
X			else 
X				tbuf[current++] = c;
X		}
X	}
X	else {
X		if ((current = fread(tbuf, sizeof(char), buflen, fp)) < 0) {
X			perror("putcluster: fread");
X			exit(1);
X		}
X					/* all files get an EOF marker */
X		if (current != buflen) 
X			tbuf[current+1] = 0x1a;
X	}
X	
X	if (write(fd, tbuf, buflen) != buflen) {
X		perror("putcluster: write");
X		exit(1);
X	}
X	return(current);
X}
X
X/*
X * Returns next free cluster or -1 if none are available.
X */
X
Xint
Xnextfat(last)
Xint last;
X{
X	static 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}
SHAR_EOF
if test 7271 -ne "`wc -c < 'mwrite.c'`"
then
	echo shar: "error transmitting 'mwrite.c'" '(should have been 7271 characters)'
fi
fi
echo shar: "extracting 'putfat.c'" '(3118 characters)'
if test -f 'putfat.c'
then
	echo shar: "will not over-write existing file 'putfat.c'"
else
sed 's/^X//' << \SHAR_EOF > 'putfat.c'
X/*
X * putfat(), writedir(), zapit(), writefat()
X */
X
X#include <stdio.h>
X#include "msdos.h"
X#undef DUP_FAT
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
Xwritedir(num, dir)
Xint num;
Xstruct directory *dir;
X{
X	int skip, entry;
X	void exit(), perror();
X	static struct directory dirs[16];
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
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}
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
Xwritefat()
X{
X	int buflen;
X
X	move(1);
X	buflen = fat_len * MSECSIZ;
X	if (write(fd, fatbuf, buflen) != buflen) {
X		perror("writefat: write");
X		exit(1);
X	}
X#ifdef DUP_FAT
X					/* the duplicate FAT table */
X	if (write(fd, fatbuf, buflen) != buflen) {
X		perror("writefat: write");
X		exit(1);
X	}
X#endif DUP_FAT
X	return;
X}
SHAR_EOF
if test 3118 -ne "`wc -c < 'putfat.c'`"
then
	echo shar: "error transmitting 'putfat.c'" '(should have been 3118 characters)'
fi
fi
echo shar: "extracting 'search.c'" '(1075 characters)'
if test -f 'search.c'
then
	echo shar: "will not over-write existing file 'search.c'"
else
sed 's/^X//' << \SHAR_EOF > 'search.c'
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	void exit(), perror();
X	static int last;
X	static struct directory dirs[16];
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}
SHAR_EOF
if test 1075 -ne "`wc -c < 'search.c'`"
then
	echo shar: "error transmitting 'search.c'" '(should have been 1075 characters)'
fi
fi
echo shar: "extracting 'subdir.c'" '(3843 characters)'
if test -f 'subdir.c'
then
	echo shar: "will not over-write existing file 'subdir.c'"
else
sed 's/^X//' << \SHAR_EOF > 'subdir.c'
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;
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
Xsubdir(name)
Xchar *name;
X{
X	char *s, *tmp, *path, *malloc(), *strcpy(), *strcat();
X	static int code;
X	int getdir();
X					/* if full pathname */
X	if (*name == '/' || *name == '\\') {
X		tmp = malloc(strlen(name)+1);
X		strcpy(tmp, name);
X	}
X					/* if relative to MCWD */
X	else {
X		if (!strlen(name)) {
X			tmp = malloc(strlen(mcwd)+1);
X			strcpy(tmp, mcwd);
X		}
X		else {
X			tmp = malloc(strlen(mcwd)+1+strlen(name)+1);
X			strcpy(tmp, mcwd);
X			strcat(tmp, "/");
X			strcat(tmp, name);
X		}
X	}
X					/* if paths are same, do nothing */
X	if (!strcmp(tmp, lastpath))
X		return(0);
X					/* not recursive, start at root */
X	reset_dir();
X	lastpath = malloc(strlen(tmp)+1);
X	strcpy(lastpath, tmp);
X					/* zap the leading separator */
X	if (*tmp == '\\' || *tmp == '/')
X		tmp++;
X	for (s = tmp; *s; ++s) {
X		if (*s == '\\' || *s == '/') {
X			path = tmp;
X			*s = NULL;
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, get_chain();
X	char *newname, *unixname(), *strncpy(), name[9], ext[4];
X	struct directory *dir, *search();
X
X					/* nothing required */
X	if (*path == NULL)
X		return(0);
X
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == NULL)
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		strncpy(name, dir->name, 8);
X		name[8] = NULL;
X		strncpy(ext, dir->ext, 3);
X		ext[3] = NULL;
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	}
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 next;
X	static int i;
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
Xreset_dir()
X{
X	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";
X	return;
X}
SHAR_EOF
if test 3843 -ne "`wc -c < 'subdir.c'`"
then
	echo shar: "error transmitting 'subdir.c'" '(should have been 3843 characters)'
fi
fi
echo shar: "extracting 'unixname.c'" '(2293 characters)'
if test -f 'unixname.c'
then
	echo shar: "will not over-write existing file 'unixname.c'"
else
sed 's/^X//' << \SHAR_EOF > 'unixname.c'
X/*
X * unixname(), getname(), getpath()
X */
X
X#include <stdio.h>
X#include <ctype.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;
Xchar *ext;
X{
X	static char *ans;
X	char *s, tname[9], text[4], *strcpy(), *strcat(), *malloc();
X	char *strchr(), *strncpy();
X
X	strncpy(tname, name, 8);
X	s = strchr(tname, ' ');
X	if (s != NULL)
X		*s = NULL;
X	tname[8] = NULL;
X
X	strncpy(text, ext, 3);
X	s = strchr(text, ' ');
X	if (s != NULL)
X		*s = NULL;
X	text[3] = NULL;
X
X	if (*text != NULL) {
X		ans = malloc(strlen(tname)+1+strlen(text)+1);
X		strcpy(ans, tname);
X		strcat(ans, ".");
X		strcat(ans, text);
X	}
X	else {
X		ans = malloc(strlen(tname)+1);
X		strcpy(ans, tname);
X	}
X	return(ans);
X}
X
X/*
X * Get name component of filename.  Translates name to upper case.  Returns
X * pointer to new name.  Could be NULL.
X */
X
Xchar *
Xgetname(name)
Xchar *name;
X{
X	char *s, *malloc(), *strcpy(), *strrchr();
X	static char *temp;
X
X	if (*name == NULL)
X		return(NULL);
X
X	temp = malloc(strlen(name)+1);
X	strcpy(temp, name);
X				
X	if (s = strrchr(temp, '/'))
X		temp = s+1;
X	if (s = strrchr(temp, '\\'))
X		temp = s+1;
X
X	for (s = temp; *s; ++s) {
X		if (islower(*s))
X			*s = toupper(*s);
X	}
X	return(temp);
X}
X
X/*
X * Get the path component of the filename.  Translates to upper case.
X * Returns pointer to path or NULL if no path exist.  Doesn't alter
X * leading separator, always strips trailing separator (unless it is the
X * path itself).
X */
X
Xchar *
Xgetpath(name)
Xchar *name;
X{
X	char *s, *s1, *malloc(), *strcpy(), *strrchr();
X	static char *temp;
X
X	if (*name == NULL)
X		return(NULL);
X
X	temp = malloc(strlen(name)+1);
X	strcpy(temp, name);
X
X	s = strrchr(temp, '/');
X	s1 = strrchr(temp, '\\');
X					/* if both are NULL , no path */
X	if (s1 == s)
X		return(NULL);
X					/* zap which ever is last separator */
X	if (s1 > s)
X		*s1 = NULL;
X	if (s > s1)
X		*s = NULL;
X					/* translate to upper case */
X	for (s = temp; *s; ++s) {
X		if (islower(*s))
X			*s = toupper(*s);
X	}
X					/* if null, put separator back */
X	if (!strlen(temp))
X		temp = "/";
X	return(temp);
X}
SHAR_EOF
if test 2293 -ne "`wc -c < 'unixname.c'`"
then
	echo shar: "error transmitting 'unixname.c'" '(should have been 2293 characters)'
fi
fi
exit 0
#	End of shell archive