[net.sources.mac] MacPrograms Sources 2 of 2

casper@wacsvax.OZ (Casper A Boon) (09/19/85)

Here is the second part of the offering, MWRescue, Stripper and sundries.


Casper Boon,
Dept of Computer Science,
University of Western Australia,
casper@wacsvax.oz (OZNet, CSNET)
...!{decvax|seismo}!mulga!wacsvax.oz!casper (UUCP)
casper%wacsvax.oz@seismo.arpa (ARPA)

"When all else fails read the instructions..."

------------------------- Cut Here --------------------------
#! /bin/sh
# This is a shell archive - extract with sh not csh
#
cat << \SHAR_EOF > 'Stripper.c'
/*
 * stripper.c -- strip control characters from a TEXT or WORD file.
 *
 * Copyright Casper A Boon, University of Western Australia
 *
 *
 * This source may be freely distributed to other educational institutions
 * on the following conditions:
 *
 *   1) This copyright notice accompanies it,
 *   2) No profit may be made from such distribution
 *
 *
 * History:
 *	Created  August '85
 *
 */

#include <MacCdefs.h>
#include <quickdraw.h>
#include <stdio.h>
#include <packages.h>

#define TRUE 1
#define FALSE 0
#define MaxChars  16000


short int infile, outfile;
char	nullstr[] = {'\0','\0'};
char	str1[]  = { '\12', 'S','t','r','i','p',' ','F','i','l','e','\0'};
char	str2[]  = { '\14', 'S','t','r','i','p','p','e','d','F','i','l','e','\0'};
char	str3[]  = { '\11', 'S','a','v','e',' ','A','s',' ',':','\0'};
char	CarrRet = '\15';
char	infname[255], outfname[255];
char	CharsBuffer[MaxChars];
long int stripcount = 0;
long int count;

extern short int FSOpen();
extern short int FSClose();
extern short int FSRead();
extern short int FSWrite();
extern short int Create();

char isprint(c)
char c;
{
	if (((c >= 32) && (c <= 126)) || (c == 10) || (c == 13))
		return(TRUE);
	return(FALSE);
}

short int OpenInFile(inf, infnam)
short int *inf;
char * infnam;
{
	Point apoint;
	SFReply theReply;
	SFTypeList typelist;

	apoint.v = 80;
	apoint.h = 80;
	typelist.ftype[0] = 'TEXT';
	typelist.ftype[1] = 'WORD';
	SFGetFile(&apoint, str1, (ProcPtr) 0, 2, &typelist,
					(ProcPtr) 0, &theReply);

	if ( theReply.good )
	    {
	    BlockMove(&theReply.Namelength, infnam, 255);
	    return (FSOpen(&theReply.Namelength,theReply.vRefNum,inf));
	    }
	else return (-1);
}

OpenOutFile(outf, outfnam)
short int *outf;
char * outfnam;
{
	Point apoint;
	SFReply theReply;
	short int err;

	apoint.v = 80;
	apoint.h = 80;
	SFPutFile(&apoint, str3, str2, (ProcPtr) 0, &theReply);

	if ( theReply.good )
	   {
	   BlockMove(&theReply.Namelength, outfnam, 255);
	   err = Create(&theReply.Namelength, theReply.vRefNum,
	   			'EDIT','TEXT');
	   return ( FSOpen(&theReply.Namelength, theReply.vRefNum, outf) );
	   }
	else return(-1);
}

char GetAByte()
{
	long int lcount = 1;
	short int err;
	char c;

 	if ( (err = FSRead(infile, &lcount, &c)) != 0 )
		{
		if (err != -39)
		    {
		    fprintf(stdout, " Read Error # %d Click mouse to continue.\r", err);
		    beepnwait();
		    }
		err = FSWrite(outfile, &count, CharsBuffer);
		FSClose(outfile);
		FSClose(infile);
		fprintf(stdout, "\r %ld Characters stripped from file.\r", stripcount);
		exit(1) ;
		}
	return ( c ) ;
}

main()
{
	char c ;
	short int err;

	InitPack(3);

	if ( err = OpenInFile(&infile, infname) !=  0 )
		{
		fprintf(stdout, " Cannot open input file. Error #%d \r Click mouse to continue.\r",err);
		beepnwait();
		exit(1);
		}
	if ( err = OpenOutFile(&outfile, outfname) !=  0 )
		{
		fprintf(stdout, " Cannot open output file. Error #%d \r Click mouse to continue.\r",err);
		beepnwait();
		exit(1);
		}

	do
                macputchar( GetAByte()) ;
        while ( TRUE ) ;
}

