Path: utzoo!utgpu!watmath!uunet!lll-winken!xanth!galaxia!lazlo!gizzmo!fthood!egray From: egray@fthood.UUCP Newsgroups: unix-pc.sources Subject: REPOST Mtools v1.6 (1 of 2) Message-ID: <6800124@fthood> Date: 16 Jul 89 15:12:00 GMT Lines: 2221 Nf-ID: #N:fthood:6800124:000:60270 Nf-From: fthood.UUCP!egray Jul 16 10:12:00 1989 Several folks have pointed out that they never saw the orginal posting of Mtools v1.6. Is it possible that it didn't actually go out??? I have been having some trouble with my unix-pc.* news feed, so I guess anything is possible... So, here is a repost (I think) of the most current version (with the two patches already installed). Sorry for any confusion... Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV fthood!egray@uxc.cso.uiuc.edu Directorate of Engineering & Housing Environmental Management Office Fort Hood, TX 76544-5057 ------------------------------------------------------------------------------ This is part 1 (of 2) to the Mtools v1.6 distribution package. Mtools is a collection of MSDOS tools to allow you to read and write to MSDOS formatted diskettes from a Unix based system. The following MSDOS commands are emulated: Mtool MSDOS name equivalent Description ----- ---- ----------- mcopy COPY copy MSDOS files to/from Unix 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 low level 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 low level write (copy) a Unix file to MSDOS Please remember... Providing a custom device driver to suit your floppy drive is beyond the scope of this program. As always, there is a shell archive called Unixpc.shar that contains the files specific to the AT&T Unix PC 7300/3b1. Have fun... Emmet P. Gray US Army, HQ III Corps & Fort Hood ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV fthood!egray@uxc.cso.uiuc.edu 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: # Customize # Makefile # Mcopy.1 # Mdel.1 # Mdir.1 # Mmd.1 # Mrd.1 # Mread.1 # Mren.1 # Mtype.1 # Mwrite.1 # Readme # Unixpc.shar # convdate.c # fixname.c # getfat.c # init.c # isdir.c # match.c # mcopy.c # This archive created: Thu Jul 6 08:08:50 1989 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'Customize'" '(3088 characters)' if test -f 'Customize' then echo shar: "will not over-write existing file 'Customize'" else sed 's/^X//' << \SHAR_EOF > 'Customize' 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 XThen, you would edit the init.c file to include the new non-standard Xparameters. You might need Norton Utilities, or some other program, to Xdetermine the statistics of the format. Using our example, the format Xwould have the following parameters: X X FAT#1 sectors 1 - 3 fat_len = 3 X FAT#2 sectors 4 - 6 dir_start = 7 X DIR sectors 7 - 13 dir_len = 7 X cluster size is 2 sectors clus_size = 2 X there are 633 clusters num_clus = 633 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 SHAR_EOF if test 3088 -ne "`wc -c < 'Customize'`" then echo shar: "error transmitting 'Customize'" '(should have been 3088 characters)' fi fi echo shar: "extracting 'Makefile'" '(2922 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 XCFLAGS = -O XLDFLAGS = -s XLINT = lint -p XSHAR = shar -a XBINDIR = /usr/local/bin XPROGS = mdir mread mwrite mdel mtype mmd mrd mren mcopy X XMDIR = mdir.o getfat.o init.o search.o match.o convdate.o unixname.o \ X subdir.o isdir.o XMREAD = mread.o getfat.o init.o search.o match.o unixname.o subdir.o \ X convdate.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 \ X subdir.o 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.c \ X subdir.o isdir.o XMCOPY = mcopy.o X Xall: $(PROGS) 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: X cp mdir $(BINDIR)/mdir X# cp Mdir.1 /usr/man/man1/mdir.1 X cp mread $(BINDIR)/mread X# cp Mread.1 /usr/man/man1/mread.1 X cp mwrite $(BINDIR)/mwrite X# cp Mwrite.1 /usr/man/man1/mwrite.1 X cp mdel $(BINDIR)/mdel X# cp Mdel.1 /usr/man/man1/mdel.1 X cp mtype $(BINDIR)/mtype X# cp Mtype.1 /usr/man/man1/mtype.1 X cp mmd $(BINDIR)/mmd X# cp Mmd.1 /usr/man/man1/mmd.1 X cp mrd $(BINDIR)/mrd X# cp Mrd.1 /usr/man/man1/mrd.1 X cp mren $(BINDIR)/mren X# cp Mren.1 /usr/man/man1/mren.1 X cp mcopy $(BINDIR)/mcopy X# cp Mcopy.1 /usr/man/man1/mcopy.1 X Xclean: X rm $(PROGS) 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) Customize Makefile Mcopy.1 Mdel.1 Mdir.1 Mmd.1 Mrd.1 \ X Mread.1 Mren.1 Mtype.1 Mwrite.1 Readme Unixpc.shar convdate.c \ X fixname.c getfat.c init.c isdir.c match.c mcopy.c > mtools_sh.1 X $(SHAR) mdel.c mdir.c mkentry.c mmd.c mrd.c mread.c mren.c \ X msdos.h mtype.c mwrite.c putfat.c search.c subdir.c unixname.c \ X > mtools_sh.2 X Xinit.o: msdos.h SHAR_EOF if test 2922 -ne "`wc -c < 'Makefile'`" then echo shar: "error transmitting 'Makefile'" '(should have been 2922 characters)' fi fi echo shar: "extracting 'Mcopy.1'" '(1676 characters)' if test -f 'Mcopy.1' then echo shar: "will not over-write existing file 'Mcopy.1'" else sed 's/^X//' << \SHAR_EOF > 'Mcopy.1' 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. SHAR_EOF if test 1676 -ne "`wc -c < 'Mcopy.1'`" then echo shar: "error transmitting 'Mcopy.1'" '(should have been 1676 characters)' fi fi echo shar: "extracting 'Mdel.1'" '(869 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 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. SHAR_EOF if test 869 -ne "`wc -c < 'Mdel.1'`" then echo shar: "error transmitting 'Mdel.1'" '(should have been 869 characters)' fi fi echo shar: "extracting 'Mdir.1'" '(975 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] 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. SHAR_EOF if test 975 -ne "`wc -c < 'Mdir.1'`" then echo shar: "error transmitting 'Mdir.1'" '(should have been 975 characters)' fi fi echo shar: "extracting 'Mmd.1'" '(906 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 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) SHAR_EOF if test 906 -ne "`wc -c < 'Mmd.1'`" then echo shar: "error transmitting 'Mmd.1'" '(should have been 906 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 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) 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'" '(1327 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 \- 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. SHAR_EOF if test 1327 -ne "`wc -c < 'Mread.1'`" then echo shar: "error transmitting 'Mread.1'" '(should have been 1327 characters)' fi fi echo shar: "extracting 'Mren.1'" '(1237 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 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. SHAR_EOF if test 1237 -ne "`wc -c < 'Mren.1'`" then echo shar: "error transmitting 'Mren.1'" '(should have been 1237 characters)' fi fi echo shar: "extracting 'Mtype.1'" '(978 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 -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. SHAR_EOF if test 978 -ne "`wc -c < 'Mtype.1'`" then echo shar: "error transmitting 'Mtype.1'" '(should have been 978 characters)' fi fi echo shar: "extracting 'Mwrite.1'" '(1594 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 \- 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. SHAR_EOF if test 1594 -ne "`wc -c < 'Mwrite.1'`" then echo shar: "error transmitting 'Mwrite.1'" '(should have been 1594 characters)' fi fi echo shar: "extracting 'Readme'" '(3841 characters)' if test -f 'Readme' then echo shar: "will not over-write existing file 'Readme'" else sed 's/^X//' << \SHAR_EOF > 'Readme' X MTOOLS X version 1.6.2 - 5 Jul 89 X XThis is a collection of MSDOS tools to allow you to read and write to XMSDOS formatted diskettes from a Unix based system. X XThe following MSDOS commands are emulated: X XMtool MSDOS Xname equivalent Description X----- ---- ----------- Xmcopy COPY copy MSDOS files to/from Unix Xmdel DEL/ERASE delete a MSDOS file Xmdir DIR display a MSDOS directory Xmmd MD/MKDIR make a MSDOS sub directory Xmrd RD/RMDIR remove a MSDOS sub directory Xmread COPY low level read (copy) a MSDOS file to Unix Xmren REN/RENAME rename an existing MSDOS file Xmtype TYPE display contents of a MSDOS file Xmwrite COPY low level write (copy) a Unix file to MSDOS X* CD change working directory X X * by use of the environmental variable MCWD X XThe formats of IBM PC floppy disk drives are: X X bytes per sectors per tracks number total disk introduced X sector track per side of sides capacity size in MSDOS X 512 8 40 1 160k 5.25 1.0 X 512 9 40 1 180k 5.25 1.1 X 512 8 40 2 320k 5.25 2.0 X 512 9 40 2 360k 5.25 2.0 X 512 15 80 2 1.2M 5.25 3.0 X 512 8 80 2 720k 3.5 3.1 X 512 16 80 2 1.4k 3.5 3.2 X X XThe following may be typical Unix device names for the IBM formats: X X /dev/rflp 'generic' used first to test the media X /dev/rflp40t8s1s 40 track 8 sector single sided X /dev/rflp40t8s2s 40 track 8 sector double sided X /dev/rflp40t9s1s 40 track 9 sector single sided X /dev/rflp40t9s2s 40 track 9 sector double sided X /dev/rflp80t15s2s 80 track 15 sector double sided X XThese device names are in the msdos.h file as #defines and must be Xedited to match the device names on your system. If your device driver Xdoes not handle all of the formats shown, then you should leave those Xparticular devices undefined in the msdos.h file. X XThe manuals are very terse... it's assumed that the reader is already Xfamiliar with MSDOS. X XThe use of the environmental variable MCWD to keep track of the current Xworking directory is a little awkward, especially since there is no X'change directory' command. Bourne shell users will have to type two Xcommands to initially set their working directory, ie: X X MCWD=/TMP X export MCWD X XWildcards are only applied to filenames and not to directory names. For Xexample '/usr/local/*.c' is appropriate, but '/usr/l*/main.c' is not. X XI really wanted to avoid the use of a 'text' mode and a 'data' mode when Xtransferring files, but I couldn't find a better way. It gets rather Xconfusing and it's quite possible to mess up a file if you apply the Xtext mode when it is not appropriate (ie: to a COM or EXE file). XLikewise, if you forget to apply the text mode (to a Unix text file) Xthen if the file is used under MSDOS, it will be missing carriage Xreturns. However, if you aren't going to use the files on your Unix Xsystem (you just intend to hold the files and then transfer them back to XMSDOS later) then you shouldn't use the text mode during either mread or Xmwrite. This is because, the text mode is only useful if the files are Xgonna be used under Unix. X XThe implementation of the Mcopy command is somewhat clumbsy since the XMSDOS drive designation "A:" is used. Mcopy is really a front-end to Xthe low level Mread and Mwrite commands. X XThere are is a shell archives called "Unixpc.shar" that contain files Xspecific to the AT&T Unix PC 7300/3b1. X XEmmet P. Gray US Army, HQ III Corps & Fort Hood X...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X Directorate of Engineering & Housing X Environmental Management Office X Fort Hood, TX 76544-5057 SHAR_EOF if test 3841 -ne "`wc -c < 'Readme'`" then echo shar: "error transmitting 'Readme'" '(should have been 3841 characters)' fi fi echo shar: "extracting 'Unixpc.shar'" '(11391 characters)' if test -f 'Unixpc.shar' then echo shar: "will not over-write existing file 'Unixpc.shar'" else sed 's/^X//' << \SHAR_EOF > 'Unixpc.shar' X#! /bin/sh X# This is a shell archive, meaning: X# 1. Remove everything above the #! /bin/sh line. X# 2. Save the resulting text in a file. X# 3. Execute the file with /bin/sh (not csh) to create: X# Makefile X# init.c X# msdos.h X# This archive created: Wed Jul 5 18:59:43 1989 Xexport PATH; PATH=/bin:/usr/bin:$PATH Xecho shar: "extracting 'Makefile'" '(2980 characters)' Xif test -f 'Makefile' Xthen X echo shar: "will not over-write existing file 'Makefile'" Xelse Xsed 's/^X//' << \SHAR_EOF > 'Makefile' XX# XX# Makefile for MSDOS tools XX# XX XXCFLAGS = -O XXLD = ld -s XXLINT = lint -p XXSHAR = shar -a XXBINDIR = /usr/local/bin XXPROGS = mdir mread mwrite mdel mtype mmd mrd mren mcopy XXSHAREDLIB = /lib/crt0s.o /lib/shlib.ifile XX XXMDIR = mdir.o getfat.o init.o search.o match.o convdate.o unixname.o \ XX subdir.o isdir.o XXMREAD = mread.o getfat.o init.o search.o match.o unixname.o subdir.o \ XX convdate.o XXMWRITE = mwrite.o getfat.o init.o search.o fixname.o unixname.o putfat.o \ XX subdir.o mkentry.o isdir.o XXMDEL = mdel.o getfat.o init.o search.o match.o unixname.o putfat.o subdir.o XXMTYPE = mtype.o getfat.o init.o search.o match.o unixname.o subdir.o XXMMD = mmd.o getfat.o init.o search.o fixname.o unixname.o putfat.o \ XX subdir.o mkentry.o XXMRD = mrd.o getfat.o init.o search.o unixname.o putfat.o subdir.o XXMREN = mren.o getfat.o init.o search.o fixname.o unixname.o putfat.o \ XX subdir.o isdir.o XXMCOPY = mcopy.o XX XXall: $(PROGS) XX XXmdir: $(MDIR) XX $(LD) $(MDIR) $(SHAREDLIB) -o mdir XX XXmread: $(MREAD) XX $(LD) $(MREAD) $(SHAREDLIB) -o mread XX XXmwrite: $(MWRITE) XX $(LD) $(MWRITE) $(SHAREDLIB) -o mwrite XX XXmdel: $(MDEL) XX $(LD) $(MDEL) $(SHAREDLIB) -o mdel XX XXmtype: $(MTYPE) XX $(LD) $(MTYPE) $(SHAREDLIB) -o mtype XX XXmmd: $(MMD) XX $(LD) $(MMD) $(SHAREDLIB) -o mmd XX XXmrd: $(MRD) XX $(LD) $(MRD) $(SHAREDLIB) -o mrd XX XXmren: $(MREN) XX $(LD) $(MREN) $(SHAREDLIB) -o mren XX XXmcopy: $(MCOPY) XX $(LD) $(MCOPY) $(SHAREDLIB) -o mcopy XX XXinstall: XX cp mdir $(BINDIR)/mdir XX# cp Mdir.1 /usr/man/man1/mdir.1 XX cp mread $(BINDIR)/mread XX# cp Mread.1 /usr/man/man1/mread.1 XX cp mwrite $(BINDIR)/mwrite XX# cp Mwrite.1 /usr/man/man1/mwrite.1 XX cp mdel $(BINDIR)/mdel XX# cp Mdel.1 /usr/man/man1/mdel.1 XX cp mtype $(BINDIR)/mtype XX# cp Mtype.1 /usr/man/man1/mtype.1 XX cp mmd $(BINDIR)/mmd XX# cp Mmd.1 /usr/man/man1/mmd.1 XX cp mrd $(BINDIR)/mrd XX# cp Mrd.1 /usr/man/man1/mrd.1 XX cp mren $(BINDIR)/mren XX# cp Mren.1 /usr/man/man1/mren.1 XX cp mcopy $(BINDIR)/mcopy XX# cp Mcopy.1 /usr/man/man1/mcopy.1 XX XXclean: XX rm $(PROGS) XX XXlint: XX $(LINT) mdir.c getfat.c init.c search.c match.c convdate.c subdir.c \ XX unixname.c isdir.c XX $(LINT) mread.c getfat.c init.c search.c match.c unixname.c subdir.c XX $(LINT) mwrite.c getfat.c init.c search.c fixname.c unixname.c \ XX putfat.c subdir.c mkentry.c isdir.c XX $(LINT) mdel.c getfat.c init.c search.c match.c unixname.c putfat.c \ XX subdir.c XX $(LINT) mtype.c getfat.c init.c search.c match.c unixname.c subdir.c XX $(LINT) mmd.c getfat.c init.c search.c fixname.c unixname.c putfat.c \ XX subdir.c mkentry.c XX $(LINT) mrd.c getfat.c init.c search.c unixname.c putfat.c subdir.c XX $(LINT) mren.c getfat.c init.c search.c fixname.c unixname.c putfat.c \ XX subdir.c XX $(LINT) mcopy.c XX XXshar: XX $(SHAR) Customize Makefile Mcopy.1 Mdel.1 Mdir.1 Mmd.1 Mrd.1 \ XX Mread.1 Mren.1 Mtype.1 Mwrite.1 Readme Unixpc.shar convdate.c \ XX fixname.c getfat.c init.c isdir.c match.c mcopy.c > mtools_sh.1 XX $(SHAR) mdel.c mdir.c mkentry.c mmd.c mrd.c mread.c mren.c \ XX msdos.h mtype.c mwrite.c putfat.c search.c subdir.c unixname.c \ XX > mtools_sh.2 XX XXinit.o: msdos.h XSHAR_EOF Xif test 2980 -ne "`wc -c < 'Makefile'`" Xthen X echo shar: "error transmitting 'Makefile'" '(should have been 2980 characters)' Xfi Xfi Xecho shar: "extracting 'init.c'" '(6148 characters)' Xif test -f 'init.c' Xthen X echo shar: "will not over-write existing file 'init.c'" Xelse Xsed 's/^X//' << \SHAR_EOF > 'init.c' XX/* XX * Initialize a MSDOS diskette. Get the media signature (1st FAT XX * entry) and alter the floppy disk controller via 'gdisk' ioctl calls XX * to match the format of the disk. Sets a bunch of global variables. XX * Returns 0 on success, or 1 on failure. XX */ XX XX#include XX#include XX#include XX#include XX#include "msdos.h" XX XX#undef DUP_FAT XX XXextern int fd, dir_len, dir_start, clus_size, fat_len, num_clus; XXextern unsigned char *fatbuf; XXextern char *mcwd; XX XXint XXinit(mode) XXint mode; XX{ XX int code, buflen, intr(); XX unsigned char read_fat(), fat; XX char *getenv(), *fixmcwd(), *malloc(); XX long lseek(); XX void perror(), exit(), dismount(), move(), reset_dir(); XX struct gdctl gdbuf; XX XX if ((fd = open(FLOPPY, mode)) < 0) { XX perror("init: open"); XX exit(1); XX } XX /* get the disk controller info */ XX if (ioctl(fd, GDGETA, &gdbuf) < 0) { XX perror("init: ioctl"); XX dismount(); XX } XX /* assume some defaults */ XX gdbuf.params.cyls = 40; /* number of cylinders */ XX gdbuf.params.heads = 1; /* number of heads */ XX gdbuf.params.psectrk = 8; /* physical sectors per track */ XX gdbuf.params.pseccyl = 8; /* physical sectors per cylinder */ XX gdbuf.params.flags = 1; /* disk type flag */ XX gdbuf.params.step = 0; /* step rate for controller */ XX gdbuf.params.sectorsz = 512; /* sector size */ XX XX /* set the default parameters */ XX if (ioctl(fd, GDSETA, &gdbuf) < 0) { XX perror("init: ioctl"); XX dismount(); XX } XX /* read media signature (1st FAT) */ XX code = 0; XX fat = read_fat(); XX switch(fat) { XX case 0xfe: /* 40 trk, 8 sect, 1 side */ XX dir_start = 3; XX dir_len = 4; XX clus_size = 1; XX fat_len = 1; XX num_clus = 313; XX gdbuf.params.heads = 1; XX gdbuf.params.psectrk = 8; XX gdbuf.params.pseccyl = 8; XX break; XX case 0xff: /* 40 trk, 8 sect, 2 sides */ XX dir_start = 3; XX dir_len = 7; XX clus_size = 2; XX fat_len = 1; XX num_clus = 315; XX gdbuf.params.heads = 2; XX gdbuf.params.psectrk = 8; XX gdbuf.params.pseccyl = 16; XX break; XX case 0xfc: /* 40 trk, 9 sect, 1 side */ XX dir_start = 5; XX dir_len = 4; XX clus_size = 1; XX fat_len = 2; XX num_clus = 351; XX gdbuf.params.heads = 1; XX gdbuf.params.psectrk = 9; XX gdbuf.params.pseccyl = 9; XX break; XX case 0xfd: /* 40 trk, 9 sect, 2 sides */ XX dir_start = 5; XX dir_len = 7; XX clus_size = 2; XX fat_len = 2; XX num_clus = 354; XX gdbuf.params.heads = 2; XX gdbuf.params.psectrk = 9; XX gdbuf.params.pseccyl = 18; XX break; XX default: XX fprintf(stderr, "Unknown format '%02x'\n", fat); XX code = 1; XX break; XX } XX if (code) XX return(1); XX /* set the new-found parameters */ XX if (ioctl(fd, GDSETA, &gdbuf) < 0) { XX perror("init: ioctl"); XX dismount(); XX } XX XX buflen = fat_len * MSECSIZ; XX fatbuf = (unsigned char *) malloc((unsigned int) buflen); XX move(1); XX /* read the FAT sectors */ XX if (read(fd, (char *) fatbuf, buflen) != buflen) { XX perror("init: read"); XX exit(1); XX } XX /* set dir_chain to root directory */ XX reset_dir(); XX /* get Current Working Directory */ XX mcwd = fixmcwd(getenv("MCWD")); XX /* test it out.. */ XX if (subdir("")) { XX fprintf(stderr, "Environmental variable MCWD needs updating\n"); XX exit(1); XX } XX /* catch signals if open for write */ XX if (mode == 2) { XX signal(SIGINT, intr); XX signal(SIGTERM, intr); XX signal(SIGQUIT, intr); XX } XX return(0); XX} XX XX/* XX * Dismount the floppy. Useful only if one of the above ioctls fail XX * and leaves the drive light turned on. XX */ XX XXvoid XXdismount() XX{ XX struct gdctl gdbuf; XX void exit(); XX XX ioctl(fd, GDDISMNT, &gdbuf); XX exit(1); XX} XX XX/* XX * Move the read/write head to the next location. Tries to optimize XX * the movement by moving relative to current location. The argument XX * is a logical sector number. All errors are fatal. XX */ XX XXvoid XXmove(sector) XXint sector; XX{ XX long cur_loc, next, lseek(); XX void exit(), perror(); XX /* get current location */ XX if ((cur_loc = lseek(fd, 0L, 1)) < 0) { XX perror("move: lseek"); XX exit(1); XX } XX next = (long) (MSECSIZ * sector) - cur_loc; XX /* we're already there */ XX if (next == 0L) XX return; XX /* move to next location */ XX if (lseek(fd, next, 1) < 0) { XX perror("move: lseek"); XX exit(1); XX } XX return; XX} XX XX/* XX * Fix MCWD to be a proper directory name. Always has a leading separator. XX * Never has a trailing separator (unless it is the path itself). XX */ XX XXchar * XXfixmcwd(dirname) XXchar *dirname; XX{ XX char *s, *ans, *strcpy(), *strcat(), *malloc(); XX XX if (dirname == NULL) XX return("/"); XX XX ans = malloc((unsigned int) strlen(dirname)+2); XX XX /* add a leading separator */ XX if (*dirname != '/' && *dirname != '\\') { XX strcpy(ans, "/"); XX strcat(ans, dirname); XX } XX else XX strcpy(ans, dirname); XX /* translate to upper case */ XX for (s = ans; *s; ++s) { XX if (islower(*s)) XX *s = toupper(*s); XX } XX /* if separator alone */ XX if (strlen(ans) == 1) XX return(ans); XX /* zap the trailing separator */ XX s--; XX if (*s == '/' || *s == '\\') XX *s = '\0'; XX return(ans); XX} XX XX/* XX * Read the first byte of the FAT table. This code serves as a media XX * signature for the diskette. XX */ XX XXunsigned char XXread_fat() XX{ XX unsigned char buf[MSECSIZ]; XX /* move to boot sector */ XX if (lseek(fd, (long) MSECSIZ, 0) < 0) { XX perror("init: lseek"); XX exit(1); XX } XX /* read the first FAT sector */ XX if (read(fd, (char *) buf, MSECSIZ) != MSECSIZ) { XX fprintf(stderr, "Drive empty or latch not closed\n"); XX exit(1); XX } XX return(buf[0]); XX} XX XX/* XX * Do a graceful exit if the program is interupted. This will reduce XX * (but not eliminate) the risk of generating a corrupted disk on XX * a user abort. XX */ XX XXint XXintr() XX{ XX void writefat(); XX XX writefat(); XX close(fd); XX exit(1); XX} XX XX/* XX * Write the FAT table to the disk. Up to now the FAT manipulation has XX * been done in memory. All errors are fatal. (Might not be too smart XX * to wait till the end of the program to write the table. Oh well...) XX */ XX XXvoid XXwritefat() XX{ XX int buflen; XX void move(); XX XX move(1); XX buflen = fat_len * MSECSIZ; XX if (write(fd, (char *) fatbuf, buflen) != buflen) { XX perror("writefat: write"); XX exit(1); XX } XX#ifdef DUP_FAT XX /* the duplicate FAT table */ XX if (write(fd, (char *) fatbuf, buflen) != buflen) { XX perror("writefat: write"); XX exit(1); XX } XX#endif /* DUP_FAT */ XX return; XX} XSHAR_EOF Xif test 6148 -ne "`wc -c < 'init.c'`" Xthen X echo shar: "error transmitting 'init.c'" '(should have been 6148 characters)' Xfi Xfi Xecho shar: "extracting 'msdos.h'" '(558 characters)' Xif test -f 'msdos.h' Xthen X echo shar: "will not over-write existing file 'msdos.h'" Xelse Xsed 's/^X//' << \SHAR_EOF > 'msdos.h' XX/* XX * msdos common header file XX */ XX XX#define MSECSIZ 512 /* sector size */ XX#define MDIRSIZ 32 /* directory size */ XX#define CLSTRBUF 1024 /* largest cluster size */ XX#define MAX_PATH 128 XX XX#define FLOPPY "/dev/rfp020" XX XXstruct directory { XX unsigned char name[8]; /* file name */ XX unsigned char ext[3]; /* file extent */ XX unsigned char attr; /* attribute byte */ XX unsigned char reserved[10]; /* ?? */ XX unsigned char time[2]; XX unsigned char date[2]; XX unsigned char start[2]; /* starting cluster number */ XX unsigned char size[4]; /* size of the file */ XX}; XSHAR_EOF Xif test 558 -ne "`wc -c < 'msdos.h'`" Xthen X echo shar: "error transmitting 'msdos.h'" '(should have been 558 characters)' Xfi Xfi Xexit 0 X# End of shell archive SHAR_EOF if test 11391 -ne "`wc -c < 'Unixpc.shar'`" then echo shar: "error transmitting 'Unixpc.shar'" '(should have been 11391 characters)' fi fi echo shar: "extracting 'convdate.c'" '(2461 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(), convstamp() X */ X#include 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} SHAR_EOF if test 2461 -ne "`wc -c < 'convdate.c'`" then echo shar: "error transmitting 'convdate.c'" '(should have been 2461 characters)' fi fi echo shar: "extracting 'fixname.c'" '(1871 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 X#include 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} SHAR_EOF if test 1871 -ne "`wc -c < 'fixname.c'`" then echo shar: "error transmitting 'fixname.c'" '(should have been 1871 characters)' fi fi echo shar: "extracting 'getfat.c'" '(1365 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, 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 1365 -ne "`wc -c < 'getfat.c'`" then echo shar: "error transmitting 'getfat.c'" '(should have been 1365 characters)' fi fi echo shar: "extracting 'init.c'" '(6662 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 entry) X * and switch to the proper floppy disk device to match the format X * of the disk. Sets a bunch of global variables. Returns 0 on success, X * or 1 on failure. X */ X X#include X#include X#include X#include "msdos.h" X X#undef DUP_FAT X Xextern int fd, dir_len, dir_start, clus_size, fat_len, num_clus; Xextern unsigned char *fatbuf; Xextern char *mcwd; X Xint Xinit(mode) Xint mode; X{ X int code, buflen, intr(); X unsigned char read_fat(), fat; X char *getenv(), *fixmcwd(), *malloc(); X long lseek(); X void perror(), exit(), move(), reset_dir(); X X /* open the 'generic' floppy */ X if ((fd = open(FLOPPY, mode)) < 0) { X perror("init: open"); X exit(1); X } X /* read media signature (1st FAT) */ X if (!(fat = read_fat())) { X#ifdef FLP_80_15_2 X close(fd); X /* OK, try the 1.2M version */ X if ((fd = open(FLP_80_15_2, mode)) < 0) { X perror("init: open"); X exit(1); X } X fat = read_fat(); X#else /* FLP_80_15_2 */ X perror("init: read"); X exit(1); X#endif /* FLP_80_15_2 */ X } X /* what kind of disk do we have? */ X code = 0; X switch(fat) { X case 0: /* I hope errno hasn't been clobbered */ X perror("init: read"); X exit(1); X case 0xfe: X#ifndef FLP_40_8_1 X fprintf(stderr, "40 track, 8 sector, single sided: not supported\n"); X code = 1; X#else /* FLP_40_8_1 */ X dir_start = 3; X dir_len = 4; X clus_size = 1; X fat_len = 1; X num_clus = 313; X close(fd); X if ((fd = open(FLP_40_8_1, mode)) < 0) { X perror("init: open"); X return(1); X } X#endif /* FLP_40_8_1 */ X break; X case 0xff: X#ifndef FLP_40_8_2 X fprintf(stderr, "40 track, 8 sector, double sided: not supported\n"); X code = 1; X#else /* FLP_40_8_2 */ X dir_start = 3; X dir_len = 7; X clus_size = 2; X fat_len = 1; X num_clus = 315; X close(fd); X if ((fd = open(FLP_40_8_2, mode)) < 0) { X perror("init: open"); X return(1); X } X#endif /* FLP_40_8_2 */ X break; X case 0xfc: X#ifndef FLP_40_9_1 X fprintf(stderr, "40 track, 9 sector, single sided: not supported\n"); X code = 1; X#else /* FLP_40_9_1 */ X dir_start = 5; X dir_len = 4; X clus_size = 1; X fat_len = 2; X num_clus = 351; X close(fd); X if ((fd = open(FLP_40_9_1, mode)) < 0) { X perror("init: open"); X return(1); X } X#endif /* FLP_40_9_1 */ X break; X case 0xfd: X#ifndef FLP_40_9_2 X fprintf(stderr, "40 track, 9 sector, double sided: not supported\n"); X code = 1; X#else /* FLP_40_9_2 */ X dir_start = 5; X dir_len = 7; X clus_size = 2; X fat_len = 2; X num_clus = 354; X close(fd); X if ((fd = open(FLP_40_9_2, mode)) < 0) { X perror("init: open"); X return(1); X } X#endif /* FLP_40_9_2 */ X break; X case 0xf9: /* all 80 track disks */ X /* X * All 80 track disk use the same media signature, X * so you'll have to come up with some way of figuring X * out what the drive type is. If you've only got X * one 80 track drive, this is a moot point. X */ X#ifndef FLP_80_15_2 X fprintf(stderr, "80 track, 15 sector, double sided: not supported\n"); X code = 1; X#else /* FLP_80_15_2 */ X dir_start = 15; X dir_len = 14; X clus_size = 1; X fat_len = 7; X num_clus = 1193; X close(fd); X if ((fd = open(FLP_80_15_2, mode)) < 0) { X perror("init: open"); X return(1); X } X#endif /* FLP_80_15_2 */ 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 X buflen = fat_len * MSECSIZ; X fatbuf = (unsigned char *) malloc((unsigned int) buflen); X move(1); X /* read the FAT sectors */ X if (read(fd, (char *) 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 /* catch signals if open for write */ X if (mode == 2) { X signal(SIGINT, intr); X signal(SIGTERM, intr); X signal(SIGQUIT, intr); X } X return(0); 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 Xvoid 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, *ans, *malloc(), *strcpy(), *strcat(); X X if (dirname == NULL) X return("/"); X X ans = malloc((unsigned int) strlen(dirname)+2); X /* add a leading separator */ X if (*dirname != '/' && *dirname != '\\') { X strcpy(ans, "/"); X strcat(ans, dirname); X } X else X strcpy(ans, dirname); X /* translate to upper case */ X for (s = ans; *s; ++s) { X if (islower(*s)) X *s = toupper(*s); X } X /* if separator alone */ X if (strlen(ans) == 1) X return(ans); X /* zap the trailing separator */ X s--; X if (*s == '/' || *s == '\\') X *s = '\0'; X return(ans); X} X X/* X * 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 /* 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, (char *) buf, MSECSIZ) != MSECSIZ) X return('\0'); X X return(buf[0]); X} X X/* X * Do a graceful exit if the program is interupted. This will reduce X * (but not eliminate) the risk of generating a corrupted disk on X * a user abort. X */ X Xint Xintr() X{ X void writefat(); X X writefat(); X close(fd); X exit(1); X} X X/* X * Write the FAT table to the disk. Up to now the FAT manipulation has X * been done in memory. All errors are fatal. (Might not be too smart X * to wait till the end of the program to write the table. Oh well...) X */ X Xvoid Xwritefat() X{ X int buflen; X void move(); X X move(1); X buflen = fat_len * MSECSIZ; X if (write(fd, (char *) fatbuf, buflen) != buflen) { X perror("writefat: write"); X exit(1); X } X#ifdef DUP_FAT X /* the duplicate FAT table */ X if (write(fd, (char *) fatbuf, buflen) != buflen) { X perror("writefat: write"); X exit(1); X } X#endif /* DUP_FAT */ X return; X} SHAR_EOF if test 6662 -ne "`wc -c < 'init.c'`" then echo shar: "error transmitting 'init.c'" '(should have been 6662 characters)' fi fi echo shar: "extracting 'isdir.c'" '(1001 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 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; entryname[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} SHAR_EOF if test 1001 -ne "`wc -c < 'isdir.c'`" then echo shar: "error transmitting 'isdir.c'" '(should have been 1001 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 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} 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 'mcopy.c'" '(2823 characters)' if test -f 'mcopy.c' then echo shar: "will not over-write existing file 'mcopy.c'" else sed 's/^X//' << \SHAR_EOF > 'mcopy.c' 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 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 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 **) realloc((char *)argv, (argc+1) * sizeof(*argv)); X nargv[argc] = NULL; X X if (destination == MWRITE) { X nargv[0] = "mwrite"; X execvp("mwrite", nargv); X } X else { X nargv[0] = "mread"; X execvp("mread", nargv); X } X} SHAR_EOF if test 2823 -ne "`wc -c < 'mcopy.c'`" then echo shar: "error transmitting 'mcopy.c'" '(should have been 2823 characters)' fi fi exit 0 # End of shell archive