home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
High Voltage Shareware
/
high1.zip
/
high1
/
DIR24
/
AV181B.ZIP
/
AVEXE.ZIP
/
SAMPLE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-12
|
20KB
|
807 lines
/****************************************************************************/
/* Source code showing how to access info in ARCHIVER.BB2, and how to */
/* use that info to determine the archive type of a file. */
/* Written by M. Kimes w/ CSet/2 for OS/2 2.x, may be freely used. */
/* ARCHIVER.BB2 and its format are donated to public domain. Anyone */
/* needing to add fields should check with me first, though. Thanks. */
/* */
/* see end of file for additional comments */
/****************************************************************************/
#define INCL_DOS
#include <os2.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <share.h>
/*
* structure to hold information (record) from ARCHIVER.BB2
* in a singly linked list
*/
typedef struct ARC_TYPE {
CHAR *id;
CHAR *ext;
LONG file_offset;
CHAR *list;
CHAR *extract;
CHAR *exwdirs;
CHAR *test;
CHAR *create;
CHAR *move;
CHAR *createrecurse;
CHAR *createwdirs;
CHAR *movewdirs;
CHAR *delete;
CHAR *signature;
CHAR *startlist;
CHAR *endlist;
INT osizepos;
INT nsizepos;
INT fdpos;
INT fdflds;
INT fnpos;
struct ARC_TYPE *next;
} ARC_TYPE;
/* # of lines in an ARCHIVER.BB2 record that we understand
* we'll skip any beyond this
*/
#define NUMLINES 21
/* stuff for literal() */
#define HEX "0123456789ABCDEF"
#define DEC "0123456789"
CHAR *strip_trail_char (CHAR *strip,CHAR *a) {
register CHAR *p;
if(a && *a && strip && *strip) {
p = &a[strlen(a) - 1];
while (*a && strchr(strip,*p) != NULL) {
*p = 0;
p--;
}
}
return a;
}
CHAR *strip_lead_char (CHAR *strip,CHAR *a) {
register CHAR *p = a;
if(a && *a && strip && *strip) {
while(*p && strchr(strip,*p) != NULL)
p++;
if(p != a)
memmove(a,p,strlen(p) + 1);
}
return a;
}
CHAR *convert_1_2_another (CHAR one,CHAR two,CHAR *a) {
register CHAR *p = a;
if(p && *p && one && two) {
while(*p) {
if(*p == one)
*p = two;
p++;
}
}
return a;
}
#define lstrip(s) strip_lead_char(" \t",(s))
#define rstrip(s) strip_trail_char(" \t",(s))
#define stripcr(s) strip_trail_char("\r\n",(s))
#define trailbkslstrip(s) strip_trail_char("\\\/",(s))
#define cvtbksl2sl(s) convert_1_2_another('\\','/',(s))
#define cvtsl2bksl(s) convert_1_2_another('/','\\',(s))
char *searchapath (char *path,char *filename) {
/* search a single path */
static char fbuf[1539];
struct stat st;
char *envbuf = NULL,*p,temp;
p = getenv(path);
if(!p)
return NULL;
envbuf = strdup(p);
if(!envbuf)
return NULL;
p = strtok(envbuf,";");
do {
strncpy(fbuf,p,1024);
fbuf[1024] = 0;
temp = fbuf[strlen(fbuf) - 1];
if(temp != '/' && temp != '\\')
strcat(fbuf,"\\");
strcat(fbuf,filename);
if(!stat(fbuf,&st)) {
free(envbuf);
return fbuf;
}
p = strtok(0,";");
} while(p);
free(envbuf);
return NULL;
}
char *searchpath (char *filename) {
/* search a group of paths */
static char fbuf[1030];
struct stat st;
char *p;
if(!stat(filename,&st)) { /* try current dir first */
if(strchr(filename,'/') || strchr(filename,'\\') || strchr(filename,':')) {
strcpy(fbuf,filename);
return fbuf;
}
save_dir(fbuf);
strcat(fbuf,"\\");
strcat(fbuf,filename);
return fbuf;
}
if((p = searchapath("PATH",filename)) != NULL)
return p;
if((p = searchapath("DPATH",filename)) != NULL)
return p;
p = searchapath("XPATH",filename);
return p;
}
INT index (CHAR *s,CHAR c) {
/* used by literal(); returns offset of c in s or -1 (error) */
CHAR *p;
p = strchr(s,c);
if(!p || !*p)
return -1;
return (INT)(p - s);
}
CHAR *literal (CHAR *fsource) {
/*
* perform C-style translation of \? escaped characters
* lets us put things like PK\x3\x4 as a signature in
* ARCHIVER.BB2's plain text format
*/
register INT wpos,w,x;
INT wincomment;
CHAR *fdestin,*freeme,wchar;
if(!fsource || !*fsource) /* error */
return fsource;
x = strlen(fsource) + 1;
freeme = fdestin = malloc(x + 1); /* work area */
wincomment = 0;
memset(fdestin,0,x); /* start out with NULL string */
w = 0; /* set index to first character */
while (fsource[w]) { /* until end of string */
switch(fsource[w]) {
case '\\':
if(!wincomment)
switch(fsource[w + 1]) {
case 'x' : /* hexadecimal */
wchar = 0;
w += 2; /* get past "\x" */
if (index(HEX,(CHAR)toupper(fsource[w])) != -1) {
while ((wpos = index(HEX,(CHAR)toupper(fsource[w]))) != -1) {
wchar = (CHAR)(wchar << 4) + (CHAR)wpos;
w++;
}
}
else wchar = 'x'; /* just an x */
w--;
*fdestin++ = wchar;
break;
case '\\' : /* we want a "\" */
w++;
*fdestin++ = '\\';
break;
case 't' : /* tab CHAR */
w++;
*fdestin++ = '\t';
break;
case 'n' : /* new line */
w++;
*fdestin++ = 10;
break;
case 'r' : /* carriage return */
w++;
*fdestin++ = '\r';
break;
case 'b' : /* backspace */
w++;
*fdestin++ = '\b';
break;
case 'a': /* bell */
w++;
*fdestin++ = '\07';
break;
case '\'' : /* single quote */
w++;
*fdestin++ = '\'';
break;
case '\"' : /* double quote */
w++;
*fdestin++ = '\"';
break;
default : /* decimal */
w++; /* get past "\" */
wchar = 0;
if (index(DEC,fsource[w]) != -1) {
do {
wchar = (CHAR)(wchar * 10 + (fsource[w++] - 48)); /* cnvt to binary */
} while (index(DEC,fsource[w]) != -1);
w--;
}
else wchar = fsource[w];
*fdestin ++ = wchar;
break;
}
break;
case '*' :
if(wincomment) {
if (fsource[w + 1] == '/') {
wincomment--; /* toggle the flag */
w++;
}
}
else
*fdestin++ = fsource[w];
break;
case '/' : /* beginning of comment perhaps */
if(fsource[w + 1] == '*') {
wincomment++; /* toggle the flag */
w++;
}
break;
default :
if(!wincomment)
*fdestin++ = fsource[w];
break;
}
w++;
}
*fdestin = 0; /* terminate the string */
strcpy(fsource,freeme); /* swap 'em */
free(freeme);
return fsource;
}
ULONG checkfile2 (CHAR *file,INT *error) {
/*
* check whether a file is executable
* used to ignore records that
* don't point to a useful program
*/
CHAR *p,*pp;
INT ret;
ULONG apptype = 0L;
if(!file || !*file) {
*error = 3;
return apptype;
}
pp = strchr(file,' ');
if(pp)
*pp = 0;
p = searchpath(file);
if(pp)
*pp = ' ';
if(!p || !*p) {
*error = 1;
}
else {
ret = (INT)DosQAppType(p,&apptype);
if(ret) {
*error = -1;
}
else {
apptype &= (~FAPPTYP_32BIT);
if(!apptype ||
(apptype == FAPPTYP_NOTWINDOWCOMPAT) ||
(apptype == FAPPTYP_WINDOWCOMPAT) ||
(apptype & FAPPTYP_BOUND) ||
(apptype & FAPPTYP_WINDOWAPI) ||
(apptype & FAPPTYP_DOS)) {
*error = 0;
}
else {
*error = 2;
}
}
}
return apptype;
}
CHAR *stristr (CHAR *t, CHAR *s) {
/* case insensitive strstr */
register CHAR *t1;
register CHAR *s1;
while(*t) {
t1 = t;
s1 = s;
while(*s1) {
if (toupper(*s1) != toupper(*t))
break;
else {
s1++;
t++;
}
}
if (!*s1)
return t1;
t = t1 + 1;
}
return NULL;
}
FILE *_fsopen (CHAR *filename,CHAR *mode,INT sharemode) {
/* open file as stream with sharing */
INT openmode = 0;
INT handle;
FILE *fp;
if(stristr(mode,"r"))
openmode |= O_RDONLY;
else if(stristr(mode,"w"))
openmode |= (O_WRONLY | O_TRUNC | O_CREAT);
if(stristr(mode,"b"))
openmode |= O_BINARY;
else
openmode |= O_TEXT;
if(stristr(mode,"a")) {
openmode |= (O_APPEND | O_WRONLY);
}
if(stristr(mode,"+")) {
openmode &= (~(O_RDONLY | O_WRONLY));
openmode |= (O_RDWR | O_CREAT);
}
handle = sopen(filename,openmode,sharemode,S_IWRITE | S_IREAD);
if(handle == -1)
return NULL;
if(openmode & O_APPEND)
lseek(handle,0L,SEEK_END);
if(mode[strlen(mode) - 1] == 't')
mode[strlen(mode) - 1] = 0; /* bug bug bug */
fp = fdopen(handle,mode);
if(!fp) {
close(handle);
fp = fopen(filename,mode); /* last ditch effort */
}
if(fp) {
if(openmode & O_TEXT) /* line buffer text files */
setvbuf(fp,NULL,_IOLBF,BUFSIZ * 2);
else
setvbuf(fp,NULL,_IOFBF,BUFSIZ * 4);
}
return fp;
}
ARC_TYPE *find_type (CHAR *filespec,ARC_TYPE *topsig) {
/*
* return pointer to matching archive info record, or NULL on
* failure (not an archive we understand). Once you know the
* archive type you can employ the information in the ARC_TYPE
* structure to manipulate the archive.
*/
FILE *file; /* File handle */
ARC_TYPE *info;
INT l; /* Length of the signature. */
CHAR buffer[80]; /* Read buffer for the signatures. */
INT error;
file = _fsopen(filespec,"rb",SH_DENYNO); /* Open the file */
if (!file) /* If can't open it, return with error. */
return NULL;
info = topsig; /* start of signatures */
while (info) {
rewind(file);
l = strlen(info->signature); /* Get the signature length. */
if(l > 79)
l = 79;
if(info->file_offset >= 0L)
fseek(file,info->file_offset,SEEK_SET);
else
fseek(file,info->file_offset,SEEK_END);
if((error = fread(buffer,1,l,file)) > 0) {
buffer[l] = 0;
if(!memcmp(info->signature,buffer,l)) { /* match, see if useable */
ULONG apptype;
apptype = checkfile2(info->list,&error);
if(apptype && apptype != FAPPTYP_DOS) {
apptype = checkfile2(info->extract,&error);
if(apptype && apptype != FAPPTYP_DOS) /* dammit! */
break;
}
}
}
info = info->next;
}
fclose(file); /* Either way, we're done for now */
return info; /* return signature, if any */
}
ARC_TYPE *load_archivers (INT *error) {
/*
* load archiver records into linked list, return start of list or
* NULL (error then contains more info on reason for failure).
* the list may be traversed like this:
*
* ARC_TYPE *info;
*
* info = arcsighead; // assign temp to head of list
* while(info) { // while != NULL, end of list...
* // do something with it
* info = info->next; // point to next structure in list
* }
*/
FILE *handle;
CHAR s[257],*p;
ARC_TYPE *info = NULL,*last = NULL;
INT numlines = NUMLINES,x;
static ARC_TYPE *arcsighead = NULL;
*error = 0; /* no error (yet) */
p = searchpath("ARCHIVER.BB2");
if(!p || !*p) { /* can't find file */
*error = 1;
return NULL;
}
handle = _fsopen(p,"rt",SH_DENYNO);
if(!handle) { /* can't open file */
*error = 2;
return NULL;
}
strcpy(archiverbb2,p);
if(!fgets(s,256,handle)) { /* file is screwed up */
fclose(handle);
*error = 3;
return NULL;
}
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s)
numlines = atoi(s); /* # lines / record */
if(!*s || numlines < NUMLINES) { /* too few lines; choke */
*error = 3;
return NULL;
}
while(!feof(handle)) { /* load the records */
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s) {
info = malloc(sizeof(ARC_TYPE));
if(!info)
break;
memset(info,0,sizeof(ARC_TYPE));
if(*s)
info->id = strdup(s);
else
info->id = NULL;
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s)
info->ext = strdup(s);
else
info->ext = NULL;
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
info->file_offset = atol(s);
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s)
info->list = strdup(s);
else
info->list = NULL;
if(!info->list)
break;
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s)
info->extract = strdup(s);
else
info->extract = NULL;
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s)
info->exwdirs = strdup(s);
else
info->exwdirs = NULL;
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s)
info->test = strdup(s);
else
info->test = NULL;
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s)
info->create = strdup(s);
else
info->create = NULL;
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s)
info->createwdirs = strdup(s);
else
info->createwdirs = NULL;
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s)
info->createrecurse = strdup(s);
else
info->createrecurse = NULL;
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s)
info->move = strdup(s);
else
info->move = NULL;
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
if(*s)
info->movewdirs = strdup(s);
else
info->movewdirs = NULL;
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
stripcr(s);
lstrip(s);
rstrip(s);
info->delete = strdup(s);
if(!fgets(s,256,handle))
break;
stripcr(s);
info->signature = strdup(literal(s));
if(!info->signature)
break;
if(!fgets(s,256,handle))
break;
stripcr(s);
info->startlist = strdup(s);
if(!fgets(s,256,handle))
break;
stripcr(s);
info->endlist = strdup(s);
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
info->osizepos = atoi(s);
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
info->nsizepos = atoi(s);
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
info->fdpos = atoi(s);
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
info->fdflds = atoi(s);
if(!fgets(s,256,handle))
break;
p = strchr(s,';');
if(p)
*p = 0;
info->fnpos = atoi(s);
for(x = NUMLINES;x < numlines;x++) { /* skip extra lines
if(!fgets(s,256,handle)) since we don't understand
break; them */
}
info->next = NULL;
if(!arcsighead)
arcsighead = last = info;
else {
last->next = info;
last = info;
}
if(info->extract && !*info->extract) {
free(info->extract);
info->extract = NULL;
}
}
info = NULL;
}
fclose(handle);
if(info) {
if(info->id) free(info->id);
if(info->ext) free(info->ext);
if(info->list) free(info->list);
if(info->extract) free(info->extract);
if(info->create) free(info->create);
if(info->move) free(info->move);
if(info->delete) free(info->delete);
if(info->signature) free(info->signature);
if(info->startlist) free(info->startlist);
if(info->endlist) free(info->endlist);
if(info->exwdirs) free(info->exwdirs);
if(info->test) free(info->test);
if(info->createrecurse)
free(info->createrecurse);
if(info->createwdirs)
free(info->createwdirs);
if(info->movewdirs) free(info->movewdirs);
}
if(!arcsighead) { /* didn't get anything */
*error = 4;
return NULL;
}
return arcsighead; /* head of list */
}
#ifdef NEVER
typical usage:
ARC_TYPE *arcsighead,*type;
INT error;
CHAR *filename = <whatever>,s[1050];
arcsighead = load_archivers(&error);
if(!arcsighead) {
printf("\nCouldn't load archiver.bb2; error #%d\n",error);
exit(1);
}
/* might check to see if filename exists first... */
type = find_type(filename,arcsighead);
if(!type)
printf("\n%s is not an archive as I understand it.\n",filename);
else {
printf("\n%s appears to be a type %s archive.\n",filename,type->id);
if(type->extract && *type->extract) { /* extract all files in archive */
sprintf(s,"%s %s",type->extract,filename);
system(s);
}
#endif