home *** CD-ROM | disk | FTP | other *** search
- /* 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;
- }
-
-