macputchar( c )
char c;
{
	if ( isprint(c) || (c == '\11') )
	    {
		DumpChar(c);
		putchar(c) ;
 	    }
	else stripcount++;
}

beepnwait()
{
SysBeep(5);
while ( !Button() );
while (  Button() );
}

DumpChar(c)
char c;
{
	short int err;
	if (count >= MaxChars)
	    {
	    err = FSWrite(outfile, &count, CharsBuffer);
	    count = 0;
	    }
	CharsBuffer[count++] = c;
}
SHAR_EOF
cat << \SHAR_EOF > 'Stripper.r'
* input for resource compiler
*

StrippRes.Rel

Type  CAB1 = STR 
  ,0
Stripper V1.0

Type ICN# = GNRL
  ,128
* cab1 icon
3FFF8000 60004000 90002000 97FF2000 F0001000 10001000 17FE1000 10001000
10031000 138F1000 103F9000 10FF9000 11FF9000 13FF9000 10FF1F00 107FE080
100FC040 09B3F020 0807F010 0404700F 04720007 02010007 01008007 00806007
00B79FE7 0080009F 0FC00087 08400080 08400100 08400100 04800200 03FFFC00
* cab1 mask
3FFF8000 7FFFC000 FFFFE000 FFFFE000 FFFFF000 1FFFF000 1FFFF000 1FFFF000
1FFFF000 1FFFF000 1FFFF000 1FFFF000 1FFFF000 1FFFF000 1FFFFF00 1FFFFF80
1FFFFFC0 0FFFFFE0 0FFFFFF0 07FFFFFF 07FFFFFF 03FFFFFF 01FFFFFF 00FFFFFF
00FFFFFF 00FFFF9F 0FFFFF87 0FFFFF80 0FFFFF00 0FFFFF00 07FFFE00 03FFFC00

Type FREF
  ,128
* APPL uses loc icon 0, no tagalongs
APPL 0

Type BNDL
  ,128
CAB1 0
* 2 types
* ICN#, 1 entry, loc 0 to glob 128
ICN#
0 128
* FREF, 1 entry, loc 0 to glob 128
FREF
0 128
SHAR_EOF
cat << \SHAR_EOF > 'Stripper.Link'
/Bundle
/Type 'APPL' 'CAB1'

!start

stdlib
stdFileIO
stdIOPrim
FSStuff
SFpacks
Stripper
/Resources
StrippRes
$
SHAR_EOF
cat << \SHAR_EOF > 'MWRescue.c'
/*
 * mwrescue.c -- rescue a damaged MacWrite file (version 3.0 and later)
 *
 *
 * History:
 *
 * 5/11/85 Winkler Created
 *
 * 12 Aug '85 Boon Hacked to Mac.
 *
 *
 */

#include <MacCdefs.h>
#include <quickdraw.h>
#include <stdio.h>
#include <packages.h>

#define TRUE 1
#define FALSE 0
#define MaxChars  16000

/* Compressed characters for English.  MacWrite stores this string
 * in the resource fork of the document.  A future improvement would
 * be to find the string there (presumably in file.rsrc on Unix) rather
 * than assume this one.
 */
char compchars[] = {' ', 'e', 't', 'n', 'r', 'o', 'a', 'i', 's',
                        'd', 'l', 'h', 'c', 'f', 'p', '\n' } ;

/* the Macintosh has several veiws on string. The ROMs were written in
 * Pascal and hence have pascal strings. These then are prefixed with a
 * length byte. Consulair Mac C uses C strings which are postfixed with
 * a NUL byte. This causes many problems in using the Mac ROM calls.
 * A further problem manifests itself in using any string. A simple
 * declaration such as:
 *
 *      char *str = 'a junk string';
 *
 * will have the string pointer set to point to the string at the end of
 * the code. The memory manager moves the code segment around and resets
 * register A5 accourdingly but that doesn't always leave the pointer
 * for the string pointing to the right places. At least that is my guess
 * at the reason behind the strange behaviour with strings.
 * my solution was to be explicit about all assignment, allocate the space
 * explicitly as the following demonstrates.
 */
char	nullstr[] = {'\0','\0'};
char	str1[]  = { '\14', 'R','e','c','o','v','e','r',' ','F','i',
			'l','e','\0'};
