REPOST Mtools v1.6 (2 of 2)

egray at fthood.UUCP egray at fthood.UUCP
Mon Jul 17 01:13:00 AEST 1989


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

Emmet P. Gray				US Army, HQ III Corps & Fort Hood
...!uunet!uiucuxc!fthood!egray		Attn: AFZF-DE-ENV
fthood!egray at 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:
#	mdel.c
#	mdir.c
#	mkentry.c
#	mmd.c
#	mrd.c
#	mread.c
#	mren.c
#	msdos.h
#	mtype.c
#	mwrite.c
#	putfat.c
#	search.c
#	subdir.c
#	unixname.c
# This archive created: Thu Jul  6 08:08:53 1989
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'mdel.c'" '(2881 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 * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *mcwd;			/* the Current Working Directory */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int i, ismatch, entry, start, nogo, verbose, fargn;
X	char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
X	char *strncpy(), *getpath(), *pathname, ans[10];
X	void exit(), zapit(), writefat(), writedir(), free();
X	struct directory *dir, *search();
X
X	if (init(2)) {
X		fprintf(stderr, "mdel: Cannot initialize diskette\n");
X		exit(1);
X	}
X
X	if (argc < 2) {
X		fprintf(stderr, "Usage: mdel [-v] msdosfile [msdosfiles...]\n");
X		exit(1);
X	}
X	if (!strcmp(argv[1], "-v")) {
X		verbose = 1;
X		fargn = 2;
X	}
X	else {
X		verbose = 0;
X		fargn = 1;
X	}
X	for (i=fargn; i<argc; i++) {
X		filename = getname(argv[i]);
X		pathname = getpath(argv[i]);
X		if (subdir(pathname)) {
X			free(filename);
X			free(pathname);
X			continue;
X		}
X		nogo = 0;
X		ismatch = 0;
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X					/* if empty */
X			if (dir->name[0] == 0x0)
X				break;
X					/* if erased */
X			if (dir->name[0] == 0xe5)
X				continue;
X					/* if dir or volume lable */
X			if ((dir->attr & 0x10) || (dir->attr & 0x08))
X				continue;
X
X			strncpy(tname, (char *) dir->name, 8);
X			strncpy(text, (char *) dir->ext, 3);
X			tname[8] = '\0';
X			text[3] = '\0';
X
X			newfile = unixname(tname, text);
X					/* see it if matches the pattern */
X			if (match(newfile, filename)) {
X				if (verbose)
X					printf("Removing %s\n", newfile);
X				ismatch = 1;
X				if (dir->attr & 0x01) {
X					while (!nogo) {
X						printf("mdel: \"%s\" is read only, erase anyway (y/n) ? ", newfile);
X						gets(ans);
X						if (ans[0] == 'y' || ans[0] == 'Y')
X							break;
X						if (ans[0] == 'n' || ans[0] == 'N')
X							nogo = 1;
X					}
X					if (nogo) {
X						free(newfile);
X						continue;
X					}
X				}
X				start = dir->start[1]*0x100 + dir->start[0];
X				zapit(start);
X				dir->name[0] = 0xe5;
X				writedir(entry, dir);
X			}
X			free(newfile);
X		}
X		if (!ismatch)
X			fprintf(stderr, "mdel: File \"%s\" not found\n", filename);
X		free(filename);
X		free(pathname);
X	}
X					/* update the FAT sectors */
X	writefat();
X	close(fd);
X	exit(0);
X}
SHAR_EOF
if test 2881 -ne "`wc -c < 'mdel.c'`"
then
	echo shar: "error transmitting 'mdel.c'" '(should have been 2881 characters)'
fi
fi
echo shar: "extracting 'mdir.c'" '(4882 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 * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *mcwd;			/* the current working directory */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int i, entry, files, blocks, fargn, wide, faked;
X	long size;
X	char name[9], ext[4], *date, *time, *convdate(), *convtime();
X	char *strncpy(), newpath[MAX_PATH], *getname(), *getpath(), *pathname;
X	char *newfile, *filename, *unixname(), volume[12], *sep;
X	char *strcpy(), *strcat(), newname[MAX_PATH], *strncat();
X	void exit(), reset_dir(), free();
X	struct directory *dir, *search();
X
X	if (init(0)) {
X		fprintf(stderr, "mdir: Cannot initialize diskette\n");
X		exit(1);
X	}
X					/* find the volume label */
X	reset_dir();
X	volume[0] = '\0';
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == 0x0)
X			break;
X					/* if not volume label */
X		if (!(dir->attr & 0x08))
X			continue;
X
X		strncpy(volume, (char *) dir->name, 8);
X		volume[8] = '\0';
X		strncat(volume, (char *) dir->ext, 3);
X		volume[11] = '\0';
X		break;
X	}
X	if (volume[0] == '\0')
X		printf(" Volume in drive has no label\n");
X	else
X		printf(" Volume in drive is %s\n", volume);
X	fargn = 1;
X	wide = 0;
X					/* first argument number */
X	if (argc > 1) {
X		if (!strcmp(argv[1], "-w")) {
X			wide = 1;
X			fargn = 2;
X		}
X	}
X					/* fake an argument */
X	faked = 0;
X	if (argc == fargn) {
X		faked++;
X		argc++;
X	}
X	files = 0;
X	for (i=fargn; i<argc; i++) {
X		if (faked) {
X			filename = getname(".");
X			pathname = getpath(".");
X		}
X		else {
X			filename = getname(argv[i]);
X			pathname = getpath(argv[i]);
X		}
X					/* move to first guess subdirectory */
X					/* required by isdir() */
X		if (subdir(pathname)) {
X			free(filename);
X			free(pathname);
X			continue;
X		}
X					/* is filename really a subdirectory? */
X		if (isdir(filename)) {
X			strcpy(newpath, pathname);
X			if (strcmp(pathname,"/") && strcmp(pathname, "\\")) {
X				if (*pathname != '\0')
X					strcat(newpath, "/");
X			}
X			strcat(newpath, filename);
X					/* move to real subdirectory */
X			if (subdir(newpath)) {
X				free(filename);
X				free(pathname);
X				continue;
X			}
X			strcpy(newname, "*");
X		}
X		else {
X			strcpy(newpath, pathname);
X			strcpy(newname, filename);
X		}
X
X		if (*filename == '\0')
X			strcpy(newname, "*");
X
X		if (*newpath == '/' || *newpath == '\\')
X			printf(" Directory for %s\n\n", newpath);
X		else if (!strcmp(newpath, "."))
X			printf(" Directory for %s\n\n", mcwd);
X		else {
X			if (strlen(mcwd) == 1 || !strlen(newpath))
X				sep = "";
X			else
X				sep = "/";
X			printf(" Directory for %s%s%s\n\n", mcwd, sep, newpath);
X		}
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X					/* if empty */
X			if (dir->name[0] == 0x0)
X				break;
X					/* if erased */
X			if (dir->name[0] == 0xe5)
X				continue;
X					/* if a volume label */
X			if (dir->attr & 0x08)
X				continue;
X
X			strncpy(name, (char *) dir->name, 8);
X			strncpy(ext, (char *) dir->ext, 3);
X			name[8] = '\0';
X			ext[3] = '\0';
X
X			newfile = unixname(name, ext);
X			if (!match(newfile, newname)) {
X				free(newfile);
X				continue;
X			}
X			free(newfile);
X
X			files++;
X			if (wide && files != 1) {
X				if (!((files-1) % 5))
X					putchar('\n');
X			}
X			date = convdate(dir->date[1], dir->date[0]);
X			time = convtime(dir->time[1], dir->time[0]);
X			size = dir->size[2]*0x10000L + dir->size[1]*0x100 + dir->size[0];
X					/* is a subdirectory */
X			if (dir->attr & 0x10) {
X				if (wide)
X					printf("%-9.9s%-6.6s", name, ext);
X				else
X					printf("%8s %3s  <DIR>     %s  %s\n", name, ext, date, time);
X				continue;
X			}
X			if (wide)
X				printf("%-9.9s%-6.6s", name, ext);
X			else
X				printf("%8s %3s %8d   %s  %s\n", name, ext, size, date, time);
X		}
X		if (argc > 2)
X			putchar('\n');
X
X		free(filename);
X		free(pathname);
X	}
X
X	blocks = getfree() * MSECSIZ;
X	if (!files)
X		printf("File \"%s\" not found\n", newname);
X	else
X		printf("     %3d File(s)     %6ld bytes free\n", files, blocks);
X	close(fd);
X	exit(0);
X}
X
X/*
X * Get the amount of free space on the diskette
X */
X
Xint
Xgetfree()
X{
X	register int i, total;
X
X	total = 0;
X	for (i=2; i<num_clus+2; i++) {
X					/* if getfat returns zero */
X		if (!getfat(i))
X			total += clus_size;
X	}
X	return(total);
X}
SHAR_EOF
if test 4882 -ne "`wc -c < 'mdir.c'`"
then
	echo shar: "error transmitting 'mdir.c'" '(should have been 4882 characters)'
