Received: from j.cc.purdue.edu by VM.CC.PURDUE.EDU ; Sun, 28 Feb 88 01:01:44 EST
Received: by j.cc.purdue.edu (5.54/1.14)
    id AA23523; Sun, 28 Feb 88 00:59:03 EST
To: fys-ma@fintuvm.BITNET
Date: Sun, 28 Feb 88 0:59:00 EST
Subject: posting to: news/comp/sources/amiga/volume3
Organization: Co-Moderators Unlimited.
Path: j.cc.purdue.edu!ahh
From: ahh@j.cc.purdue.edu (Brent L. Woods)
Newsgroups: comp.sources.amiga
Subject: find--A directory-scanning, file-finding program.
Keywords: tested, part 1 of 1
Message-Id: <6527@j.cc.purdue.edu>
Date: 28 Feb 88 05:28:01 GMT
Organization: Co-Moderators Unlimited.
Lines: 939
Approved: ahh@j.cc.purdue.edu  (Brent Woods)
 
Program Name:  find
Submitted By:  munnari!bhpese.oz.au!rodney@uunet.uu.net (Rodney Lewis)
Summary:  A file-finding program (like the UNIX program of the same
          name).
Poster Boy:  Brent Woods  (ahh@j.cc.purdue.edu)
Tested.  Part 1 of 1
 
NOTES:  Works as advertised.  The documentation is in the posting
        in comp.binaries.amiga (and is rather important, too).
 
 