char	str2[]  = { '\15', 'R','e','c','o','v','e','r','e','d','F','i',
			'l','e','\0'};
char	str3[]  = { '\11', 'S','a','v','e',' ','A','s',' ',':','\0'};
char	CarrRet = '\15';

char	infname[255], outfname[255];

char	CharsBuffer[MaxChars];

short int infile, outfile;
long int count;

/* these Mac routines were not implemented in MacC so they appear in
   an external library which I hacked together. They are declared here
   to avoid the long int/short int difference */
extern short int FSOpen();
extern short int FSClose();
extern short int FSRead();
extern short int FSWrite();
extern short int Create();



char isprint(c)
char c;
{
	if (((c >= 32) && (c <= 126)) || (c == 10) || (c == 13))
		return(TRUE);
	return(FALSE);
}

/* OpenInFile was created to give the prompt Dialog box for opening
   the source file     */
short int OpenInFile(inf, infnam)
short int *inf;
char * infnam;
{
	Point apoint;
	SFReply theReply;
	SFTypeList typelist;

	apoint.v = 80;
	apoint.h = 80;
	typelist.ftype[0] = 'WORD';
	SFGetFile(&apoint, str1, (ProcPtr) 0, 1, &typelist,
					(ProcPtr) 0, &theReply);

	if ( theReply.good )
	    {
	    BlockMove(&theReply.Namelength, infnam, 255);
	    return (FSOpen(&theReply.Namelength,theReply.vRefNum,inf));
	    }
	else return (-1);
}

/* OpenOutFile for the standard dialog for the output file */
OpenOutFile(outf, outfnam)
short int *outf;
char * outfnam;
{
	Point apoint;
	SFReply theReply;
	short int err;

	apoint.v = 80;
	apoint.h = 80;
	SFPutFile(&apoint, str3, str2, (ProcPtr) 0, &theReply);

	if ( theReply.good )
	   {
	   BlockMove(&theReply.Namelength, outfnam, 255);
	   err = Create(&theReply.Namelength, theReply.vRefNum,
	   			'EDIT','TEXT');
	   return ( FSOpen(&theReply.Namelength, theReply.vRefNum, outf) );
	   }
	else return(-1);
}

main() /* read encoded file from stdin and write text to stdout */
{
	int c ;
	short int err;

	InitPack(3);

	fprintf(stdout, " Mac Write Document Rescuer \r");
	if ( err = OpenInFile(&infile, infname) !=  0 )
		{
		fprintf(stdout, " Cannot open input file. Error #%d \r Click mouse to continue.\r",err);
		beepnwait();
		exit(1);
		}
	if ( err = OpenOutFile(&outfile, outfname) !=  0 )
		{
		fprintf(stdout, " Cannot open output file. Error #%d \r Click mouse to continue.\r",err);
		beepnwait();
		exit(1);
		}

	/* this following bit of the main() is as it came */
	do
        {
                c = getnibble() ;
                if ( c != 0x000f ) macputchar( compchars[c] ) ;
                else
                {
                        int c2 ;

                        c = getnibble() ; c2 = getnibble() ;
                        /* need variables because C doesn't guarantee
        		 * the order of evaluation of arguments.  So if
                         * c and c2 below were replaced by getnibble()'s
                         * there would be no way of knowing which of the
                         * next two nibbles on stdin would be shifted
                         */
                        macputchar( (c << 4) + c2 ) ;
                }
        }
        while ( TRUE ) ; /* infinite loop. getnibble() exits on EOF */
}

macputchar( c ) /* translate returns to newlines and suppress nonprinting characters */
/* Hacked to include the DumpChar for dumping to files */
char c;
{
	short int err;

	if ( isprint(c) )
	    {
	    if ( c != '\r' ) 
		{
		DumpChar(c);
		putchar(c) ;
		}
	    else
		{
		DumpChar(CarrRet);
		putchar('\n');
		}
 	    }
}

