home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
compress
/
arcex20.lha
/
ArcEx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-09-12
|
10KB
|
433 lines
//:ts=8
/////////////////////////////////////////////////////////////////////////////
//
// ArcEx V2.0 - V37+ only
//
// Mostly done for general 2.x practice ;-)
//
// Note: ArcEx is somewhat large, but notice that it checks everything,
// even small allocations which probably never fail.
//
//
// Compile with Aztec C V5.2a
//
// 1> cc -il ArcEx
// 2> ln ArcEx -lcl
//
/////////////////////////////////////////////////////////////////////////////
//
// This program and sourcecode is © 1992 Mark Cassidy
//
// You are allowed to distribute and modify this, as long as you always
// distribute the original source along with it. NO profit of any kind may
// be made from any such distribution.
//
/////////////////////////////////////////////////////////////////////////////
//
// Notes:
//
// I do not use any non-constant global variables, and I beleive this is a
// good example of good programming practise, unlike some sources I've seen
// from a C=ompany whose name I won't mention here :-)
// - However, the DOSBase is (at present time) somewhat impossible for me to
// get rid of, as this is initialized (as a global) by the startup-code.
//
// I use almost entirely V37 dos.library routines, not because I HAD to, but
// because I began programming V37 only yesterday, so I needed some practice
// in using them.
//
/////////////////////////////////////////////////////////////////////////////
//
// Many thanks must go to Klaus Seistrup#2:230/119.0 for his patience with
// me during the development of this program.
//
// Also thanks to Jesper Kehlet#2:230/413.0 for helpfully providing me with
// Klaus' source-codes :-)
//
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Includes.
/////////////////////////////////////////////////////////////////////////////
#include <exec/memory.h>
#include <exec/types.h>
#include <exec/libraries.h>
#include <dos/dos.h>
#include <dos/rdargs.h>
#include <dos/dostags.h>
#include <dos/dosasl.h>
#include <pragmas/dos_lib.h>
/////////////////////////////////////////////////////////////////////////////
// User-defines.
/////////////////////////////////////////////////////////////////////////////
#define VERSION 20
#define VERSIONSTR "2.0"
#define MIN_DOSBASE 37
#define MIN_DOSBASESTR "37"
#define TEMPLATE "From/A/M,To"
#define OPT_FROM 0
#define OPT_TO 1
#define OPT_COUNT 2
#define ARC_LHA 0
#define ARC_ARC 1
#define ARC_ZOO 2
#define ARC_ZIP 3
#define ARC_ARJ 4
#define ARC_APE 5
#define ARC_PP 6
#define ARC_NUMENT 7
#define ARC_UNKNOWN -1
/////////////////////////////////////////////////////////////////////////////
// Global constant data
/////////////////////////////////////////////////////////////////////////////
const char *Version = "\0$VER: ArcEx "VERSIONSTR" ("__DATE__") © 1992 Wize Productions Denmark";
const char *KS20 = "Sorry!, ArcEx needs Dos.library V"MIN_DOSBASESTR"+\n";
const char *NameStr = "ArcEx "VERSIONSTR;
const char *Poster = "Finished! - Thanx for risking using ArcEx "VERSIONSTR" :-)\n";
extern struct Library *DOSBase;
struct ArcRec {
LONG Offset;
LONG ID;
LONG Len;
};
const struct ArcRec ArcRec[] = {
2, (LONG) '-lh\0', 3, // LhA, LhArc
0, (LONG) 0x1a000000, 1, // Arc
0, (LONG) 'ZOO\0', 3, // Zoo
0, (LONG) 0x504b0304, 4, // Zip
0, (LONG) 0x60ea0000, 2, // Arj
0, (LONG) '$JPE', 4, // APE
0, (LONG) 'PP\0\0', 2 // Power-'Packer'
};
const char *Extensions[] = { ".LHA", ".LZH", ".ARC", ".ZOO", ".ZIP", ".ARJ", ".APE", ".PP" };
const char *Extractors[] = {
"LhA -I -F -Qd -Qw -e -K -a -m -M x ",
"Arc xwn ",
"Zoo xO// ",
"UnZip -d ",
"UnArj x -y ",
"APE x ",
"Decrunch "
};
/////////////////////////////////////////////////////////////////////////////
// User-defined function prototypes.
/////////////////////////////////////////////////////////////////////////////
LONG ArcEx(char *, char *, BOOL);
LONG WildArcEx(char *, char *);
short ArcType(char *);
/////////////////////////////////////////////////////////////////////////////
// Main module, overrides the normal Aztec startup-code/cli parsing.
/////////////////////////////////////////////////////////////////////////////
void _main(long alen, char *aptr)
{
char **FromFiles;
char *To;
struct RDArgs *Args;
LONG **Result;
if (DOSBase->lib_Version < MIN_DOSBASE)
{
Write(Output(), KS20, strlen(KS20));
SetIoErr(ERROR_INVALID_RESIDENT_LIBRARY);
exit(RETURN_FAIL);
}
if (!(Result = (LONG **)AllocVec(OPT_COUNT*sizeof(LONG), MEMF_ANY|MEMF_CLEAR)))
{
PrintFault(ERROR_NO_FREE_STORE, NameStr);
exit(RETURN_FAIL);
}
if (Args = (struct RDArgs *)ReadArgs(TEMPLATE, Result, NULL))
{
Printf("%s\n\n", Version+7);
FromFiles = (char **)Result[OPT_FROM];
To = (char *)Result[OPT_TO];
while(*FromFiles)
{
LONG Ret;
if (SetSignal(0,0) & SIGBREAKF_CTRL_C)
{
SetSignal(0, SIGBREAKF_CTRL_C);
PrintFault(ERROR_BREAK, NameStr);
FreeVec(Result);
exit(RETURN_WARN);
}
if ( (Ret = WildArcEx(*(FromFiles++), To)) != RETURN_OK)
{
FreeArgs(Args);
FreeVec(Result);
exit(Ret);
}
}
FreeVec(Result);
FreeArgs(Args);
} else {
FreeVec(Result);
PrintFault(IoErr(), NameStr);
exit(RETURN_WARN);
}
PutStr(Poster);
exit(RETURN_OK);
}
/////////////////////////////////////////////////////////////////////////////
// The extract routine, extracts 1 file to destinaton.
/////////////////////////////////////////////////////////////////////////////
LONG ArcEx(char *From, char *To, BOOL WildScan)
{
BPTR FromLock;
BPTR ToLock = 0;
BPTR FileHandle;
BPTR SaveDir = 0;
char *FullName;
char *SystemTagName;
char *EnvBuf;
char Buffer[6];
short Type;
LONG RetVal;
if (!(FromLock = Lock(From, SHARED_LOCK)))
{
short i;
char *NewName = (char *)AllocVec(strlen(From)+5, MEMF_ANY);
if (!NewName)
{
PrintFault(ERROR_NO_FREE_STORE, NameStr);
return(RETURN_FAIL);
}
for(i=0; i<ARC_NUMENT; i++)
{
strcpy(NewName, From);
strcat(NewName, Extensions[i]);
FromLock = Lock(NewName, SHARED_LOCK);
if (FromLock)
break;
}
FreeVec(NewName);
if ( (i==ARC_NUMENT) && (!WildScan) )
{
PrintFault(IoErr(), From);
return(RETURN_WARN);
}
}
if (!(FullName = (char *)AllocVec(1024, MEMF_ANY)))
{
PrintFault(ERROR_NO_FREE_STORE, NameStr);
return(RETURN_FAIL);
}
if(!(NameFromLock(FromLock, FullName, 1024L)))
{
PrintFault(IoErr(), NameStr);
FreeVec(FullName);
return(RETURN_ERROR);
}
if(!(FileHandle = OpenFromLock(FromLock)))
{
PrintFault(IoErr(), NameStr);
UnLock(FromLock);
FreeVec(FullName);
return(RETURN_ERROR);
}
Read(FileHandle, Buffer, 6);
Close(FileHandle);
Type = ArcType(Buffer);
if ( (Type == ARC_UNKNOWN) && (!WildScan) )
{
PrintFault(ERROR_OBJECT_WRONG_TYPE, FullName);
FreeVec(FullName);
return(RETURN_WARN);
}
if (Type == ARC_UNKNOWN)
{
FreeVec(FullName);
return(RETURN_OK);
}
if (To)
{
if(!(ToLock = Lock(To, SHARED_LOCK)))
{
PrintFault(IoErr(), To);
FreeVec(FullName);
return(RETURN_WARN);
}
SaveDir = CurrentDir(ToLock);
}
if (!(SystemTagName = (char *)AllocVec(1024, MEMF_ANY)))
{
PrintFault(ERROR_NO_FREE_STORE, NameStr);
return(RETURN_FAIL);
}
strcpy(SystemTagName, Extractors[Type]);
strcat(SystemTagName, FullName);
FreeVec(FullName);
if (!(EnvBuf = (char *)AllocVec(256L, MEMF_ANY)))
{
PrintFault(ERROR_NO_FREE_STORE, NameStr);
return(RETURN_FAIL);
}
if (GetVar("CUSTOMSHELL", EnvBuf, 256L, 0L) > 0)
RetVal = SystemTags(SystemTagName, SYS_CustomShell, EnvBuf, TAG_DONE, 0L);
else
RetVal = SystemTags(SystemTagName, SYS_UserShell, 0L, TAG_DONE, 0L);
FreeVec(SystemTagName);
FreeVec(EnvBuf);
if (ToLock)
UnLock(ToLock);
if (SaveDir)
CurrentDir(SaveDir);
switch(RetVal)
{
case -1:
PrintFault(IoErr(), NameStr);
return(RETURN_WARN);
break;
case 0:
break;
default:
Printf("%s: Archiver returned %ld\n", NameStr, RetVal);
return(RETURN_WARN);
};
return(RETURN_OK);
}
/////////////////////////////////////////////////////////////////////////////
// The wildcard parser - this one calls ArcEx().
/////////////////////////////////////////////////////////////////////////////
LONG WildArcEx(char *Pat, char *To)
{
struct AnchorPath *AnchorPath;
char *FullName;
LONG TheEnd = 0;
if (!(FullName = (char *)AllocVec(1024L, MEMF_ANY)))
{
PrintFault(ERROR_NO_FREE_STORE, NameStr);
return(RETURN_FAIL);
}
if (!(AnchorPath = (struct AnchorPath *)AllocVec(sizeof(struct AnchorPath), MEMF_ANY|MEMF_CLEAR)))
{
FreeVec(FullName);
PrintFault(ERROR_NO_FREE_STORE, NameStr);
return(RETURN_FAIL);
}
AnchorPath->ap_BreakBits = SIGBREAKF_CTRL_C;
if (MatchFirst(Pat, AnchorPath))
{
LONG ErrorCode;
FreeVec(FullName);
MatchEnd(AnchorPath);
FreeVec(AnchorPath);
if ( (ErrorCode = IoErr()) == ERROR_OBJECT_NOT_FOUND )
PrintFault(ErrorCode, Pat);
else
PrintFault(ErrorCode, NameStr);
return(RETURN_FAIL);
} else {
do {
if (AnchorPath->ap_Info.fib_DirEntryType < 0)
{
LONG Ret;
NameFromLock(AnchorPath->ap_Last->an_Lock, FullName, 1024L);
AddPart(FullName, AnchorPath->ap_Info.fib_FileName, 1024L);
if ( (Ret = ArcEx(FullName, To, ((AnchorPath->ap_Flags & APF_ITSWILD) == APF_ITSWILD) )) != RETURN_OK )
{
FreeVec(FullName);
MatchEnd(AnchorPath);
FreeVec(AnchorPath);
return(Ret);
}
}
if (MatchNext(AnchorPath))
{
LONG ErrorCode;
TheEnd = 1;
if ( ERROR_NO_MORE_ENTRIES != (ErrorCode = IoErr()) )
{
PrintFault(ErrorCode, NameStr);
FreeVec(FullName);
MatchEnd(AnchorPath);
FreeVec(AnchorPath);
return(RETURN_FAIL);
}
}
} while (!TheEnd);
}
FreeVec(FullName);
MatchEnd(AnchorPath);
FreeVec(AnchorPath);
return(RETURN_OK);
}
/////////////////////////////////////////////////////////////////////////////
// The archive-recognition routine.
/////////////////////////////////////////////////////////////////////////////
short ArcType(char *Header)
{
COUNT i;
for(i=0; i<ARC_NUMENT; i++)
if(!memcmp(Header+ArcRec[i].Offset, &ArcRec[i].ID, ArcRec[i].Len))
return(i);
return(ARC_UNKNOWN);
}