fi
fi
echo shar: "extracting 'mkentry.c'" '(2539 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 static directory structure.
X */
X
Xstruct directory *
Xmk_entry(filename, attr, fat, size, date)
Xchar *filename;
Xunsigned char attr;
Xint fat;
Xlong size, date;
X{
X	int i;
X	char *strncpy();
X	static struct directory ndir;
X	struct tm *now, *localtime();
X	unsigned char hour, min_hi, min_low, sec;
X	unsigned char year, month_hi, month_low, day;
X
X	now = localtime(&date);
X	strncpy((char *) ndir.name, filename, 8);
X	strncpy((char *) ndir.ext, filename+8, 3);
X	ndir.attr = attr;
X	for (i=0; i<10; i++)
X		ndir.reserved[i] = '\0';
X	hour = now->tm_hour << 3;
X	min_hi = now->tm_min >> 3;
X	min_low = now->tm_min << 5;
X	sec = now->tm_sec / 2;
X	ndir.time[1] = hour + min_hi;
X	ndir.time[0] = min_low + sec;
X	year = (now->tm_year - 80) << 1;
X	month_hi = (now->tm_mon+1) >> 3;
X	month_low = (now->tm_mon+1) << 5;
X	day = now->tm_mday;
X	ndir.date[1] = year + month_hi;
X	ndir.date[0] = month_low + day;
X	ndir.start[1] = fat / 0x100;
X	ndir.start[0] = fat % 0x100;
X	ndir.size[3] = 0;		/* can't be THAT large */
X	ndir.size[2] = size / 0x10000L;
X	ndir.size[1] = (size % 0x10000L) / 0x100;
X	ndir.size[0] = (size % 0x10000L) % 0x100;
X	return(&ndir);
X}
X
X/*
X * Make a subdirectory grow in length.  Only subdirectories (not root) 
X * may grow.  Returns a 0 on success or 1 on failure (disk full).
X */
X
Xint
Xgrow(fat)
Xint fat;
X{
X	int i, next, last, num, sector, buflen;
X	unsigned char tbuf[CLSTRBUF];
X	void perror(), exit(), move();
X
X	last = nextfat(0);
X	if (last == -1)
X		return(1);
X
X	while (1) {
X		next = getfat(fat);
X		if (next == -1) {
X			fprintf(stderr, "grow: FAT problem\n");
X			exit(1);
X		}
X					/* end of cluster chain */
X		if (next >= 0xff8)
X			break;
X		fat = next;
X	}
X					/* mark the end of the chain */
X	putfat(fat, (unsigned int) last);
X	putfat(last, 0xfff);
X					/* zero the buffer */
X	buflen = clus_size * MSECSIZ;
X	for (i=0; i<buflen; i++)
X		tbuf[i] = '\0';
X
X					/* write the cluster */
X	sector = (last - 2) * clus_size + dir_start + dir_len;
X	move(sector);
X	if (write(fd, (char *) tbuf, buflen) != buflen) {
X		perror("grow: write");
X		exit(1);
X	}
X					/* fix up the globals.... */
X	num = dir_entries / 16;
X	dir_entries += clus_size * 16;
X	dir_chain[num] = sector;
X	if (clus_size == 2)
X		dir_chain[num+1] = sector +1;
X	return(0);
X}
SHAR_EOF
if test 2539 -ne "`wc -c < 'mkentry.c'`"
then
	echo shar: "error transmitting 'mkentry.c'" '(should have been 2539 characters)'