getnibble() /* return the next nibble from stdin.  exits on EOF. */
/* Haqued to read from other than standard in (ie using the Mac FSRead()) */
{
        static int got = FALSE ;
        static int chr ;
	char c;
	long int lcount = 1;
	short int err;

        if ( ! got )
            {
 	    if ( (err = FSRead(infile, &lcount, &c)) != 0 )
		{
		if (err != -39)
		    {
		    fprintf(stdout, " Read Error # %d Click mouse to continue.\r", err);
		    beepnwait();
		    }
		err = FSWrite(outfile, &count, CharsBuffer);
		FSClose(outfile);
		FSClose(infile);
		exit(1) ;
		}
	    got = TRUE ;
	    chr = c;
	    return ( ( chr >> 4 ) & 0x0f) ;
	    }
	else
	    {
	    got = FALSE ;
	    return (chr & 0x0f) ;
	    }
}

/* a little procedure for debugging. Easier to make a sound and wait for
   the mouse click than to write to the screen in initial stages */
beepnwait()
{
SysBeep(5);
while ( !Button() );
while (  Button() );
}

/* put chars in a large buffer, and dump the buffer when full */
DumpChar(c)
char c;
{
	short int err;
	if (count >= MaxChars)
	    {
	    err = FSWrite(outfile, &count, CharsBuffer);
	    count = 0;
	    }
	CharsBuffer[count++] = c;
}
SHAR_EOF
cat << \SHAR_EOF > 'MWRescue.r'
* input for resource compiler
*

MWRescRes.Rel

Type  CAB0 = STR 
  ,0
Mac Write Rescue V 1.0

Type ICN# = GNRL
  ,128
* cab0 icon
00000000 00010000 00010000 00010000 0007C000 00393800 00C10600 01010100
02010080 03895980 05555540 05955540 0555D540 09895920 0803BF20 7FFFC0FC
08638060 09813020 0601F810 0402780F 0C023007 0A010007 12018007 11016007
20C11FE7 2039381F 4007C007 40010004 40010004 7FFFFFFC 00000000 00000000
* cab0 mask
00000000 00010000 00010000 00010000 0007C000 003FF800 00FFFE00 01FFFF00
03FFFF80 03FFFF80 07FFFFC0 07FFFFC0 07FFFFC0 0FFFFFE0 0FFFFFE0 7FFFFFFC
0FFFFFE0 0FFFFFE0 07FFFFF0 07FFFFFF 0FFFFFFF 0FFFFFFF 1FFFFFFF 1FFFFFFF
3FFFFFFF 3FFFFFFF 7FFFFFFF 7FFFFFFC 7FFFFFFC 7FFFFFFC 00000000 00000000

Type FREF
  ,128
* APPL uses loc icon 0, no tagalongs
APPL 0

Type BNDL
  ,128
CAB0 0
* 2 types
* ICN#, 1 entry, loc 0 to glob 128
ICN#
0 128
* FREF, 1 entry, loc 0 to glob 128
FREF
0 128
SHAR_EOF
cat << \SHAR_EOF > 'MWRescue.link'
/Bundle
/Type 'APPL' 'CAB0'
!start

stdlib
stdFileIO
stdIOPrim
FSStuff
VolStuff
SFpacks
mwrescue
/Resources
MWRescRes
$
SHAR_EOF
cat << \SHAR_EOF > 'FSStuff.c'
#include "pbDefs.h"

#define NIL 0

typedef  struct PARAMBLK
    {
    long  int qLink;		// next queue entry
    short int qType;		// queue type
    short int ioTrap;		// routine trap
    long  int ioCmdAddr;	// routine address
    char     *ioCompletion;	// completion routine
    short int ioResult;		// result code
    struct P_Str
	     *ioFileName;	// volume or file name
    short int ioVRefNum;	// volume reference or drive number
    short int ioRefNum;		// path reference number
    char      ioVersNum;	// version number
    char      ioPermission;	// read/write permission
    long  int ioMisc;		// miscellaneous pointer
    char     *ioBuffer;	// data buffer
    long  int ioReqCount;	// requested number of bytes
    long  int ioActCount;	// actual number of bytes
    short int ioPosMode;	// newline char and type of positioning op
    long  int ioPosOffset;	// size of positioning ofset
    };



short int Create(str,mode, creator, filetype)
struct P_Str * str;
short int mode;
long int creator, filetype;
{
	struct PARAMBLK myparamblk;
	short int retval;
	long int TheTime;

	myparamblk.ioCompletion = NIL;
	myparamblk.ioMisc	= 0;
	myparamblk.ioFileName	= str;
	myparamblk.ioVRefNum	= mode;
	myparamblk.ioVersNum	= 0;
#asm
		CLR.W	-(SP)
		PEA	-76(A6)
		DC.W	$A039
		TST	(SP)+
#endasm
	myparamblk.ioRefNum	= 0;
	myparamblk.ioReqCount	= creator;
	myparamblk.ioBuffer	= (char *) filetype;
	retval = PBCreate(&myparamblk, 0);
	
	retval = PBSetFInfo(&myparamblk, 0);
	return(retval);

}

