home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
arc_lbr
/
lhx.arc
/
lhx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-04-15
|
6KB
|
318 lines
/* LHX.C -- An LHARC archive tester/scanner
*
* version 1.0 by Mark Armbrust, 15 April 1985 (IRS? Just say NO!)
*
* The code in this module is public domain -- do whatever you want with it */
static char version[] = "@(#)lhx.c version 1.0 by Mark Armbrust";
#include <process.h>
#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <stdlib.h>
#include <malloc.h>
#define MAIN
#include "lhx.h"
/* private routines */
PRIVATE void Usage (void);
PRIVATE int Match (char *, char *);
PRIVATE int WC_Match (char *, char *);
PUBLIC void main (argc, argv)
int argc;
char * argv[];
{
char * arcname,
* arcpath;
FILE * arcfile;
struct fname * filename,
* filenames;
char * p,
* q;
struct find_t findbuf;
int i;
int exitcode;
if (argc < 2)
Usage();
--argc;
++argv;
mode = LIST; /* set default mode */
if (**argv == '-') { /* get mode switch if present */
switch (*++*argv) {
case 'e':
case 'E':
mode = EXTRACT;
break;
case 'l':
case 'L':
mode = LIST;
break;
case 's':
case 'S':
mode = SCAN;
break;
case 't':
case 'T':
mode = TEST;
break;
default:
Usage();
}
--argc;
++argv;
}
header_start = -1; /* disable starting offset options */
file_start = -1;
file_size = -1;
file_type = -1;
file_name[0] = 0;
if (argc && **argv == '@') { /* get starting offsets */
if (mode & SCAN)
fprintf (stderr, "lhx: WARNING -- offsets ignored.\n");
else {
mode |= AT;
i = sscanf (++*argv, "%ld,%ld,%ld,%d,%s", &header_start, &file_start,
&file_size, &file_type, file_name);
if (!i)
Usage();
}
--argc;
++argv;
}
if (argc) { /* get archive name */
arcname = *argv;
--argc;
++argv;
}
else
Usage();
if (argc == 0) { /* get file names if present */
filenames = malloc (sizeof (struct fname));
filenames->name = "*.*";
filenames->next = 0; /* none specified, assume *.* */
}
else {
if (mode & SCAN)
fprintf (stderr, "lhx: WARNING -- filenames ignored.\n");
else {
filenames = 0; /* use the rest of the names to build a */
while (argc--) { /* linked list of filenames to match. */
filename = malloc (sizeof (struct fname));
filename->name = *argv++;
filename->next = filenames;
filenames = filename;
}
}
}
if (strpbrk (arcname, "\\/:")) {
arcpath = strdup(arcname); /* strip path from arcname */
p = arcpath - 1;
while (q = strpbrk (++p, "\\/:"))
p = q;
*p = '\0';
}
else
arcpath = "";
strcpy (name, arcname);
p = name;
if (q = strrchr (p, '\\'))
p = q + 1;
if (q = strrchr (p, '/'))
p = q + 1;
if ( ! strchr (p, '.'))
strcat (name, ".lzh");
if (_dos_findfirst (name, _A_NORMAL | _A_RDONLY ,&findbuf)) {
fprintf (stderr, "lhx: ERROR -- could not find any archive files "
"matching '%s'.\n", arcname);
exit (-1);
}
exitcode = 0;
do {
strcpy (name, arcpath);
strcat (name, findbuf.name);
arcfile = fopen (name, "rb");
if ( ! arcfile) {
fprintf (stderr, "lzx: ERROR -- could not open archive file '%s'.\n",
name);
exit (-1);
}
switch (mode & MODES) {
case EXTRACT:
case LIST:
case TEST:
exitcode += Process (arcfile, filenames);
break;
case SCAN:
Scan (arcfile);
break;
}
fclose (arcfile);
} while ( !(mode & AT) && ! _dos_findnext (&findbuf) );
exit (exitcode);
}
PRIVATE void Usage ()
{
printf ("\n");
printf ("usage: lhx [-elst] [@hdr,data,size,type,name] arcname [filename ...]\n\n");
printf (" E => extract files\n");
printf (" (default) L => list archive contents\n");
printf (" S => scan damaged archive\n");
printf (" T => test archive\n\n");
printf (" @hdr,data,size,type,name => where to start in a damaged archive.\n");
exit (1);
}
PUBLIC int MatchAny (name, filenames)
char * name;
struct fname * filenames;
{
do {
if (Match (name, filenames->name))
return 1;
filenames = filenames->next;
}
while (filenames);
return 0;
}
PRIVATE int Match (file, pattern)
char *file;
char *pattern;
{
int i;
register char *filename;
register char *s;
/* strip off the leading path and trailing modifiers (zoo ver. number, etc.) */
filename = file;
if (s = strrchr (filename, '/')) filename = s+1;
if (s = strrchr (filename, '\\')) filename = s+1;
filename = strdup (filename);
/* if (!filename) Abort ("filename strdup failed in Match"); */
if (s = strpbrk (filename, ";*, ")) *s = '\0';
i = WC_Match (filename, pattern);
free (filename);
return i;
}
/* Returns TRUE if s1 and s2 match under modified MSDOS wildcard rules.
*
* Two strings match if all their substrings between : . / and \ match
* using * and ? as wildcards in the substrings.
*
* Note that MSDOS is a bit schitzo about matching strings that end in : and .
* This code will only match them 1-to-1. For example 'DIR X' matches X.* or
* X\*.* depending on what X is. We do, however, match 'X' to 'X.' and 'X.*'
*
*/
PRIVATE int WC_Match (s1, s2)
register char *s1;
register char *s2;
{
#define IS_SLANT(c) ((c) == '/' || (c) == '\\')
#define IS_FILE_SEP(c) ( (c) == ':' || (c) == '.' || IS_SLANT(c) )
while (1) {
if (*s1 == '*' || *s2 == '*') {
while (*s1 && ! IS_FILE_SEP (*s1))
++s1;
while (*s2 && ! IS_FILE_SEP (*s2))
++s2;
continue;
}
if (*s1 == '?') {
if (!*s2 || IS_FILE_SEP (*s2))
return 0;
++s1;
++s2;
continue;
}
if (*s2 == '?') {
if (!*s1 || IS_FILE_SEP (*s1))
return 0;
++s1;
++s2;
continue;
}
if (*s1 == 0 && *s2 == '.') {
++s2;
continue;
}
if (*s2 == 0 && *s1 == '.') {
++s1;
continue;
}
if (toupper(*s1) != toupper(*s2))
return 0;
if (*s1 == 0) /* then (*s2 == 0) as well! */
break;
++s1;
++s2;
}
return 1;
}