fi
fi
echo shar: "extracting 'mmd.c'" '(4058 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 * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *mcwd;			/* the Current Working Directory */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int entry, slot, fat, dot, fargn, verbose;
X	char *filename, *newfile, *fixname(), *strncpy();
X	char *getpath(), *pathname, tname[9], text[4], *fixed, *unixname();
X	void exit(), putcluster(), writefat(), writedir(), free();
X	struct directory *dir, *search(), *mk_entry();
X	long time(), now;
X
X	if (init(2)) {
X		fprintf(stderr, "mmd: Cannot initialize diskette\n");
X		exit(1);
X	}
X
X	fargn = 1;
X	verbose = 0;
X	if (argc > 1) {
X		if (!strcmp(argv[1], "-v")) {
X			fargn = 2;
X			verbose = 1;
X		}
X	}
X					/* only 1 directory ! */
X	if (argc != fargn+1) {
X		fprintf(stderr, "Usage: mmd [-v] msdosdirectory\n");
X		exit(1);
X	}
X	fixed = fixname(argv[fargn], verbose);
X
X	strncpy(tname, fixed, 8);
X	strncpy(text, fixed+8, 3);
X	tname[8] = '\0';
X	text[3] = '\0';
X
X	filename = unixname(tname, text);
X	pathname = getpath(argv[fargn]);
X
X	if (subdir(pathname))
X		exit(1);
X					/* see if exists and get slot */
X	slot = -1;
X	dot = 0;
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == 0x0) {
X			if (slot < 0)
X				slot = entry;
X			break;
X		}
X					/* if erased */
X		if (dir->name[0] == 0xe5) {
X			if (slot < 0)
X				slot = entry;
X			continue;
X		}
X					/* if not a directory */
X		if (!(dir->attr & 0x10))
X			continue;
X
X		strncpy(tname, (char *) dir->name, 8);
X		strncpy(text, (char *) dir->ext, 3);
X		tname[8] = '\0';
X		text[3] = '\0';
X
X		newfile = unixname(tname, text);
X					/* save the 'dot' directory info */
X		if (!strcmp(".", newfile))
X			dot = dir->start[1]*0x100 + dir->start[0];
X
X		if (!strcmp(filename, newfile)) {
X			fprintf(stderr, "mmd: Directory \"%s\" already exists\n", filename);
X			exit(1);
X		}
X		free(newfile);
X	}
X					/* no '.' entry means root directory */
X	if (dot == 0 && slot < 0) {
X		fprintf(stderr, "mmd: No directory slots\n");
X		exit(1);
X	}
X					/* make the directory grow */
X	if (dot && slot < 0) {
X		if (grow(dot)) {
X			fprintf(stderr, "mmd: Disk full\n");
X			exit(1);
X		}
X					/* first slot in 'new' directory */
X		slot = entry;
X	}
X	if ((fat = nextfat(0)) == -1) {
X		fprintf(stderr, "mmd: Disk full\n");
X		exit(1);
X	}
X					/* make directory entry */
X	time(&now);
X	dir = mk_entry(fixed, 0x10, fat, 0L, now);
X	writedir(slot, dir);
X					/* write the cluster */
X	putfat(fat, 0xfff);
X	putcluster(fat, dot);
X					/* write FAT sectors */
X	writefat();
X	close(fd);
X	exit(0);
X}
X
X/*
X * Write a blank directory 'template' to the cluster starting at 'dot'.
X */
X
Xvoid
Xputcluster(dot, dot_dot)
Xint dot, dot_dot;
X{
X	int buflen, start;
X	static struct directory dirs[32];
X	struct directory *mk_entry();
X	void exit(), perror(), move();
X	long time(), now;
X
X	start = (dot - 2)*clus_size + dir_start + dir_len;
X	move(start);
X
X	buflen = clus_size * MSECSIZ;
X					/* make the '.' and '..' entries */	
X	time(&now);
X	dirs[0] = *mk_entry(".          ", 0x10, dot, 0L, now);
X	dirs[1] = *mk_entry("..         ", 0x10, dot_dot, 0L, now);
X
X	if (write(fd, (char *) &dirs[0], buflen) != buflen) {
X		perror("putcluster: write");
X		exit(1);
X	}
X	return;
X}
X
X/*
X * Returns next free cluster or -1 if none are available.
X */
X
Xint
Xnextfat(last)
Xint last;
X{
X	register int i;
X
X	for (i=last+1; i<num_clus+2; i++) {
X		if (!getfat(i))
X			return(i);
X	}
X	return(-1);
X}
SHAR_EOF
if test 4058 -ne "`wc -c < 'mmd.c'`"
then
	echo shar: "error transmitting 'mmd.c'" '(should have been 4058 characters)'
fi
fi
echo shar: "extracting 'mrd.c'" '(3277 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 * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *mcwd;			/* the Current Working Directory */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int ismatch, entry, start;
X	char *filename, *newfile, text[4], tname[9], *getname();
X	char *strncpy(), *pathname, *getpath(), *unixname();
X	void exit(), zapit(), writefat(), writedir(), free();
X	struct directory *dir, *search();
X
X	if (init(2)) {
X		fprintf(stderr, "mrd: Cannot initialize diskette\n");
X		exit(1);
X	}
X					/* only 1 directory ! */
X	if (argc != 2) {
X		fprintf(stderr, "Usage: mrd mdsosdirectory\n");
X		exit(1);
X	}
X
X	filename = getname(argv[1]);
X	pathname = getpath(argv[1]);
X	if (subdir(pathname))
X		exit(1);
X
X	ismatch = 0;
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == 0x0)
X			break;
X					/* if erased */
X		if (dir->name[0] == 0xe5)
X			continue;
X					/* if not dir */
X		if (!(dir->attr & 0x10))
X			continue;
X
X		strncpy(tname, (char *) dir->name, 8);
X		strncpy(text, (char *) dir->ext, 3);
X		tname[8] = '\0';
X		text[3] = '\0';
X
X		newfile = unixname(tname, text);
X		if (!strcmp(newfile, filename)) {
X			start = dir->start[1]*0x100 + dir->start[0];
X			if (!isempty(start)) {
X				fprintf(stderr, "mrd: Directory \"%s\" is not empty\n", filename);
X				exit(1);
X			}
X			if (!start) {
X				fprintf(stderr, "mrd: Can't remove root directory\n");
X				exit(1);
X			}
X			zapit(start);
X			dir->name[0] = 0xe5;
X			writedir(entry, dir);
X			ismatch = 1;
X		}
X		free(newfile);
X	}
X	if (!ismatch) {
X		fprintf(stderr, "mrd: Directory \"%s\" not found\n", filename);
X		exit(1);
X	}
X					/* update the FAT sectors */
X	writefat();
X	close(fd);
X	exit(0);
X}
X
X/*
X * See if directory is empty.  Returns 1 if empty, 0 if not.  Can't use
X * subdir() and search() as it would clobber the globals.
X */
X
Xint
Xisempty(fat)
Xint fat;
X{
X	register int i;
X	int next, buflen, sector;
X	unsigned char tbuf[CLSTRBUF];
X	void perror(), exit(), move();
X
X	while (1) {
X		sector = (fat-2)*clus_size + dir_start + dir_len;
X		move(sector);
X		buflen = clus_size * MSECSIZ;
X		if (read(fd, (char *) tbuf, buflen) != buflen) {
X			perror("isempty: read");
X			exit(1);
X		}
X					/* check first character of name */
X		for (i=0; i<MSECSIZ; i+=MDIRSIZ) {
X			if (tbuf[i] == '.')
X				continue;
X			if (tbuf[i] != 0x0 && tbuf[i] != 0xe5)
X				return(0);
X		}
X					/* get next cluster number */
X		next = getfat(fat);
X		if (next == -1) {
X			fprintf(stderr, "isempty: FAT problem\n");
X			exit(1);
X		}
X					/* end of cluster chain */
X		if (next >= 0xff8)
X			break;
X		fat = next;
X	}
X	return(1);
X}
SHAR_EOF
if test 3277 -ne "`wc -c < 'mrd.c'`"
then
	echo shar: "error transmitting 'mrd.c'" '(should have been 3277 characters)'