short int FSOpen(str,mode,chan)
struct P_Str * str;
short int mode;
short int * chan;
{
	struct PARAMBLK myparamblk;
	short int retval;

	myparamblk.ioCompletion = NIL;
	myparamblk.ioFileName	= str;
	myparamblk.ioVRefNum	= mode;
	myparamblk.ioVersNum	= 0;
	myparamblk.ioPermission = 0;
	myparamblk.ioMisc	= NIL;
	retval = PBOpen(&myparamblk, 0);
	*chan = myparamblk.ioRefNum;
	return(retval);

}

short int FSRead(chan, count, c)
short int chan;
long int * count;
char * c;
{
	struct PARAMBLK myparamblk;
	short int retval;

	myparamblk.ioCompletion = NIL;
	myparamblk.ioReqCount = *count;
	myparamblk.ioRefNum = chan;
	myparamblk.ioBuffer = c;
	myparamblk.ioPosMode = 0;
	myparamblk.ioPosOffset = 0;
	retval = PBRead(&myparamblk, 0);
	*count = myparamblk.ioActCount;
	return(retval);

}

short int FSWrite(chan, count, c)
short int chan;
long int * count;
char * c;
{
	struct PARAMBLK myparamblk;
	short int retval;

	myparamblk.ioCompletion = NIL;
	myparamblk.ioReqCount = *count;
	myparamblk.ioRefNum = chan;
	myparamblk.ioBuffer = c;
	myparamblk.ioPosMode = 0;
	myparamblk.ioPosOffset = 0;
	retval = PBWrite(&myparamblk, 0);
	*count = myparamblk.ioActCount;
	return(retval);

}

short int FSClose(refnum)
short int refnum;
{
	struct PARAMBLK myparamblk;
	short int retval;

	myparamblk.ioCompletion = 0;
	myparamblk.ioRefNum	= refnum;
	return(PBClose(&myparamblk, 0));
}

short int FSDelete(name,vrefnum)
struct P_Str * name;
short int vrefnum;
{
	struct PARAMBLK myparamblk;
	short int retval;

	myparamblk.ioCompletion = 0;
	myparamblk.ioFileName	= name;
	myparamblk.ioVersNum	= 0;
	myparamblk.ioVRefNum	= vrefnum;
	return(PBDelete(&myparamblk, 0));
}
SHAR_EOF
cat << \SHAR_EOF > 'SFPacks.c'
#include <MacCdefs.h>
#include <quickdraw.h>
#include <packages.h>

#define TRUE 1
#define FALSE 0



SFGetFile(where,prompt,fileFilter,numTypes,typeList,dlgHook,reply)

Point		*where;
struct P_Str	*prompt;
int		(*fileFilter)();
short		numTypes;
SFTypeList	*typeList;
int		(*dlgHook)();
SFReply		*reply;
{
#asm
	MOVE.L	SP, A1			;SAVE ORIGINAL SP
	MOVE.L	D0, A0			;DEREFERENCE POINT SINCE
					;STRUCTURE SIZE IS SMALLER
					;THAN 33 BITS
	MOVE.L	(A0), -(SP)		;WHERE
	MOVE.L	D1, -(SP)		;PROMPT
	MOVE.L	D2, -(SP)		;fileFilter
	MOVE.W	D3, -(SP)		;numTypes
	MOVE.L	D4, -(SP)		;typeList
	MOVE.L	D5, -(SP)		;dlgHook
	MOVE.L	D6, -(SP)		;reply
	MOVE.W	#2, -(SP)		;Select SFPGetFile
	DC.W	$A9EA			;_Pack3
#endasm
}

SFPutFile(where,prompt,origname,dlgHook,reply)

