home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
unix
/
unshar.sit
/
unshar.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-11
|
13KB
|
564 lines
/* unshar for MPW that's good enough for comp.sources.unix archives */
#include <stdio.h>
#include <string.h>
/*#include <Files.h>
#include <Errors.h>
*/
#include <errno.h>
#ifndef NIL
#define NIL (0L)
#endif
#ifndef EOF
#define EOF (-1L)
#endif
#define DIRECTORY(pb) (((pb).dirInfo.ioFlAttrib & 0x10) == 0x10)
#define getDir 11 /* buttons in the dialogue box */
#define getCurDir 12
#define GD_PROMPT 13
typedef enum
{
infoDlgRes = 1000,
aboutAlrtRes, /* About... alert resource number */
abortRes,
gdDlgRes,
typeDlgRes,
errorAlertRes
};
typedef enum /* File menu item numbers */
{
extract = 1,
close,
quit
};
typedef enum /* Edit menu item numbers */
{
undo = 1,
/* --- */
cut = 3,
copy,
paste,
clear
};
typedef enum /* Option menu item numbers */
{
forceOpt = 1,
setCr
};
typedef enum /* dialog item numbers */
{
okB = 1,
crText,
cancelB
};
typedef enum
{
continueB = 1,
quitB,
messageItem
};
OSErr OurGetVol(char *volName,short *vRefNum,long *dirID);
OSErr OurDirCreate(short vRefNum,long parentDirID,char *directoryName,
long *createdDirID);
Boolean force = FALSE; /* force overwriting existing files */
MenuHandle fileM, editM, optM;
short dirVRefNum = 0;
char *progname;
OSType fdCreator='PEDT'; /* Finder Creator */
OSType fdType='TEXT'; /* Finder Type */
short appFileCount,
whatToDo;
DialogPtr infoDlgPtr, typeDlgPtr;
SetDText (dlog, item, str)
DialogPtr dlog;
int item;
Str255 str;
{
Handle itemHandle;
int itemType;
Rect itemRect;
GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
SetIText (itemHandle, str);
}
/* Dialog handler */
GetDText (dlog, item, str)
DialogPtr dlog;
int item;
StringPtr str;
{
Handle itemHandle;
int itemType;
Rect itemRect;
GetDItem (dlog, item, &itemType, &itemHandle, &itemRect);
GetIText (itemHandle, str);
}
GetCreator()
{
int itemHit;
char creator[5];
typeDlgPtr = GetNewDialog (typeDlgRes, NIL, (WindowPtr) -1L);
BlockMove(&fdCreator, creator+1, 4);
creator[0] = '\004';
SetDText(typeDlgPtr, crText, creator);
SelectWindow(typeDlgPtr);
ShowWindow(typeDlgPtr);
DrawDialog(typeDlgPtr);
ModalDialog(NIL, &itemHit);
if (itemHit == okB) {
GetDText (typeDlgPtr, crText, &creator);
BlockMove(creator+1, &fdCreator, 4);
}
DisposDialog(typeDlgPtr);
}
/*
File menu handler
*/
DoFileMenu (item)
int item;
{
WindowPeek wPeek;
switch (item)
{
case extract:
Extract();
break;
case close:
if ((wPeek = (WindowPeek) FrontWindow ()) != NIL)
{
if (wPeek->windowKind < 0)
CloseDeskAcc (wPeek->windowKind);
}
break;
case quit:
SkelWhoa ();
break;
}
}
DoEditMenu (item)
int item;
{
DialogPtr theDialog;
theDialog = (DialogPtr) FrontWindow ();
if (((WindowPeek) theDialog)->windowKind != dialogKind)
return;
switch (item)
{
case cut:
{
DlgCut (theDialog);
(void) ZeroScrap ();
(void) TEToScrap ();
break;
}
case copy:
{
DlgCopy (theDialog);
(void) ZeroScrap ();
(void) TEToScrap ();
break;
}
case paste:
{
(void) TEFromScrap ();
DlgPaste (theDialog);
break;
}
case clear:
{
DlgDelete (theDialog);
break;
}
}
}
DoOptMenu(item)
int item;
{
switch (item)
{
case forceOpt: force = !force;
CheckItem(optM, forceOpt, force);
break;
case setCr: GetCreator();
break;
}
}
/*
Handle selection of About╔ item from Apple menu
*/
DoAbout ()
{
(void) Alert (aboutAlrtRes, NIL);
}
Boolean useCurDir; /* Set if current dir to be used */
/* Filter procs & dialogue hooks to select directories only in SFGet file */
pascal short
DirSelHook(item, theDialog)
short item;
DialogPtr theDialog;
{
if (item == getDir|| item == getCurDir) {
/* folder selected */
useCurDir = item == getCurDir;
item = getOpen;
}
return(item);
}
pascal Boolean
DirFilterProc(pb)
CInfoPBPtr pb;
{
return(!DIRECTORY(*pb)); /* a directory if bit 4 is set */
}
/*
* GetDir - manage the directory selection dialog
*/
long
GetDir(text)
char *text;
{
char *routine = "\pGetDir";
Point where;
short ht, wd;
SFReply reply;
CInfoPBRec pb;
DialogPtr dlgP;
long dirDirID=0; /* Selected directory DirID */
if ((dlgP = GetNewDialog(gdDlgRes, NIL,(WindowPtr) -1)) == NIL) {
return(TRUE);
}
wd = (dlgP->portRect.right)-(dlgP->portRect.left);
ht = (dlgP->portRect.bottom)-(dlgP->portRect.top);
/* centre the dialogue box on the screen
(but how do I know which screen?)
*/
where.h = (screenBits.bounds.right-screenBits.bounds.left-wd) / 2;
where.v = (screenBits.bounds.bottom-screenBits.bounds.top-ht) / 2;
ParamText((StringPtr)text, (StringPtr)"\p", (StringPtr)"\p", (StringPtr)"\p");
SFPGetFile (where, (StringPtr)text, (FilterProc)DirFilterProc, -1, NIL, DirSelHook, &reply,
gdDlgRes, NIL);
if (reply.good) {
dirVRefNum = reply.vRefNum;
if (useCurDir) {
dirDirID = CurDirStore;
}
else {
dirDirID = (long)(reply.fType);
}
}
return(dirDirID);
}
void GetNextFile(fInfoPtr)
SFReply *fInfoPtr;
{ AppFile nextFile;
static short idx=1;
GetAppFiles(idx++, &nextFile);
fInfoPtr->vRefNum = nextFile.vRefNum;
fInfoPtr->fType = nextFile.fType;
fInfoPtr->version = nextFile.versNum;
BlockMove(nextFile.fName, fInfoPtr->fName, (int)(nextFile.fName[0]+1));
appFileCount--;
}
Extract() {
Point where;
SFReply reply;
while (1){
if (appFileCount > 0) GetNextFile(&reply);
else {
/*
* Use the standard file dialog to select the archive.
*/
where.h = where.v = 75;
SFGetFile(where, (StringPtr)"\pSelect shar file", NIL, 0, NIL, NIL, &reply);
if (!reply.good)
return;
}
/*
* Remember the VRefNum and Name for OpenArchive.
* Find out where to put the extracted files.
*/
(void) SetVol(NIL, reply.vRefNum);
PtoCstr((char *)reply.fName);
unshar(reply.fName);
(void) SetVol(NIL, reply.vRefNum);
}
}
main(argc, argv)
int argc;
char **argv;
{
Handle fTypeH;
DialogTHndl dlgH;
Point where;
short ht, wd;
SkelInit (3, NIL);
SkelApple ("\pAbout Unshar╔", DoAbout);
fileM = NewMenu (1000, (StringPtr)"\pFile");
AppendMenu (fileM, (StringPtr)"\pExtract/O;Close/K;Quit/Q");
SkelMenu (fileM, DoFileMenu, NIL, FALSE);
editM = NewMenu (1001, (StringPtr)"\pEdit");
AppendMenu (editM, (StringPtr)"\p(Undo/Z;(-;Cut/X;Copy/C;Paste/V;Clear");
SkelMenu (editM, DoEditMenu, NIL, FALSE);
optM = NewMenu (1002, (StringPtr)"\pOptions");
AppendMenu (optM, (StringPtr)"\pOverwrite existing files;File type...");
SkelMenu (optM, DoOptMenu, NIL, TRUE);
CountAppFiles (&whatToDo, &appFileCount);
if ((fTypeH = (char **)GetResource('ftyp', 0)) == NIL) {
ExitToShell();
}
BlockMove(*fTypeH, &fdCreator, 4);
BlockMove((*fTypeH)+4, &fdType, 4);
ReleaseResource(fTypeH);
CouldDialog(typeDlgRes);
CouldDialog(infoDlgRes);
dlgH = (DialogTHndl)GetResource('DLOG', typeDlgRes);
wd = ((* dlgH)->boundsRect.right)-((* dlgH)->boundsRect.left);
/* centre the dialogue box on the screen
(but how do I know which screen?)
*/
where.h = (screenBits.bounds.right-screenBits.bounds.left-wd) / 2;
(* dlgH)->boundsRect.right += where.h;
(* dlgH)->boundsRect.left = where.h;
dlgH = (DialogTHndl)GetResource('DLOG', infoDlgRes);
wd = ((* dlgH)->boundsRect.right)-((* dlgH)->boundsRect.left);
/* centre the dialogue box on the screen
(but how do I know which screen?)
*/
where.h = (screenBits.bounds.right-screenBits.bounds.left-wd) / 2;
(* dlgH)->boundsRect.right += where.h;
(* dlgH)->boundsRect.left = where.h;
SkelMain ();
SkelClobber ();
FreeDialog(typeDlgRes);
FreeDialog(infoDlgRes);
}
unshar(s)
char *s;
{
char buffer[BUFSIZ];
char *cp;
FILE *infp, *outfp;
char unixfilename[64], mpwfilename[64];
int line;
short v;
long dirID, dID;
WDPBRec wdpb;
char lineNo[10];
infp = fopen(s, "r");
CtoPstr(s);
if (!infp) {
ParamText((StringPtr)"\pCould not open file ", (StringPtr)s,
(StringPtr)"\p", (StringPtr)"\p");
(void)StopAlert(errorAlertRes, NIL);
return;
}
/* skip over news header lines etc. */
for (line = 1; cp = fgets(buffer, sizeof(buffer), infp); line++)
if (buffer[0] == '#') break;
if (!cp) {
ParamText((StringPtr)"\pCould not locate start of archive in file",
(StringPtr)s, (StringPtr)"\p", (StringPtr)"\p");
(void)StopAlert(errorAlertRes, NIL);
return;
}
/*
* Open the target directory as a base to put everything.
*/
if ((dirID = GetDir("\pin which to put extracted files")) == 0L)
return;
wdpb.ioCompletion = NIL;
wdpb.ioNamePtr = NIL;
wdpb.ioVRefNum = dirVRefNum;
wdpb.ioWDProcID = 'Shar';
wdpb.ioWDDirID = dirID;
if (PBOpenWD(&wdpb, FALSE) != noErr) {
return;
}
/*
* Extract and print the files as found in the archive.
*/
dID = dirVRefNum = wdpb.ioVRefNum;
(void)SetVol(NIL, dID);
/* now we should be at the start of the shar archive itself */
infoDlgPtr = NIL;
infoDlgPtr = GetNewDialog (infoDlgRes, NIL, (WindowPtr)-1L);
while (cp = fgets(buffer, sizeof(buffer), infp)) {
line++;
if (buffer[0] == '#') continue; /* comment line */
if (buffer[0] == 'e') { /*fclose(infp); return;*/ break; } /* exit */
if (buffer[0] == 'i') {
if (!strncmp(buffer, "if test -f", 10)) {
/* testing to see if a file is there */
if (sscanf(buffer, "if test -f '%s'", unixfilename) == 1) {
/* make Mac relative pathname */
sprintf(mpwfilename, "%s", unixfilename);
/* convert '/' to ':' & vice versa */
for (cp = mpwfilename+1; *cp; cp++)
if (*cp == '/')
*cp = ':';
else if (*cp == ':')
*cp = '/';
cp[-1] = 0; /* drop trailing quote mark */
outfp = fopen(mpwfilename, "r");
if (outfp && !force) {
fclose(outfp);
CtoPstr(mpwfilename);
ParamText((StringPtr)"\pWill not clobber existing file",
(StringPtr)mpwfilename, (StringPtr)"\p", (StringPtr)"\p");
if (NoteAlert(errorAlertRes, NIL) == quitB) break;
while (buffer[0] != 'f') { /* skip to size "fi" */
fgets(buffer, sizeof(buffer), infp);
}
fgets(buffer, sizeof(buffer), infp); /* skip over ending comment */
fgets(buffer, sizeof(buffer), infp); /* skip over test "fi" */
} else {
if (outfp) fclose(outfp);
CtoPstr(mpwfilename);
Create((StringPtr)mpwfilename, dID, fdCreator, fdType);
ParamText((StringPtr)mpwfilename,
(StringPtr)"\p", (StringPtr)"\p", (StringPtr)"\p");
SelectWindow(infoDlgPtr);
ShowWindow(infoDlgPtr);
DrawDialog(infoDlgPtr);
PtoCstr(mpwfilename);
outfp = fopen(mpwfilename, "a");
while (buffer[0] != 'X')
fgets(buffer, sizeof(buffer), infp);
do {
fputs(buffer+1, outfp);
fgets(buffer, sizeof(buffer), infp);
} while (buffer[0] == 'X');
fclose(outfp);
fgets(buffer, sizeof(buffer), infp); /* skip to next if */
fgets(buffer, sizeof(buffer), infp);
fgets(buffer, sizeof(buffer), infp);
fgets(buffer, sizeof(buffer), infp);
fgets(buffer, sizeof(buffer), infp);
}
} else {
NumToString((long)line, (StringPtr)lineNo);
CtoPstr(buffer);
ParamText((StringPtr)"\pCannot understand 'if' statement, aborting",
(StringPtr)s, (StringPtr)lineNo, (StringPtr)"\p");
(void) StopAlert(abortRes, NIL);
break;
}
} else if (!strncmp(buffer, "if test ! -d", 12)) {
/* testing to see if a directory is there */
if (sscanf(buffer, "if test ! -d '%s'", unixfilename) == 1) {
/* make Mac relative pathname */
sprintf(mpwfilename, ":%s", unixfilename);
/* convert '/' to ':' & vice versa */
for (cp = mpwfilename+1; *cp; cp++)
if (*cp == '/')
*cp = ':';
else if (*cp == ':')
*cp = '/';
cp[-1] = 0; /* drop trailing quote mark */
/* I wish MPW C had mkdir(), but at least we don't have to do parameter blocks */
OurGetVol(unixfilename, &v, &dirID);
CtoPstr(mpwfilename);
OurDirCreate(v, dirID, mpwfilename, &dID);
fgets(buffer, sizeof(buffer), infp);
fgets(buffer, sizeof(buffer), infp);
fgets(buffer, sizeof(buffer), infp);
}
}
}
}
if (infoDlgPtr != NIL) DisposDialog(infoDlgPtr);
infoDlgPtr = NIL;
(void) PBCloseWD(&wdpb, FALSE);
fclose(infp);
}
OSErr OurGetVol(name, volP, dirIdP)
char *name;
short *volP;
long *dirIdP;
{
WDPBRec pb;
pb.ioCompletion = NULL;
PBHGetVol (&pb, FALSE);
*volP = pb.ioVRefNum;
*dirIdP = pb.ioWDDirID;
BlockMove(pb.ioNamePtr, name, pb.ioNamePtr[0]+1);
}
OSErr OurDirCreate(vRefNum,parentDirID, directoryName,
createdDirID)
short vRefNum;
long parentDirID;
char *directoryName;
long *createdDirID;
{
HParamBlockRec pb;
pb.fileParam.ioNamePtr = (StringPtr)directoryName;
pb.fileParam.ioVRefNum = vRefNum;
pb.fileParam.ioDirID = parentDirID;
pb.fileParam.ioCompletion = NULL;
PBDirCreate(&pb, FALSE);
*createdDirID = pb.fileParam.ioDirID;
}