fi
fi
echo shar: "extracting 'mread.c'" '(5880 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 * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "msdos.h"
X
X#define LOWERCASE
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *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, single, c, oops, mod_time;
X	long mod_date, convstamp();
X	char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
X	char *strncpy(), *pathname, *getpath(), *target, tmp[MAX_PATH];
X	char *strcat(), *strcpy();
X	void perror(), exit(), free();
X	struct directory *dir, *search();
X	struct stat stbuf;
X
X	if (init(0)) {
X		fprintf(stderr, "mread: Cannot initialize diskette\n");
X		exit(1);
X	}
X					/* get command line options */
X	oops = 0;
X	mod_time = 0;
X	while ((c = getopt(argc, argv, "tnm")) != EOF) {
X		switch(c) {
X			case 't':
X				textmode = 1;
X				break;
X			case 'n':
X				nowarn = 1;
X				break;
X			case 'm':
X				mod_time = 1;
X				break;
X			default:
X				oops = 1;
X				break;
X		}
X	}
X
X	if (oops || (argc - optind) < 2) {
X		fprintf(stderr, "Usage: mread [-tn] msdosfile unixfile\n");
X		fprintf(stderr, "    or mread [-tn] msdosfile [msdosfiles...] unixdirectory\n");
X		exit(1);
X	}
X					/* only 1 file to copy... */
X	single = 1;
X	target = argv[argc-1];
X					/* ...unless last arg is a directory */
X	if (!stat(target, &stbuf)) {
X		if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
X			single = 0;	
X	}
X					/* too many arguments */
X	if (single && (argc - optind) != 2) {
X		fprintf(stderr, "mread: too many arguments or destination directory omitted\n");
X		exit(1);
X	}
X
X	for (i=optind; i<argc-1; i++) {
X		filename = getname(argv[i]);
X		pathname = getpath(argv[i]);
X		if (subdir(pathname)) {
X			free(filename);
X			free(pathname);
X			continue;
X		}
X
X		ismatch = 0;
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X					/* if empty */
X			if (dir->name[0] == 0x0)
X				break;
X					/* if erased */
X			if (dir->name[0] == 0xe5)
X				continue;
X					/* if dir or volume lable */
X			if ((dir->attr & 0x10) || (dir->attr & 0x08))
X				continue;
X
X			strncpy(tname, (char *) dir->name, 8);
X			strncpy(text, (char *) dir->ext, 3);
X			tname[8] = '\0';
X			text[3] = '\0';
X
X			newfile = unixname(tname, text);
X			fat = dir->start[1]*0x100 + dir->start[0];
X			size = dir->size[2]*0x10000L + dir->size[1]*0x100 + dir->size[0];
X			if (mod_time)
X				mod_date = convstamp(dir->time, dir->date);
X			else
X				mod_date = 0L;
X
X					/* if single file */
X			if (single) {
X				if (!strcmp(newfile, filename)) {
X					readit(fat, target, mod_date);
X					ismatch = 1;
X					break;
X				}
X			}
X					/* if multiple files */
X			else {
X				if (match(newfile, filename)) {
X					printf("Copying %s\n", newfile);
X					strcpy(tmp, target);
X					strcat(tmp, "/");
X					strcat(tmp, newfile);
X					readit(fat, tmp, mod_date);
X					ismatch = 1;
X				}
X			}
X			free(newfile);
X		}
X		if (!ismatch)
X			fprintf(stderr, "mread: File \"%s\" not found\n", filename);
X		free(filename);
X		free(pathname);
X	}
X	close(fd);
X	exit(0);
X}
X
X/*
X * Decode the FAT chain given the begining FAT entry, open the named Unix
X * file for write.
X */
X
Xint
Xreadit(fat, target, mod_date)
Xint fat;
Xchar *target;
Xlong mod_date;
X{
X	char ans[10];
X	void exit(), getcluster();
X	FILE *fp;
X	struct stat stbuf;
X	struct utimbuf {
X		time_t actime;
X		time_t modtime;
X	} utbuf;
X
X#ifdef LOWERCASE
X	char *c;
X	c = target;
X	while(*c) {
X		if (isupper(*c))
X			*c = tolower(*c);
X		c++;
X	}
X#endif /* LOWERCASE */
X
X	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					/* sanity checking */
X			if (!stat(target, &stbuf)) {
X				if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
X					fprintf(stderr, "mread: \"%s\" is not a regular file\n", target);
X					return;
X				}
X			}
X		}
X	}
X
X	if (!(fp = fopen(target, "w"))) {
X		fprintf(stderr, "mread: Can't open \"%s\" for write\n", target);
X		return;
X	}
X
X	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					/* preserve mod times ? */
X	if (mod_date != 0L) {
X		utbuf.actime = mod_date;
X		utbuf.modtime = mod_date;
X		utime(target, &utbuf);
X	}
X	return;
X}
X
X/*
X * Read the named cluster, write to the Unix file descriptor.
X */
X
Xvoid
Xgetcluster(num, fp)
Xint num;
XFILE *fp;
X{
X	register int i;
X	int buflen, start;
X	unsigned char buf[CLSTRBUF];
X	void exit(), perror(), move();
X
X	start = (num - 2)*clus_size + dir_start + dir_len;
X	move(start);
X
X	buflen = clus_size * MSECSIZ;
X	if (read(fd, (char *) buf, buflen) != buflen) {
X		perror("getcluster: read");
X		exit(1);
X	}
X					/* stop at size not EOF marker */
X	for (i=0; i<buflen; i++) {
X		current++;
X		if (current > size) 
X			break;
X		if (textmode && buf[i] == '\r')
X			continue;
X		if (textmode && current == size && buf[i] == 0x1a)
X			continue;
X		fputc((char) buf[i], fp);
X	}
X	return;
X}
SHAR_EOF
if test 5880 -ne "`wc -c < 'mread.c'`"
then
	echo shar: "error transmitting 'mread.c'" '(should have been 5880 characters)'