[[ NOTES2:  I had to "reshar" this bu hand, because some long lines
            were spilled over to next line during MAIL transmission.
            As a result, all of those length tests may be false :-(
                                                   /Matti Aarnio    ]]
 
Brent Woods, Co-Moderator, comp.{sources,binaries}.amiga
 
USENET:  ...!j.cc.purdue.edu!ahh     ARPANET:  ahh@j.cc.purdue.edu
BITNET:  PODUM@PURCCVM               PHONE:  +1 (317) 743-8421
USNAIL:  320 Brown St., #406  /  West Lafayette, IN  47906
 
================================================================
 
    This is a "find" program for the Amiga.
 
    This is the source and makefile, the uuencoded binary and doc
    files are in another posting.
 
                        Rodney Lewis
 
                    ACSnet:    rodney@bhpese.oz
 
#    This is a shell archive.
#    Remove everything above and including the cut line.
#    Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#    Run the following text with /bin/sh to create:
#    README
#    find.c
#    makefile
# This archive created: Wed Jan 27 08:12:12 1988
echo shar: extracting README
sed 's/^XX//' << \SHAR_EOF > README
XX
XX    find - Version 1.0 - a program to find files based on a
XX    set of various criterion. (see doc file for usage).
XX
XX    It compiles under Manx 3.4b but will also compile under
XX    3.4a which will give a few warning messages that can be
XX    ignored.
XX
XX    Any bug reports, suggestions to:
XX
XX    ACSnet:        rodney@bhpese.oz
SHAR_EOF
if test 299 -ne "`wc -c README`"
then
echo shar: error transmitting README '(should have been 299 characters)'
fi
echo shar: extracting find.c
sed 's/^XX//' << \SHAR_EOF > find.c
XX/**********************************************************************/
XX/*                                                                    */
XX/* find - Version 1.0                                                 */
XX/*                                                                    */
XX/* Copyright (c) 1988 - Rodney Lewis                                  */
XX/* This program is freely copyable and distributable. All copyrights  */
XX/* are reserved by the author. You may give copies of this program to */
XX/* anyone you wish but you may not sell it.                           */
XX/*                                                                    */
XX/* Pattern matching routine taken from Matt Dillon's csh program;     */
XX/* reproduced by permission.                                          */
XX/*                                                                    */
XX/**********************************************************************/
XX
XX/**********************************************************************/
XX/*                                                                    */
XX/* find    - searches the directory hierachy looking for files that   */
XX/*           match a given boolean expression. Based  on  the  U**X   */
XX/*           find command.                                            */
XX/*                                                                    */
XX/**********************************************************************/
XX
XX#include <exec/types.h>
XX#include <exec/memory.h>
XX#include <libraries/dosextens.h>
XX#include <stdio.h>
XX#include <functions.h>
XX
XX#define MAXARGS        20
XX#define NULL_PRIM    (struct primary *) NULL
XX#define EQ(x,y)        (strcmp(x, y) == 0)
XX#define PROTECTION    (FIBF_READ | FIBF_WRITE | FIBF_EXECUTE | FIBF_DELETE)
XX
XX/* boolean expression node structure */
XX
XXstruct node {
XX    unsigned long        type;
XX    struct node    *first;
XX    struct node    *second;
XX};
XX
XX/* Node types - must be different from primary node types (below) */
XX
XX#define OR    0x000000ff
XX#define AND    0x0000ff00
XX#define NOT    0x00ff0000
XX
XX/* structure to hold interpreted primary information */
XX
XXstruct primary {
XX    unsigned long        type;
XX    unsigned long        size;
XX    char                *data[MAXARGS];
XX};
XX
XX/* start of compiled expression tree */
XX
XXstruct node *node_head;
XX
XX/* Primary types */
XX
XX#define PRINT    0x00000001
XX#define NAME    0x00000002
XX#define SIZE    0x00000004
XX#define TYPE    0x00000008
XX#define EXEC    0x00000010
XX#define NEWER    0x00000020
XX#define MTIME    0x00000040
XX#define PERM    0x00000080
XX#define PRIMS    0x0000ffff
XX
XX/* type qualifiers */
XX
XX#define DIRECT    0x00010000        /* directory for -type */
XX#define PLAIN    0x00020000        /* plain file for -type */
XX#define PROMPT    0x00040000        /* prompt for EXEC */
XX#define LT        0x00080000        /* greater than */
XX#define GT        0x00100000        /* less than */
XX#define CHAR    0x00200000        /* use characters in -size check */
XX#define QUALS    0xffff0000
XX
XXint breakflag = FALSE;
XX
XXchar path[80] = "";                /* memory to hold full path name */
XXstruct DateStamp date;
XX
XX/* manx releases the memory allocated by calloc when you call exit() */
XX
XXextern char        *calloc();
XX
XXmain(argc, argv)
XXint argc;
XXchar *argv[];
XX{
XX    register struct FileLock *start;
XX    register i;
XX    extern struct node *compile();
XX
XX    DateStamp(&date);
XX
XX    /* must be at least three arguments */
XX
XX    if (argc < 3) {
XX        fprintf(stderr, "Usage: find <path-list> <expression>\n");
XX        exit(1);
XX    }
XX
XX    /* find the start of the boolean expression */
XX
XX   for (i = 1 ; argv[i][0] != '-' && argv[i][0] != '!' && argv[i][0] != '(' ;\
XXi++);
XX    if (i == 1) {
XX        /* no path name list */
XX        fprintf(stderr, "Usage: find <path-list> <expression>\n");
XX        exit(1);
XX    }
XX
XX    /* compile the boolean expression */
XX
XX    if (node_head = compile(argc - i, &argv[i])) {
XX
XX        /* search each path-name specified */
XX
XX       for (i = 1 ; argv[i][0] != '-' && argv[i][0] != '!' && argv[i][0] != \
XX'(' ; ++i) {
XX            start = Lock(argv[i], ACCESS_READ);
XX            if (start == NULL) {
XX                fprintf(stderr, "can't access '%s'\n", argv[i]);
XX                continue;
XX            }
XX
XX            search(start);
XX            UnLock(start);
XX        }
XX    }
XX
XX    exit(0);
XX}
XX
XX/* search the given directory and for each file
XX * execute the boolean expression.
XX */
XX
XXsearch(lock)
XXregister struct FileLock *lock;
XX{
XX    register struct FileInfoBlock *fib;
XX    register struct FileLock *nlock;
XX    char *prev, file[80];
XX
XX    fib = (struct FileInfoBlock *) AllocMem((long) sizeof(struct\
XX FileInfoBlock), MEMF_CLEAR);
XX    if (fib == NULL) {
XX        fprintf(stderr, "can't allocate file info block\n");
XX        return(0);
XX    }
XX
XX    /* save current position in full path name */
XX
XX    prev = path + strlen(path);
XX
XX    if (*path == '\0' && pwd(ParentDir(lock)) == 0) {
XX        FreeMem(fib, (long) sizeof(struct FileInfoBlock));
XX        return(0);
XX    }
XX
XX    /* examine initial path name */
XX
XX    if (Examine(lock, fib)) {
XX
XX        /* execute the expression on the inital path */
XX
XX        execute(node_head, fib);
XX
XX        if (fib->fib_DirEntryType > 0) {
XX
XX            /* set up printable path name */
XX
XX            if (*path) {
XX                strcat(path, fib->fib_FileName);
XX                strcat(path, "/");
XX            }
XX            else if (pwd(lock) == 0) {
XX                *prev = '\0';
XX                FreeMem(fib, (long) sizeof(struct FileInfoBlock));
XX                return(0);
XX            }
XX        }
XX
XX        else {
XX
XX            /* if initial path name is not a directory then we just return */
XX
XX            *prev = '\0';
XX            FreeMem(fib, (long) sizeof(struct FileInfoBlock));
XX            return(0);
XX        }
XX
XX        /* examine directory contents */
XX
XX        while(ExNext(lock, fib)) {
XX            if (breakflag) break;
XX
XX            /* recurse if we have found a directory */
XX
XX            if (fib->fib_DirEntryType > 0) {
XX                strcpy(file, path);
XX                strcat(file, fib->fib_FileName);
XX                nlock = Lock(file, ACCESS_READ);
XX                if (nlock == NULL)
XX                    fprintf(stderr, "locking error - %s\n", file);
XX                else {
XX                    search(nlock);
XX                    UnLock(nlock);
XX                }
XX            }
XX            else
XX                execute(node_head, fib);
XX
XX            if (SetSignal(0L, 0L) & SIGBREAKF_CTRL_C) {
XX                breakflag = TRUE;
XX                break;
XX            }
XX        }
XX    }
XX
XX    *prev = '\0';
XX    FreeMem(fib, (long) sizeof(struct FileInfoBlock));
XX}
XX
XX/* execute the boolean expression on the given file */
XX
XXexecute(cnode, fib)
XXstruct node *cnode;
XXstruct FileInfoBlock *fib;
XX{
XX    register struct primary *prim;
XX    register long checksize;
XX    register j;
XX    register struct DateStamp *ds;
XX    char file[80], ok[10];
XX    char *av[MAXARGS];
XX
XX    /* check node type */
XX
XX    if (cnode->type == AND)
XX        if  (execute(cnode->first, fib))
XX            return(execute(cnode->second, fib));
XX        else
XX            return(0);
XX
XX    else if (cnode->type == OR)
XX        if  (execute(cnode->first, fib))
XX            return(1);
XX        else
XX            return(execute(cnode->second, fib));
XX
XX    else if (cnode->type == NOT)
XX        return(!execute(cnode->first, fib));
XX
XX    else {
XX
XX        /* we have an actual primary */
XX
XX        prim = (struct primary *) cnode;
XX        switch (prim->type & PRIMS) {
XX
XX        case PRINT:
XX
XX            if (*path)
XX                printf("%s%s\n", path, fib->fib_FileName);
XX            else
XX                printf("%s:\n", fib->fib_FileName);
XX            return(1);
XX
XX        case NAME:
XX
XX            if (compare_ok(prim->data[0], fib->fib_FileName))
XX                return(1);
XX            else
XX                return(0);
XX
XX        case SIZE:
XX
XX            if (prim->type & CHAR)
XX                checksize = fib->fib_Size;
XX            else
XX                checksize = fib->fib_NumBlocks;
XX
XX            if (((prim->type & GT) && (checksize > prim->size) ) ||
XX                ((prim->type & LT) && (checksize < prim->size) ) ||
XX                ((prim->type & (GT | LT)) == 0 && (checksize == prim->size)))
XX                return(1);
XX            else
XX                return(0);
XX
XX        case TYPE:
XX
XX            switch (prim->type & QUALS | (fib->fib_DirEntryType > 0)) {
XX
XX            case DIRECT:
XX            case (PLAIN | 1):
XX                return(0);
XX
XX            default:
XX                return(1);
XX            }
XX
XX        case EXEC:
XX
XX            for (j = 0 ; prim->data[j] ; j++)
XX                if (EQ("{}", prim->data[j])) {
XX                    strcpy(file, path);
XX                    strcat(file, fib->fib_FileName);
XX                    av[j] = file;
XX                }
XX                else
XX                    av[j] = prim->data[j];
XX            av[j] = NULL;
XX
XX            if (!(prim->type & PROMPT) || (pr_cmd(av) && gets(ok) &&
XX                 ((ok[0] == 'y') || (ok[0] == 'Y')))) {
XX                if (fexecv(av[0], av) == -1)
XX                    return(0);
XX                else if (wait())
XX                    return(0);
XX                else
XX                    return(1);
XX            }
XX
XX        case NEWER:
XX
XX            ds = (struct DateStamp *) prim->data[0];
XX            if (fib->fib_Date.ds_Days > ds->ds_Days)
XX                return(1);
XX            else if (fib->fib_Date.ds_Days == ds->ds_Days &&
XX                     fib->fib_Date.ds_Minute > ds->ds_Minute)
XX                return(1);
XX            else if (fib->fib_Date.ds_Days == ds->ds_Days &&
XX                     fib->fib_Date.ds_Minute == ds->ds_Minute &&
XX                     fib->fib_Date.ds_Tick > ds->ds_Tick)
XX                return(1);
XX            else
XX                return(0);
XX
XX        case MTIME:
XX
XX            checksize = date.ds_Days - fib->fib_Date.ds_Days;
XX
XX            if (((prim->type & GT) && (checksize > prim->size) ) ||
XX                ((prim->type & LT) && (checksize < prim->size) ) ||
XX                ((prim->type & (GT | LT)) == 0 && (checksize == prim->size)))
XX                return(1);
XX            else
XX                return(0);
XX
XX        case PERM:
XX
XX            if ((fib->fib_Protection & PROTECTION) == prim->size)
XX                return(1);
XX            else
XX                return(0);
XX
XX        }
XX        return(0);
XX    }
XX}
XX
XX/* print the command to be executed on the screen */
XX
XXpr_cmd(av)
XXchar *av[];
XX{
XX    register j;
XX
XX    printf("< ");
XX    for (j = 0 ; av[j] ; j++) printf("%s ", av[j]);
XX    printf("> ? ");
XX    return(1);
XX}
XX
XX/* compile the boolean expression: returns a pointer to the start
XX * of the compiled expression tree, or NULL if a failure occurs.
XX */
XX
XXstruct node *
XXcompile(argc, argv)
XXint argc;
XXchar *argv[];
XX{
XX    register i, j, scan;
XX    register struct primary *prim;
XX    register struct node *node_head = (struct node *) NULL, *tmp_node;
XX
XX    for(i = 0 ; i < argc ; i++) {
XX
XX        prim = (struct primary *) calloc(1, sizeof(struct primary));
XX        if (prim == NULL_PRIM) {
XX            fprintf(stderr, "out memory in primary interpretation\n");
XX            exit(5);
XX        }
XX
XX
XX        if (EQ("-o", argv[i])) {
XX            free(prim);
XX
XX            /* -o cannot be the first argument */
XX
XX            if (node_head == NULL_PRIM) {
XX                fprintf(stderr, "misplaced 'or' operator ... ignored\n");
XX                continue;
XX            }
XX
XX            else {
XX
XX                /* create OR node */
XX
XX                tmp_node = (struct node *) calloc(1, sizeof(struct node));
XX                if (tmp_node == NULL) {
XX                  fprintf(stderr, "out of memory in expression compilation");
XX                    exit(5);
XX                }
XX                tmp_node->type = OR;
XX                tmp_node->first = node_head;
XX
XX                /* compile rest of expression and attach it to OR node */
XX
XX                if ((tmp_node->second = compile(argc - i - 1, argv + i + 1))\
XX == NULL) {
XX                    free(tmp_node);
XX                    return(node_head);
XX                }
XX                else
XX                    return(tmp_node);
XX            }
XX        }
XX
XX        else if (EQ("(", argv[i])) {
XX            free(prim);
XX
XX            /* scan to matching brackets */
XX
XX           for (j = 0, scan = 0 ; ++i < argc && (!EQ(")", argv[i]) || scan !=\
XX 0) ; j++) {
XX                if (EQ("(", argv[i])) scan++;
XX                if (EQ(")", argv[i])) scan--;
XX            }
XX
XX            if (i >= argc) {
XX                fprintf(stderr, "unmatched bracket\n");
XX                exit(5);
XX            }
XX
XX            if (j == 0) {
XX                fprintf(stderr, "empty brackets ... ignored\n");
XX                continue;
XX            }
XX
XX            /* compile what is in the brackets */
XX
XX            if ((prim = (struct primary *) compile(j, argv + i - j)) == NULL)
XX                continue;
XX        }
XX
XX        else if (EQ("!", argv[i])) {
XX            if (++i >= argc) {
XX                fprintf(stderr, "trailing '!' ignored\n");
XX                continue;
XX            }
XX            if (EQ("-o", argv[i])) {
XX                fprintf(stderr, "illegal 'or' operator placement\n");
XX                exit(5);
XX            }
XX
XX            tmp_node = (struct node *) calloc(1, sizeof(struct node));
XX            if (tmp_node == NULL) {
XX                fprintf(stderr, "out of memory in expression compilation\n");
XX                exit(5);
XX            }
XX            tmp_node->type = NOT;
XX
XX            if (EQ("(", argv[i])) {
XX
XX                /* scan to matching bracket */
XX
XX                for (j = 0, scan = 0 ; ++i < argc && (!EQ(")", argv[i]) ||\
XX scan != 0) ; j++) {
XX                    if (EQ("(", argv[i])) scan++;
XX                    if (EQ(")", argv[i])) scan--;
XX                }
XX
XX                if (i >= argc) {
XX                    fprintf(stderr, "unmatched bracket\n");
XX                    exit(5);
XX                }
XX
XX                if (j == 0) {
XX                    fprintf(stderr, "empty brackets ... ignored\n");
XX                    free(tmp_node);
XX                    continue;
XX                }
XX
XX                /* compile what is in the brackets */
XX
XX                if ((tmp_node->first = compile(j, argv + i - j)) == NULL)
XX                    continue;
XX            }
XX            else {
XX                tmp_node->first = (struct node *) prim;
XX                i += interpret(prim, argc - i, argv + i);
XX            }
XX            prim = (struct primary *) tmp_node;
XX        }
XX
XX        else
XX            i += interpret(prim, argc - i, argv + i);
XX
XX        /* attach interpreted primary to expression tree */
XX
XX        if (node_head == NULL)
XX            node_head = (struct node *) prim;
XX        else {
XX            tmp_node = (struct node *) calloc(1, sizeof(struct node));
XX            if (tmp_node == NULL) {
XX                fprintf(stderr, "out of memory in expression compilation\n");
XX                exit(5);
XX            }
XX            tmp_node->type   = AND;
XX            tmp_node->first  = node_head;
XX            tmp_node->second = (struct node *) prim;
XX            node_head        = tmp_node;
XX        }
XX    }
XX
XX    return(node_head);
XX}
XX
XX/* interpret a primary */
XX
XXinterpret(prim, argc, argv)
XXstruct primary *prim;
XXchar *argv[];
XX{
XX    register i, j;
XX    register struct FileLock *lock;
XX    register struct FileInfoBlock *fib;
XX    register struct DateStamp *ds;
XX    char *numstr;
XX    extern unsigned long atol();
XX
XX    for (i = 0 ; i < argc ; i++) {
XX
XX        if (EQ("-print", argv[i]))
XX            prim->type = PRINT;
XX
XX        else if (EQ("-name", argv[i])) {
XX            prim->type = NAME;
XX            prim->data[0] = argv[++i];
XX        }
XX
XX        else if (EQ("-size", argv[i])) {
XX            prim->type = SIZE;
XX
XX            /* get required size */
XX
XX            numstr = argv[++i];
XX
XX            if (*numstr == '+') {
XX                prim->type |= GT;
XX                numstr++;
XX            }
XX
XX            else if (*numstr == '-') {
XX                prim->type |= LT;
XX                numstr++;
XX            }
XX
XX            if (numstr[strlen(numstr) - 1] == 'c') {
XX                prim->type |= CHAR;
XX                numstr[strlen(numstr) - 1] == '\0';
XX            }
XX
XX            prim->size = atol(numstr);
XX        }
XX
XX        else if (EQ("-type", argv[i])) {
XX            prim->type = TYPE;
XX            if (EQ(argv[++i], "d"))
XX                prim->type |= DIRECT;
XX            else if (EQ(argv[i], "f"))
XX                prim->type |= PLAIN;
XX            else {
XX                fprintf(stderr, "illegal file type specified\n");
XX                exit(5);
XX            }
XX        }
XX
XX        else if (EQ("-exec", argv[i])) {
XX            prim->type = EXEC;
XX
XX            /* scan to ending ';', saving pointers to arguments */
XX
XX            for (j=0 ; (j<MAXARGS) && (++i < argc) && !EQ(";",argv[i]) ; j++)
XX                prim->data[j] = argv[i];
XX
XX            if (i >= argc) {
XX                fprintf(stderr, "no ending ';' on command\n");
XX                exit(5);
XX            }
XX
XX            else if (j >= MAXARGS) {
XX                fprintf(stderr, "command too long\n");
XX                exit(5);
XX            }
XX
XX            else
XX                argv[j] = NULL;
XX        }
XX
XX        else if (EQ("-ok", argv[i])) {
XX            prim->type = EXEC | PROMPT;
XX
XX            /* scan to ending ';', saving pointers to arguments */
XX
XX            for (j=0 ; (j<MAXARGS) && (++i < argc) && !EQ(";",argv[i]) ; j++)
XX                prim->data[j] = argv[i];
XX
XX            if (i >= argc) {
XX                fprintf(stderr, "no ending ';' on command\n");
XX                exit(5);
XX            }
XX
XX            else if (j >= MAXARGS) {
XX                fprintf(stderr, "command too long\n");
XX                exit(5);
XX            }
XX
XX            else
XX                argv[j] = NULL;
XX        }
XX
XX        else if (EQ("-newer", argv[i])) {
XX            prim->type = NEWER;
XX
XX            if (lock = Lock(argv[++i])) {
XX                fib = (struct FileInfoBlock *) AllocMem((long) sizeof(struct\
XX FileInfoBlock), MEMF_CLEAR);
XX                if (fib == NULL) {
XX                    fprintf(stderr, "no mem for -newer test\n");
XX                    UnLock(lock);
XX                    exit(5);
XX                }
XX
XX                if (Examine(lock, fib) == 0) {
XX                    fprintf(stderr, "could not examine %s\n", argv[i]);
XX                    FreeMem(fib, (long) sizeof(struct FileInfoBlock));
XX                    UnLock(lock);
XX                    exit(5);
XX                }
XX
XX                /* save date stamp of given file */
XX
XX                ds = (struct DateStamp *) calloc(1, sizeof(struct DateStamp));
XX                if (ds == NULL) {
XX                    fprintf(stderr, "no mem for DateStamp on %s\n", argv[i]);
XX                    FreeMem(fib, (long) sizeof(struct FileInfoBlock));
XX                    UnLock(lock);
XX                    exit(5);
XX                }
XX
XX                prim->data[0] = (char *) ds;
XX                *ds = fib->fib_Date;
XX
XX                FreeMem(fib, (long) sizeof(struct FileInfoBlock));
XX                UnLock(lock);
XX            }
XX
XX            else {
XX                fprintf(stderr, "unable to access %s\n", argv[i]);
XX                exit(5);
XX            }
XX        }
XX
XX        else if (EQ("-mtime", argv[i])) {
XX            prim->type = MTIME;
XX
XX            /* get required number of days */
XX
XX            numstr = argv[++i];
XX
XX            if (*numstr == '+') {
XX                prim->type |= GT;
XX                numstr++;
XX            }
XX            else if (*numstr == '-') {
XX                prim->type |= LT;
XX                numstr++;
XX            }
XX
XX            prim->size = atol(numstr);
XX        }
XX
XX        else if (EQ("-perm", argv[i])) {
XX            prim->type = PERM;
XX            prim->size = PROTECTION;
XX
XX            /* assemble desired protection bits */
XX
XX            for(i++, j = 0 ; argv[i][j] ; j++) {
XX                switch(argv[i][j]) {
XX
XX                case 'n':
XX                    prim->size = PROTECTION;
XX                    return(i);
XX
XX                case 'r':
XX                    prim->size &= ~FIBF_READ;
XX                    break;
XX
XX                case 'w':
XX                    prim->size &= ~FIBF_WRITE;
XX                    break;
XX
XX                case 'e':
XX                    prim->size &= ~FIBF_EXECUTE;
XX                    break;
XX
XX                case 'd':
XX                    prim->size &= ~FIBF_DELETE;
XX                    break;
XX
XX                default:
XX                    fprintf(stderr, "unknown code '%c' ... ignored\n",\
XX argv[i][j]);
XX                    break;
XX                }
XX            }
XX        }
XX
XX        else {
XX            fprintf(stderr, "unknown primary: %s\n", argv[i]);
XX            exit(5);
XX        }
XX
XX        return(i);
XX    }
XX}
XX
XX/* find the full path name of the given lock */
XX
XXpwd(dir)
XXregister struct FileLock *dir;
XX{
XX    register struct FileLock *par;
XX    register struct FileInfoBlock *fib;
XX
XX    if (dir == NULL) {
XX        *path = '\0';
XX        return(1);
XX    }
XX
XX    fib = (struct FileInfoBlock *) AllocMem((long) sizeof(struct\
XX FileInfoBlock), MEMF_CLEAR);
XX    if (fib == NULL) {
XX        fprintf(stderr, "pwd: can't allocate a FileInfoBlock\n");
XX        return(0);
XX    }
XX
XX    if (!Examine(dir, fib)) {
XX        fprintf(stderr, "pwd: examine failed\n");
XX        FreeMem(fib, (long) sizeof(struct FileInfoBlock));
XX        return(0);
XX    }
XX
XX    if (par = ParentDir(dir)) {
XX
XX        /* find full path name of parent */
XX
XX        if (pwd(par) == 0) {
XX            FreeMem(fib, (long) sizeof(struct FileInfoBlock));
XX            return(0);
XX        }
XX
XX        /* add current name */
XX
XX        strcat(path, fib->fib_FileName);
XX        strcat(path, "/");
XX    }
XX    else {
XX
XX        /* found the root name */
XX
XX        strcpy(path, fib->fib_FileName);
XX        strcat(path, ":");
XX    }
XX
XX    FreeMem(fib, (long) sizeof(struct FileInfoBlock));
XX    return(1);
XX}
XX
XX/*
XX * Compare a wild card name with a normal name.
XX * Taken from Matt Dillon's csh program.
XX */
XX
XX#define MAXB   8
XX
XXcompare_ok(wild, name)
XXchar *wild, *name;
XX{
XX   register char *w = wild;
XX   register char *n = name;
XX   char *back[MAXB][2];
XX   register char s1, s2;
XX   int    bi = 0;
XX
XX   while (*n || *w) {
XX      switch (*w) {
XX      case '*':
XX     if (bi == MAXB) {
XX        fprintf(stderr,"Too many levels of '*'\n");
XX        return (0);
XX     }
XX     back[bi][0] = w;
XX     back[bi][1] = n;
XX     ++bi;
XX     ++w;
XX     continue;
XXgoback:
XX     --bi;
XX     while (bi >= 0 && *back[bi][1] == '\0')
XX        --bi;
XX     if (bi < 0)
XX        return (0);
XX     w = back[bi][0] + 1;
XX     n = ++back[bi][1];
XX     ++bi;
XX     continue;
XX      case '?':
XX     if (!*n) {
XX        if (bi)
XX           goto goback;
XX        return (0);
XX     }
XX     break;
XX      default:
XX     s1 = (*n >= 'A' && *n <= 'Z') ? *n - 'A' + 'a' : *n;
XX     s2 = (*w >= 'A' && *w <= 'Z') ? *w - 'A' + 'a' : *w;
XX     if (s1 != s2) {
XX        if (bi)
XX           goto goback;
XX        return (0);
XX     }
XX     break;
XX      }
XX      if (*n)  ++n;
XX      if (*w)  ++w;
XX   }
XX   return (1);
XX}
SHAR_EOF
if test 18071 -ne "`wc -c find.c`"
then
echo shar: error transmitting find.c '(should have been 18071 characters)'
fi
echo shar: extracting makefile
sed 's/^XX//' << \SHAR_EOF > makefile
XXOBJ = find.o
XX
XX.c.o:
XX    cc -E200 $*.c
XX
XXfind:    Makefile $(OBJ)
XX    ln -o find $(OBJ) -lc
XX
XXfind.o:    find.c
XX
XXshar:
XX    shar -a README find.c makefile > find.shar1
XX    shar -a find.doc find.uue > find.shar2
SHAR_EOF
if test 189 -ne "`wc -c makefile`"
then
echo shar: error transmitting makefile '(should have been 189 characters)'
fi
#    End of shell archive
exit 0