Point		*where;
struct P_Str	*prompt;
struct P_Str	*origname;
int		(*dlgHook)();
SFReply		*reply;
{
#asm
	MOVE.L	SP, A1			;SAVE ORIGINAL SP
	MOVE.L	D0, A0			;DEREFERENCE POINT SINCE
					;STRUCTURE SIZE IS SMALLER
					;THAN 33 BITS
	MOVE.L	(A0), -(SP)		;WHERE
	MOVE.L	D1, -(SP)		;PROMPT
	MOVE.L	D2, -(SP)		;origname
	MOVE.L	D3, -(SP)		;dlghook
	MOVE.L	D4, -(SP)		;reply
	MOVE.W	#1, -(SP)		;Select SFPutFile
	DC.W	$A9EA			;_Pack3
#endasm
}
SHAR_EOF
cat << \SHAR_EOF > 'VolStuff.c'
#include "pbDefs.h"

#define NIL 0

typedef  struct PARAMBLK
    {
    long  int qLink;		// next queue entry
    short int qType;		// queue type
    short int ioTrap;		// routine trap
    long  int ioCmdAddr;	// routine address
    char     *ioCompletion;	// completion routine
    short int ioResult;		// result code
    char     *ioFileName;	// volume or file name
    short int ioVRefNum;	// volume reference or drive number
    short int ioRefNum;		// path reference number
    short int filler;		// not used
    short int ioVolIndex;	// volume index
    long  int ioVCrDate;	// date and time of initialization
    long  int ioVLsBkUp;	// date & time of last backup
    short int ioVAtrb;		// bit 15 = 1 if volume locked
    short int ioVNmFls;		// number of files
    short int ioVDirSt;		// first block of file directory
    short int ioVBlLn;		// number blocks in file directory
    short int ioVNmAlBlks;	// number alloc blocks in volume
    long  int ioVAlBlkSiz;	// number bytes per allocation block
    long  int ioVClpSiz;	// bytes to allocate
    short int ioAlBlSt;		// first block in vol block map
    long  int ioVNxtFNum;	// next free file number
    short int ioVFrBlk;		// number free alloc blocks
    };

short int GetVInfo(drvnum, vnam, vrefno, freeBytes)
short int drvnum;
char * vnam;
short int *vrefno;
long int * freeBytes;
{
	struct PARAMBLK myparamblk;
	short int retval;

	myparamblk.ioCompletion = 0;
	myparamblk.ioVRefNum	= drvnum;
	if (vnam == (char *) -1)
	   myparamblk.ioVolIndex	= -1;
	else
	   myparamblk.ioVolIndex	= 0;
	myparamblk.ioFileName	= vnam;
	retval = PBGetVInfo(&myparamblk, 0);
	*freeBytes = (myparamblk.ioVFrBlk * myparamblk.ioVAlBlkSiz);
	*vrefno = myparamblk.ioVRefNum;
	vnam = myparamblk.ioFileName;
	return(retval);

}

short int GetVol(vnam, vrefno)
char * vnam;
short int * vrefno;
{
	struct PARAMBLK myparamblk;
	short int retval;

	myparamblk.ioCompletion = 0;
	retval = PBGetVol(&myparamblk, 0);
	*vrefno = myparamblk.ioVRefNum;
	vnam = myparamblk.ioFileName;
	return(retval);

}

short int SetVol(vnam, vrefno)
char * vnam;
short int vrefno;
{
	struct PARAMBLK myparamblk;
	short int retval;

	myparamblk.ioCompletion = 0;
	myparamblk.ioVRefNum	= vrefno;
	myparamblk.ioFileName	= vnam;
	return(PBSetVol(&myparamblk, 0));

}

short int FlushVol(vnam, vrefno)
char * vnam;
short int vrefno;
{
	struct PARAMBLK myparamblk;
	short int retval;

	myparamblk.ioCompletion = 0;
	myparamblk.ioVRefNum	= vrefno;
	myparamblk.ioFileName	= vnam;
	return(PBFlshVol(&myparamblk, 0));

}

short int UnmountVol(vnam, vrefno)
char * vnam;
short int vrefno;
{
	struct PARAMBLK myparamblk;
	short int retval;

	myparamblk.ioCompletion = 0;
	myparamblk.ioVRefNum	= vrefno;
	myparamblk.ioFileName	= vnam;
	return(PBUnmountVol(&myparamblk, 0));

}

short int Eject(vnam, vrefno)
char * vnam;
short int vrefno;
{
	struct PARAMBLK myparamblk;
	short int retval;

	myparamblk.ioCompletion = 0;
	myparamblk.ioVRefNum	= vrefno;
	myparamblk.ioFileName	= vnam;
	return(PBEject(&myparamblk, 0));

}
SHAR_EOF