fi
fi
echo shar: "extracting 'mren.c'" '(3153 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 * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *mcwd;			/* the Current Working Directory */
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int entry, ismatch, nogo, fargn, verbose, got_it;
X	char *filename, *newfile, *fixname(), *strncpy(), *unixname();
X	char *getpath(), *pathname, tname[9], text[4], *getname(), *target;
X	char *new, ans[10], *temp, *strcpy();
X	void exit(), writedir(), free();
X	struct directory *dir, *search();
X
X	if (init(2)) {
X		fprintf(stderr, "mren: Cannot initialize diskette\n");
X		exit(1);
X	}
X	fargn = 1;
X	verbose = 0;
X	if (argc > 1) {
X		if (!strcmp(argv[1], "-v")) {
X			fargn = 2;
X			verbose = 1;
X		}
X	}
X	if (argc != fargn+2) {
X		fprintf(stderr, "Usage: mren [-v] sourcefile targetfile\n");
X		exit(1);
X	}
X	filename = getname(argv[fargn]);
X	pathname = getpath(argv[fargn]);
X	if (subdir(pathname))
X		exit(1);
X
X	temp = getname(argv[fargn+1]);
X	target = fixname(argv[fargn+1], verbose);
X
X	strncpy(tname, target, 8);
X	strncpy(text, target+8, 3);
X	tname[8] = '\0';
X	text[3] = '\0';
X
X	new = unixname(tname, text);
X	nogo = 0;
X					/* the name supplied may be altered */
X	if (strcmp(temp, new) && verbose) {
X		while (!nogo) {
X			printf("Do you accept \"%s\" as the new file name (y/n) ? ", new);
X			gets(ans);
X			if (ans[0] == 'y' || ans[0] == 'Y')
X				break;
X			if (ans[0] == 'n' || ans[0] == 'N')
X				nogo = 1;
X		}
X	}
X	if (nogo)
X		exit(0);
X					/* see if exists and do it */
X	ismatch = 0;
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == 0x0)
X			break;
X					/* if erased */
X		if (dir->name[0] == 0xe5)
X			continue;
X					/* if volume label */
X		if (dir->attr == 0x08)
X			continue;
X					/* you may rename a directory */
X		strncpy(tname, (char *) dir->name, 8);
X		strncpy(text, (char *) dir->ext, 3);
X		tname[8] = '\0';
X		text[3] = '\0';
X
X		newfile = unixname(tname, text);
X
X					/* if the new name already exists */
X		if (!strcmp(new, newfile)) {
X			fprintf(stderr, "mren: File \"%s\" already exists\n", new);
X			exit(1);
X		}
X					/* if the old name exists */
X		if (!strcmp(filename, newfile)) {
X			ismatch = 1;
X			got_it = entry;
X		}
X		free(newfile);
X	}
X	if (!ismatch) {
X		fprintf(stderr, "mren: File \"%s\" not found\n", filename);
X		exit(1);
X	}
X					/* so go ahead and do it */
X	dir = search(got_it);
X	strncpy((char *) dir->name, target, 8);
X	strncpy((char *) dir->ext, target+8, 3);
X	writedir(got_it, dir);
X
X	close(fd);
X	exit(0);
X}
SHAR_EOF
if test 3153 -ne "`wc -c < 'mren.c'`"
then
	echo shar: "error transmitting 'mren.c'" '(should have been 3153 characters)'
fi
fi
echo shar: "extracting 'msdos.h'" '(868 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 MAX_PATH 128
X
X/*
X * If your device driver does not support any of the following formats,
X * then leave those devices undefined.
X */
X
X#define	FLOPPY		"/dev/rflp"
X#define	FLP_40_8_1	"/dev/rflp40t8s1s"
X#define	FLP_40_8_2	"/dev/rflp40t8s2s"
X#define	FLP_40_9_1	"/dev/rflp40t9s1s"
X#define	FLP_40_9_2	"/dev/rflp40t9s2s"
X#define FLP_80_15_2	"/dev/rflp80t15s2s"
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 868 -ne "`wc -c < 'msdos.h'`"
then
	echo shar: "error transmitting 'msdos.h'" '(should have been 868 characters)'
fi
fi
echo shar: "extracting 'mtype.c'" '(3748 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 * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xint fd;				/* the file descriptor for the floppy */
Xint dir_start;			/* starting sector for directory */
Xint dir_len;			/* length of directory (in sectors) */
Xint dir_entries;		/* number of directory entries */
Xint dir_chain[25];		/* chain of sectors in directory */
Xint clus_size;			/* cluster size (in sectors) */
Xint fat_len;			/* length of FAT table (in sectors) */
Xint num_clus;			/* number of available clusters */
Xunsigned char *fatbuf;		/* the File Allocation Table */
Xchar *mcwd;			/* the Current Working Directory */
X
Xlong size;
Xlong current;
Xint stripmode = 0;
Xint textmode = 0;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	extern int optind;
X	extern char *optarg;
X	int fat, i, ismatch, entry, c, oops;
X	char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
X	char *strncpy(), *pathname, *getpath();
X	void exit(), readit(), free();
X	struct directory *dir, *search();
X
X	if (init(0)) {
X		fprintf(stderr, "mtype: Cannot initialize diskette\n");
X		exit(1);
X	}
X					/* get command line options */
X	oops = 0;
X	while ((c = getopt(argc, argv, "st")) != EOF) {
X		switch(c) {
X			case 's':
X				stripmode = 1;
X				break;
X			case 't':
X				textmode = 1;
X				break;
X			default:
X				oops = 1;
X				break;
X		}
X	}
X
X	if (oops || (argc - optind) < 1) {
X		fprintf(stderr, "Usage: mtype [-st] msdosfile [msdosfiles...]\n");
X		exit(1);
X	}
X
X	for (i=optind; i<argc; i++) {
X		filename = getname(argv[i]);
X		pathname = getpath(argv[i]);
X		if (subdir(pathname)) {
X			free(filename);
X			free(pathname);
X			continue;
X		}
X		ismatch = 0;
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X					/* if empty */
X			if (dir->name[0] == 0x0)
X				break;
X					/* if erased */
X			if (dir->name[0] == 0xe5)
X				continue;
X					/* if dir or volume label */
X			if ((dir->attr & 0x10) || (dir->attr & 0x08))
X				continue;
X
X			strncpy(tname, (char *) dir->name, 8);
X			strncpy(text, (char *) dir->ext, 3);
X			tname[8] = '\0';
X			text[3] = '\0';
X
X			newfile = unixname(tname, text);
X					/* see it if matches the pattern */
X			if (match(newfile, filename)) {
X				fat = dir->start[1]*0x100 + dir->start[0];
X				size = dir->size[2]*0x10000L + dir->size[1]*0x100 + dir->size[0];
X				readit(fat);
X				ismatch = 1;
X			}
X			free(newfile);
X		}
X		if (!ismatch)
X			fprintf(stderr, "mtype: File \"%s\" not found\n", filename);
X		free(filename);
X		free(pathname);
X	}
X	close(fd);
X	exit(0);
X}
X
X/*
X * Decode the FAT chain given the begining FAT entry.
X */
X
Xvoid
Xreadit(fat)
Xint fat;
X{
X	void getcluster();
X
X	current = 0L;
X	while (1) {
X		getcluster(fat);
X					/* get next cluster number */
X		fat = getfat(fat);
X		if (fat == -1) {
X			fprintf(stderr, "mtype: FAT problem\n");
X			exit(1);
X		}
X					/* end of cluster chain */
X		if (fat >= 0xff8)
X			break;
X	}
X	return;
X}
X
X/*
X * Read the named cluster, output to the stdout.
X */
X
Xvoid
Xgetcluster(num)
Xint num;
X{
X	register int i;
X	int buflen, start;
X	unsigned char buf[CLSTRBUF];
X	void exit(), perror(), move();
X
X	start = (num - 2)*clus_size + dir_start + dir_len;
X	move(start);
X
X	buflen = clus_size * MSECSIZ;
X	if (read(fd, (char *) buf, buflen) != buflen) {
X		perror("getcluster: read");
X		exit(1);
X	}
X					/* stop at size not EOF marker */
X	for (i=0; i<buflen; i++) {
X		current++;
X		if (current > size) 
X			break;
X		if (textmode && buf[i] == '\r')
X			continue;
X		if (textmode && current == size && buf[i] == 0x1a)
X			continue;
X		if (stripmode)
X			putchar(buf[i] & 0x7f);
X		else
X			putchar(buf[i]);
X	}
X	return;
X}
SHAR_EOF
if test 3748 -ne "`wc -c < 'mtype.c'`"
then
	echo shar: "error transmitting 'mtype.c'" '(should have been 3748 characters)'
