


/*
        A recursive descent main to search directories and subs
        with wildcard and path capabilities -> then pass the
        path name to a user supplied function called "subfunc".
        2 switches are presently supported: /t for totals and
        /s for subdirectories.
*/

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <dos.h>

#define MAX_SUB 128             /* max subdirectory width for stack */
                                                /* subfunc is user module to link to */
extern  void subfunc(char *path);

int main(int argc, char **argv)
{
struct find_t *fib;
char *path, *drive, *dir, *fname, *ext;
char *tmppath, *tmpdir, *tmpargv, *subfifo;
char (*subfifoptr)[_MAX_FNAME];
int total = 0;
                                /* malloc so we don't blow up the stack */
if (!((fib = malloc(sizeof(struct find_t))) &&
                        (path = malloc(_MAX_PATH)) &&
                        (drive = malloc(_MAX_DRIVE)) &&
                        (dir = malloc(_MAX_DIR)) &&
                        (fname = malloc(_MAX_FNAME)) &&
                        (ext = malloc(_MAX_EXT)) &&
                        (tmpdir = malloc(_MAX_DIR)) &&
                        (tmppath = malloc(_MAX_PATH))))
        {                       /* return resources to DOS */
        free(fib), free(path), free(drive), free(dir);
        free(fname), free(ext), free(tmpdir), free(tmppath);
        printf("NOT ABLE TO MALLOC SPACE!\N");
        exit(-1);
        }

if (argc < 2)
        {                       /* there was no command line argument */
        _splitpath(argv[0], drive, dir, fname, ext);
        printf("\n\t%s <filespec> [/s/t]\n", fname);
        printf("\tFilespec can have DOS wildcards!\n");
        printf("\t/S switch includes subdirectories.\n");
        printf("\t/T switch gives a total.\n");
        }
else
        {
        if (argc > 2 && (strstr(strupr(argv[2]), "/S")))
                {               /* if S switch - do subdirectories first */
                tmpargv = argv[1];      /* save argv[1] for future use */
                if (!(subfifo = *subfifoptr =
                                (char *)malloc(_MAX_FNAME * MAX_SUB)))
                        {               /* return resources to DOS */
                        free(fib), free(path), free(drive), free(dir);
                        free(fname), free(ext), free(tmpdir), free(tmppath);
                        printf("UNABLE TO MALLOC FOR INTERNAL FIFO!\N");
                        exit(-1);
                        }
                _splitpath(argv[1], drive, dir, fname, ext);
                _makepath(path, drive, dir, "*", "*");
                if (!_dos_findfirst(path, _A_SUBDIR, fib))
                        do
                                {
                                if (fib->name[0] != '.' &&
                                                 fib->attrib & _A_SUBDIR)
                                                                /* push on FIFO */
                                        strcpy(*subfifoptr++, fib->name);
                                } while (!_dos_findnext(fib) &&
                                                *subfifoptr <
                                                &subfifo[(_MAX_FNAME - 1) * MAX_SUB]);
                **subfifoptr = NULL;            /* terminate FIFO */
                *subfifoptr = subfifo;  /* reset FIFO pointer */
                while(**subfifoptr)             /* while not at the end */
                        {
                        strcpy(tmpdir, dir);
                        _makepath(path, drive, 
                                        strcat(tmpdir, *subfifoptr++), fname, ext);
                        argv[1] = path;
                                                                /* recursive part of program */
                        total += main(argc, argv);      /* check next level */
                        }
                free(subfifo);
                argv[1] = tmpargv;                              /* restore argv[1] */
                }
                                                                                /* look for files */
        if (!_dos_findfirst(argv[1], _A_NORMAL, fib))
                do
                        {
                        _splitpath(argv[1], drive, dir, fname, ext);
                        strcpy(tmppath, drive);
                        strcat(tmppath, dir);
                                                        /* now call the work function */
                        subfunc(strcat(tmppath, fib->name));
                        total++;
                        } while (!_dos_findnext(fib));
        if (argc > 2 && strstr(strupr(argv[2]), "/T"))
                printf("\ntotal = %d\t%s files\n", total, argv[1]);
        }
                /* return resources to DOS */
free(fib), free(path), free(drive), free(dir);
free(fname), free(ext), free(tmpdir), free(tmppath);

return total;
}
