home *** CD-ROM | disk | FTP | other *** search
- #ifndef LINT
- static char sccsid[]="@(#) needed.c 2.16 88/01/31 15:54:37";
- #endif /* LINT */
-
- /*
- Copyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
- (C) Copyright 1988 Rahul Dhesi -- All rights reserved
- */
-
- #define STRCMP(s1,op,s2) (strcmp(s1,s2) op 0)
-
- #include "options.h"
- /* Accepts a filename from an archive and returns 1 if a command-line
- argument filename matches it. Otherwise returns 0. Returns
- 1 if no arguments were supplied (so by default, all files will
- be extracted */
-
- #include "zoo.h"
-
- #ifdef NEEDCTYP
- #include <ctype.h> /* for tolower() */
- #else
- #include "portable.h"
- #endif
-
- #include "zooio.h"
- #include "zoofns.h"
- #include "various.h"
- #include "debug.h"
-
- extern int next_arg; /* filenames start at this position */
- extern int arg_count; /* count of arguments supplied to program */
- extern char **arg_vector; /* vector of arguments supplied to program */
- /* Uses FIRST_ARG in zoo.h, so must be recompiled when switching
- between Ooz and Zoo */
-
- int needed(pathname, direntry, header)
- char *pathname;
- struct direntry *direntry;
- struct zoo_header *header;
- {
- register int i;
- register char *arg;
- char *justname;
- char arg_copy[PATHSIZE]; /* working copy of an argument */
- char path_copy[PATHSIZE]; /* working copy of pathname */
- char *p; /* a temporary pointer */
- char *q; /* a temporary pointer */
-
- /* if no filenames supplied, match latest version of each
- (but match any version if versions not enabled) */
- if (arg_count <= FIRST_ARG &&
- (!(header->vdata & VFL_ON) ||
- !(direntry->vflag & VFL_ON) || (direntry->vflag & VFL_LAST))) {
-
- return (1); /* .. then all files are needed */
- }
-
- /* count backwards and stop if '+' is encountered */
- for (i = arg_count-1; i >= next_arg; i--) {
- arg = arg_vector[i];
- #ifdef FOLD
- str_lwr(pathname); str_lwr(arg);
- #endif
- #ifdef DEBUG
- printf("needed: testing [%s] and [%s]\n", pathname, arg);
- #endif
- if (STRCMP(arg,==,"+"))
- return (0);
-
- /* If the argument contains a slash, the match fails if the
- path prefixes don't match */
- if (strchr(arg, *(char *)PATH_CH) != NULL) { /* found slash */
- strcpy(arg_copy,arg);
- strcpy(path_copy,pathname);
- p = findlast(arg_copy, PATH_CH);
- if (p != NULL)
- *p = '\0';
- else {
- p = findlast (arg_copy, VER_INPUT);
- if (p != NULL)
- *p = '\0';
- }
- p = findlast(path_copy, PATH_CH);
- if (p != NULL)
- *p = '\0';
- else {
- p = findlast (path_copy, VER_DISPLAY);
- if (p != NULL)
- *p = '\0';
- }
- if (!match_half(path_copy, arg_copy)) {
- #ifdef DEBUG
- printf ("needed(): match failed for [%s] and [%s]\n",
- path_copy, arg_copy);
- #endif
- continue; /* no match this time in loop */
- }
- }
-
- /*
- We reach here either if the pattern had no slashes, or if it had a
- slash but the path prefixes matched. Now we will test to see if the
- filename parts match. If the argument contains VER_INPUT character,
- then this separates the filename from a version number, and only that
- specific version will match. If not, then only the latest version
- will match. However, if the argument has a version character but
- nothing following it, that matches all versions. Also, version
- 0 matches only the latest version and version ^0 matches all
- versions except the latest one.
- */
- strcpy (arg_copy, arg); /* local copy of argument */
- strcpy (path_copy, pathname); /* local copy of pathname */
- p = findlast(arg_copy, VER_INPUT); /* p is version in argument */
- q = findlast(path_copy, VER_DISPLAY); /* q is version in archive */
- if (p != NULL && p != lastptr(arg_copy)) {/* nonnull version in arg */
- if (q != NULL) { /* nonnull ver. in archive */
- char *pp = p+1; /* point to actual version */
- char *qq = q+1;
- if (STRCMP(pp, ==, "0") && !(direntry->vflag & VFL_LAST) ||
- STRCMP(pp, ==, "^0") && (direntry->vflag & VFL_LAST)) {
- debug(("needed: no match versions [%s] and [%s]\n", qq, pp))
- continue;
- }
- if (STRCMP(pp, !=, "0") && STRCMP(pp, !=, "^0") &&
- !match_half (qq, pp)) {
- debug(("needed: no match versions [%s] and [%s]\n", qq, pp))
- continue; /* no match this loop */
- }
- }
- }
- /* Special case test: If argument has version but no filename,
- then filename is assumed to match */
- if (p == arg_copy) { /* 1st char is version char */
- return (1); /* .. so declare a match */
- }
-
- /*
- Reach here if argument has no version character, or if argument has
- version character and it matches version in pathname. Now we check to
- see if argument has no version character and if pathname is latest
- version. If so, the versions do match; if not, then the match fails.
- But if version numbering is not enabled, then versions always match.
- If the match fails, we do a "continue", else we fall through and
- proceed to test the filenames. (Note: It is intuitively better
- to first compare filenames and then see if versions match, but
- since they are both just independent fields, it's equally correct
- to compare versions first, as we are doing here, and then see if
- filenames match. It may even be more efficient.)
- */
-
- if (p == NULL && /* no version char typed */
- !( /* NOT */
- (direntry->vflag & VFL_ON) == 0 || /* no versions */
- (direntry->vflag & VFL_LAST) || /* .. or latest version */
- q == NULL /* .. or no version char */
- )
- )
- {
- #ifdef DEBUG
- printf("needed: fail--no version typed and not latest version\n");
- #endif
- continue; /* match fails */
- }
- /* versions match and we fall through */;
-
- /* reach here if versions match -- so strip them and compare rest */
- if (p != NULL)
- *p = '\0'; /* strips version from arg_copy */
- if (q != NULL)
- *q = '\0'; /* strips version from path_copy */
-
- justname = nameptr(path_copy); /* filename without any pathname */
- if (match_half (justname, nameptr(arg_copy)))
- return (1);
- #ifdef DEBUG
- printf ("needed: fname-only match failed [%s] and [%s]\n",
- justname, nameptr(arg_copy));
- #endif
-
- /* try for a character range */
- if (match_half (arg, "?-?")) { /* character range given */
- if (arg[0] <= *justname && arg[2] >= *justname)
- return (1);
- }
- }
- return (0);
-
- } /* needed */
-
- /***********************/
- /*
- match_half() compares a pattern with a string. Wildcards accepted in
- the pattern are: "*" for zero or more arbitrary characters; "?"
- for any one characters. Unlike the MS-DOS wildcard match, "*" is
- correctly handled even if it isn't at the end of the pattern. ".'
- is not special.
-
- Originally written by Jeff Damens of Columbia University Center for
- Computing Activities. Taken from the source code for C-Kermit version
- 4C.
- */
-
- int match_half (string, pattern)
- register char *string, *pattern;
- {
- char *psave,*ssave; /* back up pointers for failure */
- psave = ssave = NULL;
- while (1) {
- #ifdef IGNORECASE
- for (;
- tolower(*pattern) == tolower(*string);
- pattern++,string++ ) /* skip first */
- #else
- for (; *pattern == *string; pattern++,string++) /* skip first */
- #endif /* IGNORECASE */
-
- if (*string == '\0')
- return(1); /* end of strings, succeed */
- if (*string != '\0' && *pattern == '?') {
- pattern++; /* '?', let it match */
- string++;
- } else if (*pattern == '*') { /* '*' ... */
- psave = ++pattern; /* remember where we saw it */
- ssave = string; /* let it match 0 chars */
- } else if (ssave != NULL && *ssave != '\0') { /* if not at end */
- /* ...have seen a star */
- string = ++ssave; /* skip 1 char from string */
- pattern = psave; /* and back up pattern */
- } else
- return(0); /* otherwise just fail */
- }
- }
-
-