fi
fi
echo shar: "extracting 'mwrite.c'" '(8266 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 * ...!uunet!uiucuxc!fthood!egray	Attn: AFZF-DE-ENV
X * 					Directorate of Engineering & Housing
X * 					Environmental Management Office
X * 					Fort Hood, TX 76544-5057
X */
X
X#include <stdio.h>
X#include <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;
Xint need_nl = 0;
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, single;
X	int root, c, oops, verbose, first, mod_time;
X	char *filename, *newfile, tname[9], text[4], *fixname(), *getname();
X	char *unixname(), ans[10], *strncpy(), *pathname, *getpath(), *fixed;
X	char tmp[MAX_PATH], *target, *strcat(), *strcpy();
X	void exit(), zapit(), writefat(), writedir(), free();
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	verbose = 0;
X	mod_time = 0;
X	while ((c = getopt(argc, argv, "tnvm")) != EOF) {
X		switch(c) {
X			case 't':
X				textmode = 1;
X				break;
X			case 'n':
X				nowarn = 1;
X				break;
X			case 'v':
X				verbose = 1;
X				break;
X			case 'm':
X				mod_time = 1;
X				break;
X			default:
X				oops = 1;
X				break;
X		}
X	}
X
X	if (oops || (argc - optind) < 2) {
X		fprintf(stderr, "Usage: mwrite [-tnv] unixfile msdosfile\n");
X		fprintf(stderr, "    or mwrite [-tnv] unixfile [unixfiles...] msdosdirectory\n");
X		exit(1);
X	}
X	root = 0;
X	if (!strcmp(argv[argc-1], "/") || !strcmp(argv[argc-1], "\\"))
X		root = 1;
X
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			strcpy(tmp, filename);
X		}
X		else {
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					/* too many arguments */
X		if ((argc - optind) != 2) {
X			fprintf(stderr, "mwrite: too many arguments or destination directory omitted\n");
X			exit(1);
X		}
X	}
X
X	for (i=optind; i<argc-1; i++) {
X		if (single)
X			fixed = fixname(argv[argc-1], verbose);
X		else
X			fixed = fixname(argv[i], verbose);
X
X		strncpy(tname, fixed, 8);
X		strncpy(text, fixed+8, 3);
X		tname[8] = '\0';
X		text[3] = '\0';
X
X		target = unixname(tname, text);
X					/* see if exists and get slot */
X		ismatch = 0;
X		slot = -1;
X		dot = 0;
X		nogo = 0;
X		first = 1;
X		for (entry=0; entry<dir_entries; entry++) {
X			dir = search(entry);
X					/* save the '.' entry info */
X			if (first) {
X				first = 0;
X				if ((dir->attr & 0x10) && dir->name[0] == '.') {
X					dot = dir->start[1]*0x100 + dir->start[0];
X					continue;
X				}
X			}
X					/* is empty */
X			if (dir->name[0] == 0x0) {
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					/* is dir or volume lable */
X			if ((dir->attr & 0x10) || (dir->attr & 0x08))
X				continue;
X
X			strncpy(tname, (char *) dir->name, 8);
X			strncpy(text, (char *) dir->ext, 3);
X			tname[8] = '\0';
X			text[3] = '\0';
X
X			newfile = unixname(tname, text);
X					/* if file exists, delete it first */
X			if (!strcmp(target, 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) ? ", target);
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			free(newfile);
X			if (ismatch)
X				break;
X		}
X		if (nogo) {		/* chickened out... */
X			free(fixed);
X			free(target);
X			continue;
X		}
X					/* no '.' entry means root directory */
X		if (dot == 0 && slot < 0) {
X			fprintf(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		if (!single)
X			printf("Copying %s\n", target);
X					/* write the file */
X		if (dir = writeit(fixed, argv[i], verbose, mod_time))
X			writedir(slot, dir);
X
X		free(fixed);
X		free(target);
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 or NULL on error.
X */
X
Xstruct directory *
Xwriteit(fixed, path, verbose, mod_time)
Xchar *fixed, *path;
Xint verbose, mod_time;
X{
X	FILE *fp;
X	int fat, firstfat, oldfat;
X	long size, time(), now;
X	struct directory *dir, *mk_entry();
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
X	if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
X		if (verbose)
X			fprintf(stderr, "mwrite: \"%s\" is a directory\n", path);
X		return(NULL);
X	}
X
X	if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
X		fprintf(stderr, "mwrite: \"%s\" is not a regular file\n", path);
X		return(NULL);
X	}
X	filesize = stbuf.st_size;
X					/* preserve mod time? */
X	if (mod_time)
X		now = stbuf.st_mtime;
X	else
X		time(&now);
X
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			zapit(firstfat);
X			full = 1;
X			return(NULL);
X		}
X		putfat(oldfat, (unsigned int) fat);
X	}
X	fclose(fp);
X	dir = mk_entry(fixed, 0x20, firstfat, size, now);
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	int buflen, c, start, current;
X	unsigned char tbuf[CLSTRBUF];
X	void exit(), perror(), move();
X
X	start = (num - 2)*clus_size + dir_start + dir_len;
X	move(start);
X
X	buflen = clus_size * MSECSIZ;
X					/* '\n' to '\r\n' translation */
X	if (textmode) {
X		current = 0;
X		if (need_nl) {
X			tbuf[current++] = '\n';
X			need_nl = 0;
X		}
X		while (current < buflen) {
X			if ((c = fgetc(fp)) == EOF) {
X					/* put a file EOF marker */
X				tbuf[current++] = 0x1a;
X					/* make the file appear larger */
X				filesize++;
X				break;
X			}
X			if (c == '\n') {
X				tbuf[current++] = '\r';
X					/* make the file appear larger */
X				filesize++;
X					/* if at the end of the buffer */
X				if (current == buflen) {
X					need_nl++;
X					break;
X				}
X			}
X			tbuf[current++] = c;
X		}
X	}
X	else {
X		if ((current = fread((char *) tbuf, sizeof(*tbuf), buflen, fp)) < 0) {
X			perror("putcluster: fread");
X			exit(1);
X		}
X	}
X	
X	if (write(fd, (char *) 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	register int i;
X
X	for (i=last+1; i<num_clus+2; i++) {
X		if (!getfat(i))
X			return(i);
X	}
X	return(-1);
X
X}
SHAR_EOF
if test 8266 -ne "`wc -c < 'mwrite.c'`"
then
	echo shar: "error transmitting 'mwrite.c'" '(should have been 8266 characters)'
fi
fi
echo shar: "extracting 'putfat.c'" '(2561 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()
X */
X
X#include <stdio.h>
X#include "msdos.h"
X
Xextern int fd, fat_len, dir_chain[25];
Xextern unsigned char *fatbuf;
X
X/*
X * Puts a code into the FAT table.  Is the opposite of getfat().  No
X * sanity checking is done on the code.  Returns a 1 on error.
X */
X
Xint
Xputfat(num, code)
Xint num;
Xunsigned int code;
X{
X/*
X *	|    byte n     |   byte n+1    |   byte n+2    |
X *	|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|
X *	| | | | | | | | | | | | | | | | | | | | | | | | |
X *	|  n.0  |  n.5  | n+1.0 | n+1.5 | n+2.0 | n+2.5 |
X *	    \_____  \____   \______/________/_____   /
X *	      ____\______\________/   _____/  ____\_/
X *	     /     \      \          /       /     \
X *	| n+1.5 |  n.0  |  n.5  | n+2.0 | n+2.5 | n+1.0 |
X *	|      FAT entry k      |    FAT entry k+1      |
X */
X	int start;
X					/* which bytes contain the entry */
X	start = num * 3 / 2;
X	if (start < 0 || start+1 > (fat_len * MSECSIZ))
X		return(1);
X					/* (odd) not on byte boundary */
X	if (num % 2) {
X		*(fatbuf+start) = (*(fatbuf+start) & 0x0f) + ((code << 4) & 0xf0);
X		*(fatbuf+start+1) = (code >> 4) & 0xff;
X	}
X					/* (even) on byte boundary */
X	else {
X		*(fatbuf+start) = code & 0xff;
X		*(fatbuf+start+1) = (*(fatbuf+start+1) & 0xf0) + ((code >> 8) & 0x0f);
X	}
X	return(0);
X}
X
X/*
X * Write a directory entry.  The first argument is the directory entry
X * number to write to.  The second is a pointer to the directory itself.
X * All errors are fatal.
X */
X
Xvoid
Xwritedir(num, dir)
Xint num;
Xstruct directory *dir;
X{
X	int skip, entry;
X	struct directory dirs[16];
X	void exit(), perror(), move();
X					/* which sector */
X	skip = dir_chain[num / 16];
X
X	move(skip);
X					/* read the sector */
X	if (read(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) {
X		perror("writedir: read");
X		exit(1);
X	}
X					/* which entry in sector */
X	entry = num % 16;
X					/* copy the structure */
X	dirs[entry] = *dir;
X	move(skip);
X					/* write the sector */
X	if (write(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) {
X		perror("writedir: write");
X		exit(1);
X	}
X	return;
X}
X
X/*
X * Remove a string of FAT entries (delete the file).  The argument is
X * the beginning of the string.  Does not consider the file length, so
X * if FAT is corrupted, watch out!  All errors are fatal.
X */
X
Xvoid
Xzapit(fat)
Xint fat;
X{
X	int next;
X
X	while (1) {
X					/* get next cluster number */
X		next = getfat(fat);
X					/* mark current cluster as empty */
X		if (putfat(fat, 0) || next == -1) {
X			fprintf(stderr, "zapit: FAT problem\n");
X			exit(1);
X		}
X		if (next >= 0xff8)
X			break;
X		fat = next;
X	}
X	return;
X}
SHAR_EOF
if test 2561 -ne "`wc -c < 'putfat.c'`"
then
	echo shar: "error transmitting 'putfat.c'" '(should have been 2561 characters)'
fi
fi
echo shar: "extracting 'search.c'" '(1083 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	static int last;
X	static struct directory dirs[16];
X	void exit(), perror(), move();
X
X					/* first call disables optimzation */
X	if (num == 0)
X		last = 0;
X					/* which sector */
X	skip = dir_chain[num / 16];
X					/* don't read it if same sector */
X	if (skip != last) {
X		move(skip);
X					/* read the sector */
X		if (read(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) {
X			perror("mread: read");
X			exit(1);
X		}
X	}
X	last = skip;
X					/* which entry in sector */
X	entry = num % 16;
X	return(&dirs[entry]);
X}
SHAR_EOF
if test 1083 -ne "`wc -c < 'search.c'`"
then
	echo shar: "error transmitting 'search.c'" '(should have been 1083 characters)'
fi
fi
echo shar: "extracting 'subdir.c'" '(3775 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[MAX_PATH];
X
X/*
X * Parse the path names of a sub directory.  Both '/' and '\' are
X * valid separators.  However, the use of '\' will force the operator
X * to use quotes in the command line to protect '\' from the shell.
X * Returns 1 on error.  Attempts to optimize by remembering the last
X * path it parsed
X */
X
Xint
Xsubdir(name)
Xchar *name;
X{
X	char *s, *tmp, tbuf[MAX_PATH], *path, *strcpy(), *strcat();
X	int code;
X	void reset_dir();
X					/* if full pathname */
X	if (*name == '/' || *name == '\\')
X		strcpy(tbuf, name);
X					/* if relative to MCWD */
X	else {
X		if (!strlen(name))
X			strcpy(tbuf, mcwd);
X		else {
X			strcpy(tbuf, mcwd);
X			strcat(tbuf, "/");
X			strcat(tbuf, name);
X		}
X	}
X					/* if paths are same, do nothing */
X	if (!strcmp(tbuf, lastpath))
X		return(0);
X					/* not recursive, start at root */
X	reset_dir();
X	strcpy(lastpath, tbuf);
X					/* zap the leading separator */
X	tmp = tbuf;
X	if (*tmp == '\\' || *tmp == '/')
X		tmp++;
X	for (s = tmp; *s; ++s) {
X		if (*s == '\\' || *s == '/') {
X			path = tmp;
X			*s = '\0';
X			if (getdir(path))
X				return(1);
X			tmp = s+1;
X		}
X	}
X	code = getdir(tmp);
X	return(code);
X}
X
X/*
X * Find the directory and get the starting cluster.  A null directory
X * is ok.  Returns a 1 on error.
X */
X
Xint
Xgetdir(path)
Xchar *path;
X{
X	int entry, start;
X	char *newname, *unixname(), *strncpy(), name[9], ext[4];
X	struct directory *dir, *search();
X	void reset_dir(), free();
X					/* nothing required */
X	if (*path == '\0')
X		return(0);
X
X	for (entry=0; entry<dir_entries; entry++) {
X		dir = search(entry);
X					/* if empty */
X		if (dir->name[0] == 0x0)
X			break;
X					/* if erased */
X		if (dir->name[0] == 0xe5)
X			continue;
X					/* skip if not a directory */
X		if (!(dir->attr & 0x10))
X			continue;
X
X		strncpy(name, (char *) dir->name, 8);
X		strncpy(ext, (char *) dir->ext, 3);
X		name[8] = '\0';
X		ext[3] = '\0';
X
X		newname = unixname(name, ext);
X		if (!strcmp(newname, path)) {
X			start = dir->start[1]*0x100 + dir->start[0];
X					/* if '..' pointing to root */
X			if (!start && !strcmp(path, "..")) {
X				reset_dir();
X				return(0);
X			}
X					/* fill in the directory chain */
X			dir_entries = get_chain(start) * 16;
X			return(0);
X		}
X		free(newname);
X	}
X					/* if '.' or '..', must be root */
X	if (!strcmp(path, ".") || !strcmp(path, "..")) {
X		reset_dir();
X		return(0);
X	}
X	fprintf(stderr, "Path component \"%s\" is not a directory\n", path);
X	return(1);
X}
X
X/*
X * Fill in the global variable dir_chain.  Argument is the starting
X * cluster number.  Info, in this variable is used by search() to 
X * scan a directory.  An arbitrary limit of 25 sectors is placed, this
X * equates to 400 entries.  Returns the number of sectors in the chain.
X */
X
Xint
Xget_chain(num)				/* fill the directory chain */
Xint num;
X{
X	int i, next;
X	void exit();
X
X	i = 0;
X	while (1) {
X		dir_chain[i] = (num - 2)*clus_size + dir_start + dir_len;
X					/* sectors, not clusters! */
X		if (clus_size == 2) {
X			dir_chain[i+1] = dir_chain[i] + 1;
X			i++;
X		}
X		i++;
X		if (i >= 25) {
X			fprintf(stderr, "get_chain: directory too large\n");
X			exit(1);
X		}
X					/* get next cluster number */
X		next = getfat(num);
X		if (next == -1) {
X			fprintf(stderr, "get_chain: FAT problem\n");
X			exit(1);
X		}
X					/* end of cluster chain */
X		if (next >= 0xff8) {
X			break;
X		}
X		num = next;
X	}
X	return(i);
X}
X
X/* 
X * Reset the global variable dir_chain to the root directory.
X */
X
Xvoid
Xreset_dir()
X{
X	register int i;
X
X	for (i=0; i<dir_len; i++)
X		dir_chain[i] = dir_start + i;
X	dir_entries = dir_len * 16;
X					/* disable subdir() optimization */
X	lastpath[0] = '\0';
X	return;
X}
SHAR_EOF
if test 3775 -ne "`wc -c < 'subdir.c'`"
then
	echo shar: "error transmitting 'subdir.c'" '(should have been 3775 characters)'
fi
fi
echo shar: "extracting 'unixname.c'" '(2215 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#include "msdos.h"
X
X/*
X * Get rid of spaces in a MSDOS 'raw' name (one that has come from the
X * directory structure) so that it can be used for regular expression
X * matching with a unix file name.  Also used to 'unfix' a name that has
X * been altered by fixname().  Returns a pointer to the unix style name.
X */
X
Xchar *
Xunixname(name, ext)
Xchar *name, *ext;
X{
X	char *s, tname[9], text[4], *strcpy(), *strcat(), *strchr();
X	char *ans, *malloc();
X
X	strcpy(tname, name);
X	if (s = strchr(tname, ' '))
X		*s = '\0';
X
X	strcpy(text, ext);
X	if (s = strchr(text, ' '))
X		*s = '\0';
X
X	ans = malloc(13);
X
X	if (*text) {
X		strcpy(ans, tname);
X		strcat(ans, ".");
X		strcat(ans, text);
X	}
X	else
X		strcpy(ans, tname);
X	return(ans);
X}
X
X/*
X * Get name component of filename.  Translates name to upper case.  Returns
X * pointer to new name.
X */
X
Xchar *
Xgetname(filename)
Xchar *filename;
X{
X	char *s, *ans, *malloc(), *temp, *strcpy(), *strrchr();
X	char buf[MAX_PATH];
X
X	strcpy(buf, filename);
X	temp = buf;
X					/* find the last separator */
X	if (s = strrchr(temp, '/'))
X		temp = s+1;
X	if (s = strrchr(temp, '\\'))
X		temp = s+1;
X					/* xlate to upper case */
X	for (s = temp; *s; ++s) {
X		if (islower(*s))
X			*s = toupper(*s);
X	}
X
X	ans = malloc((unsigned int) strlen(temp)+1);
X	strcpy(ans, temp);
X	return(ans);
X}
X
X/*
X * Get the path component of the filename.  Translates to upper case.
X * Returns pointer to path.  Doesn't alter leading separator, always
X * strips trailing separator (unless it is the path itself).
X */
X
Xchar *
Xgetpath(filename)
Xchar *filename;
X{
X	char *s, *temp, *ans, *malloc(), *strcpy(), *strrchr();
X	char buf[MAX_PATH];
X	int has_sep;
X
X	strcpy(buf, filename);
X	temp = buf;
X					/* find last separator */
X	has_sep = 0;
X	if (s = strrchr(temp, '/')) {
X		has_sep++;
X		temp = s;
X	}
X	if (s = strrchr(temp, '\\')) {
X		has_sep++;
X		temp = s;
X	}
X
X	*temp = '\0';
X					/* translate to upper case */
X	for (s = buf; *s; ++s) {
X		if (islower(*s))
X			*s = toupper(*s);
X	}
X					/* if separator alone, put it back */
X	if (!strlen(buf) && has_sep)
X		strcpy(buf, "/");
X
X	ans = malloc((unsigned int) strlen(buf)+1);
X	strcpy(ans, buf);
X	return(ans);
X}
SHAR_EOF
if test 2215 -ne "`wc -c < 'unixname.c'`"
then
	echo shar: "error transmitting 'unixname.c'" '(should have been 2215 characters)'
fi
fi
exit 0
#	End of shell archive



More information about the Unix-pc.sources mailing list