home *** CD-ROM | disk | FTP | other *** search
- static char *RCSid = "$Header: arcdir.c,v 1.2 86/07/15 07:52:56 turner Exp $";
-
- /*
- * $Log: arcdir.c,v $
- * Hack-attack 1.3 86/12/20 01:23:45 wilhite@usceast.uucp
- * Bludgeoned into submission for VAX 11/780 BSD4.2
- * (ugly code, but fewer core dumps)
- *
- * Revision 1.2 86/07/15 07:52:56 turner
- *
- * Revision 1.1 86/06/26 15:00:12 turner
- * initial version
- *
- */
-
- /* ARC - Archive utility - ARCDIR
- */
- #include <stdio.h>
- #include "arc.h"
-
- #if MSDOS
- #include <dir.h>
- #endif
-
- #if BSD
- #include <sys/types.h>
- #include <sys/dir.h>
- #endif
-
- char *pattern; /* global so that fmatch can use them */
- INT filemode;
-
- char *dir(filename,mode,NameList) /* get files, one by one */
- char *filename; /* template, or NULL */
- INT mode; /* search mode bits */
- char *(*NameList[]);
- {
- struct direct *(*namelist[]);
- #ifdef BSD
- INT alphasort();
- INT scandir();
- #endif BSD
- INT fmatch();
- static INT Nnum = 0,ii;
- char *result;
-
- pattern = filename;
- filemode = mode; /* set up globals for fmatch */
- if(Nnum == 0) { /* first call */
- Nnum = scandir(".", namelist, fmatch, alphasort);
- *NameList = (char **)malloc(Nnum*sizeof(char *));
- for (ii=0; ii<Nnum; ii++) {
- (*NameList)[ii] = (char *)malloc((*namelist)[ii]->d_namlen+1);
- strcpy((*NameList)[ii],(*namelist)[ii]->d_name);
- }
- ii = 0;
- }
- if(ii >= Nnum) { /* all out of files */
- if(Nnum) { /* there were some files found */
- freedir(namelist);
- }
- Nnum = 0;
- return(NULL);
- }
- else {
- return((*NameList)[ii++]);
- }
- }
-
- #define ASTERISK '*' /* The '*' metacharacter */
- #define QUESTION '?' /* The '?' metacharacter */
- #define LEFT_BRACKET '[' /* The '[' metacharacter */
- #define RIGHT_BRACKET ']' /* The ']' metacharacter */
-
- #define IS_OCTAL(ch) (ch >= '0' && ch <= '7')
-
- typedef INT BOOLEAN;
- #define VOID short
- #define TRUE 1
- #define FALSE 0
- #define EOS '\000'
-
- static BOOLEAN do_list ();
- static char nextch ();
- static VOID list_parse ();
-
-
- /*
- * FUNCTION
- *
- * match test string for wildcard match
- *
- * SYNOPSIS
- *
- * BOOLEAN match (string, pattern)
- * register char *string;
- * register char *pattern;
- *
- * DESCRIPTION
- *
- * Test string for match using pattern. The pattern may
- * contain the normal shell metacharacters for pattern
- * matching. The '*' character matches any string,
- * including the null string. The '?' character matches
- * any single character. A list of characters enclosed
- * in '[' and ']' matches any character in the list.
- * If the first character following the beginning '['
- * is a '!' then any character not in the list is matched.
- *
- */
-
-
- /*
- * PSEUDO CODE
- *
- * Begin match
- * Switch on type of pattern character
- * Case ASTERISK:
- * Attempt to match asterisk
- * Break
- * Case QUESTION MARK:
- * Attempt to match question mark
- * Break
- * Case EOS:
- * Match is result of EOS on string test
- * Break
- * Case default:
- * If explicit match then
- * Match is result of submatch
- * Else
- * Match is FALSE
- * End if
- * Break
- * End switch
- * Return result of match test
- * End match
- *
- */
-
- static BOOLEAN match (string, pattern)
- register char *string;
- register char *pattern;
- {
- register BOOLEAN ismatch;
-
- ismatch = FALSE;
- switch (*pattern) {
- case ASTERISK:
- pattern++;
- do {
- ismatch = match (string, pattern);
- } while (!ismatch && *string++ != EOS);
- break;
- case QUESTION:
- if (*string != EOS) {
- ismatch = match (++string, ++pattern);
- }
- break;
- case EOS:
- if (*string == EOS) {
- ismatch = TRUE;
- }
- break;
- case LEFT_BRACKET:
- if (*string != EOS) {
- ismatch = do_list (string, pattern);
- }
- break;
- default:
- if (tolower(*string) == tolower(*pattern))
- {
- string++;
- pattern++;
- ismatch = match (string, pattern);
- } else {
- ismatch = FALSE;
- }
- break;
- }
- return (ismatch);
- }
-
-
- /*
- * FUNCTION
- *
- * do_list process a list and following substring
- *
- * SYNOPSIS
- *
- * static BOOLEAN do_list (string, pattern)
- * register char *string;
- * register char *pattern;
- *
- * DESCRIPTION
- *
- * Called when a list is found in the pattern. Returns
- * TRUE if the current character matches the list and
- * the remaining substring matches the remaining pattern.
- *
- * Returns FALSE if either the current character fails to
- * match the list or the list matches but the remaining
- * substring and subpattern's don't.
- *
- * RESTRICTIONS
- *
- * The mechanism used to match characters in an inclusive
- * pair (I.E. [a-d]) may not be portable to machines
- * in which the native character set is not ASCII.
- *
- * The rules implemented here are:
- *
- * (1) The backslash character may be
- * used to quote any special character.
- * I.E. "\]" and "\-" anywhere in list,
- * or "\!" at start of list.
- *
- * (2) The sequence \nnn becomes the character
- * given by nnn (in octal).
- *
- * (3) Any non-escaped ']' marks the end of list.
- *
- * (4) A list beginning with the special character
- * '!' matches any character NOT in list.
- * The '!' character is only special if it
- * is the first character in the list.
- *
- */
-
-
- /*
- * PSEUDO CODE
- *
- * Begin do_list
- * Default result is no match
- * Skip over the opening left bracket
- * If the next pattern character is a '!' then
- * List match gives FALSE
- * Skip over the '!' character
- * Else
- * List match gives TRUE
- * End if
- * While not at closing bracket or EOS
- * Get lower and upper bounds
- * If character in bounds then
- * Result is same as sense flag.
- * Skip over rest of list
- * End if
- * End while
- * If match found then
- * If not at end of pattern then
- * Call match with rest of pattern
- * End if
- * End if
- * Return match result
- * End do_list
- *
- */
-
- static BOOLEAN do_list (string, pattern)
- register char *string;
- char *pattern;
- {
- register BOOLEAN ismatch;
- register BOOLEAN if_found;
- register BOOLEAN if_not_found;
- auto char lower;
- auto char upper;
-
- pattern++;
- if (*pattern == '!') {
- if_found = FALSE;
- if_not_found = TRUE;
- pattern++;
- } else {
- if_found = TRUE;
- if_not_found = FALSE;
- }
- ismatch = if_not_found;
- while (*pattern != ']' && *pattern != EOS) {
- list_parse (&pattern, &lower, &upper);
- if (*string >= lower && *string <= upper) {
- ismatch = if_found;
- while (*pattern != ']' && *pattern != EOS) {pattern++;}
- }
- }
- if (*pattern++ != ']') {
- fprintf (stderr, "warning - character class error\n");
- } else {
- if (ismatch) {
- ismatch = match (++string, pattern);
- }
- }
- return (ismatch);
- }
-
-
- /*
- * FUNCTION
- *
- * list_parse parse part of list into lower and upper bounds
- *
- * SYNOPSIS
- *
- * static VOID list_parse (patp, lowp, highp)
- * char **patp;
- * char *lowp;
- * char *highp;
- *
- * DESCRIPTION
- *
- * Given pointer to a pattern pointer (patp), pointer to
- * a place to store lower bound (lowp), and pointer to a
- * place to store upper bound (highp), parses part of
- * the list, updating the pattern pointer in the process.
- *
- * For list characters which are not part of a range,
- * the lower and upper bounds are set to that character.
- *
- */
-
- static VOID list_parse (patp, lowp, highp)
- char **patp;
- char *lowp;
- char *highp;
- {
- *lowp = nextch (patp);
- if (**patp == '-') {
- (*patp)++;
- *highp = nextch (patp);
- } else {
- *highp = *lowp;
- }
- }
-
-
- /*
- * FUNCTION
- *
- * nextch determine next character in a pattern
- *
- * SYNOPSIS
- *
- * static char nextch (patp)
- * char **patp;
- *
- * DESCRIPTION
- *
- * Given pointer to a pointer to a pattern, uses the pattern
- * pointer to determine the next character in the pattern,
- * subject to translation of backslash-char and backslash-octal
- * sequences.
- *
- * The character pointer is updated to point at the next pattern
- * character to be processed.
- *
- */
-
- static char nextch (patp)
- char **patp;
- {
- register char ch;
- register char chsum;
- register INT count;
-
- ch = *(*patp)++;
- if (ch == '\\') {
- ch = *(*patp)++;
- if (IS_OCTAL (ch)) {
- chsum = 0;
- for (count = 0; count < 3 && IS_OCTAL (ch); count++) {
- chsum *= 8;
- chsum += ch - '0';
- ch = *(*patp)++;
- }
- (*patp)--;
- ch = chsum;
- }
- }
- return (ch);
- }
-
- /*
- * Filename match - here, *.* matches everything
- */
-
- BOOLEAN fmatch (direntry)
- struct direct *direntry;
- {
- char *ptr,*string;
-
- string = direntry->d_name;
-
- if(!strcmp(pattern, "") || !strcmp(pattern, "*.*"))
- return(1);
- return(match(string, pattern));
- }
-