home *** CD-ROM | disk | FTP | other *** search
- #ifdef CWRU
-
- /* CWRU specific extention(hack :-)
- * Examine each argument given to main,
- * If it is a directory, then expand it
- * to all its component files, recursively
- * till you bottom out.
- * If it is not a directory, then just pass it on.
- *
- * Inputs: argc, argv
- * Outputs: nargc, nargv (calls MAIN(nargc, nargv))
- * To test: compile with -DCASE -DTEST
- * run with a directory as an arg
- * Hacker: JRB
- * Requirements: BSD 4.2/3 specific routines used
- * only tested on Vax BSD 4.3
- *
- * Added -P name prune option at the suggestion of dietz@zhmti
- * Multiple -P's may be given on the command line.
- * -P name may be given anywhere on the command line. -P name
- * will prune the subdirectories named as arguement to -P.
- * ie: when the program is decending the file hierarchy it
- * will not visit the pruned branches.
- * NOTE that the option is -P and not -p
- * (-p is a valid sz option).
- * NOTE that the arguement given to -P can be the name
- * of a file or a directory. In case it is a file,
- * that file is skipped.
- *
- */
-
- /*
- * Expand argc, so that the called MAIN(nargc,nargv) receives only
- * filenames, in nargv[][]
- *
- * WARNING: Contains BSD specific code, tested on BSD4.3 ONLY.
- *
- * Jwahar Bammi
- * usenet: {decvax,cbatt,cbosgd,sun}!cwruecmp!bammi
- * csnet: bammi@case
- * arpa: bammi%case@csnet-relay
- * compuServe: 71515,155
- *
- */
- #include <stdio.h>
-
- #define OK 0
- #define FALSE 0
- #define Realloc realloc
-
- typedef struct _prunelist {
- char *name; /* name of subdirectory to prune */
- struct _prunelist *next; /* ptr to next */
- } PRUNELIST;
-
- static char *ProgName;
- static PRUNELIST *PruneList = (PRUNELIST *)NULL; /* Head of PruneList */
-
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- register int status;
- int nargc = 0;
- char **nargv = (char **)NULL;
- extern int MAIN();
- extern char **CopyToNargv();
- extern PRUNELIST *AddPrune();
-
- ProgName = *argv;
-
- /* copy argv[0] blindly */
- if((nargv = CopyToNargv(*argv, nargc, nargv)) == (char **)NULL)
- return(~OK);
-
- nargc++;
-
- while((--argc) > 0)
- {
- argv++;
- if(**argv == '-')
- {
- /* copy any options except -P */
- if( (*argv)[1] == 'P')
- {
- if((--argc) <= 0)
- {
- fprintf(stderr,"no argument given to -P\n");
- return(~OK);
- }
- if((PruneList = AddPrune(PruneList,*++argv))
- == (PRUNELIST *)NULL)
- return(~OK);
- }
- else
- {
- if((nargv = CopyToNargv(*argv, nargc, nargv))
- == (char **)NULL)
- return(~OK);
- else
- nargc++;
- }
-
- }
- else
- {
- /* If its not on the PruneList then */
- if(!OnPruneList(PruneList, *argv))
- {
- /* if it is a directory, push it */
- if(isdir(*argv))
- {
- if((status = PushDir(*argv)) != OK)
- {
- return(status);
- }
- }
- else
- {
- /* it is NOT a directory, copy to nargv */
- if((nargv = CopyToNargv(*argv, nargc, nargv))
- == (char **)NULL)
- return(~OK);
- else
- nargc++;
- }
- }
- }
- } /* while */
-
- /* process pushed directories if any */
- if((status = ProcessDirs(&nargc, &nargv)) != OK)
- return(status);
- /* else Free the Stack and call MAIN */
- FreeStack();
- return (MAIN(nargc, nargv));
- }
-
- #include <sys/types.h>
- #include <sys/stat.h>
-
- /*
- * is name a directory ?
- *
- */
- int isdir(name)
- char *name;
- {
- struct stat st;
-
- if(stat(name, &st) != 0)
- return (FALSE); /* assume its not a directory */
-
- /* NOTE: the expression below eliminates Sockets.
- (st.st_mode & S_IFMT)& S_IFDIR does not!
- */
- return( ( (st.st_mode & S_IFMT) == S_IFDIR) );
- }
-
- /*
- * Expand nargv by an element and copy a String into the new element
- *
- */
- char **CopyToNargv(string, nargc, nargv)
- char *string;
- int nargc;
- char **nargv;
- {
- extern char *malloc(), *Realloc(), *strcpy();
- extern int strlen();
-
- /* expand nargv by 1 element */
- if(nargv == (char **)NULL)
- /* do it with malloc for the first one */
- nargv = (char **)malloc(sizeof(char **));
- else
- /* do it with Realloc for others */
- nargv = (char **)Realloc(nargv, (nargc+1)*sizeof(char **));
-
- if(nargv == (char **)NULL)
- {
- /* failed to get memory */
- perror(ProgName);
- return ((char **)NULL);
- }
-
- /* Get mem for string */
- if(( nargv[nargc] = malloc(strlen(string)+1)) == (char *)NULL)
- {
- /* failed to get memory */
- perror(ProgName);
- return ((char **)NULL);
- }
-
- /* copy string into nargv[nargc] */
- (void)strcpy( nargv[nargc], string);
- return(nargv);
- }
-
- static char **Stack = (char **)NULL; /* directory stack */
- static char StackSize = 0; /* Size of current Stack */
- static int Top = -1;
- #define STACK_EMPTY (Top < 0)
- #define CHUNKSIZE 16
-
- /*
- * Grow the Stack by one chunk of CHUNKSIZE elements
- *
- */
- char **ExpandStack(Stack)
- char **Stack;
- {
- extern char *malloc(), *Realloc();
-
- /* Grow Stack */
- if(Stack == (char **)NULL)
- /* with malloc */
- Stack = (char **)malloc(CHUNKSIZE * sizeof(char **));
- else
- /* with Realloc */
- Stack = (char **)Realloc(Stack, (StackSize+CHUNKSIZE) *
- sizeof(char **));
-
- if(Stack == (char **)NULL)
- {
- /* outa mem */
- perror(ProgName);
- return((char **)NULL);
- }
- StackSize += CHUNKSIZE;
- return(Stack);
- }
-
- /*
- * Free the Stack
- *
- */
- FreeStack()
- {
- if(StackSize > 0)
- (void)free(Stack);
- }
-
-
- /*
- * Push a directory name on Stack
- *
- */
- int PushDir(name)
- char *name;
- {
- register int status;
- extern char *malloc(), *strcpy();
- extern int strlen();
- extern char **ExpandStack();
-
- ++Top;
- if(Top >= StackSize)
- {
- if((Stack = ExpandStack(Stack)) == (char **)NULL)
- return(~OK);
- }
-
- if((Stack[Top] = malloc(strlen(name)+1)) == (char *)NULL)
- {
- /* outa mem */
- perror(ProgName);
- return(~OK);
- }
- (void)strcpy(Stack[Top], name);
- return(OK);
- }
-
- /*
- * Pop a directory name from the stack
- *
- */
- char *PopDir()
- {
- register char *r;
- extern char **ShrinkStack();
-
- if(STACK_EMPTY)
- return ((char *)NULL);
-
- r = Stack[Top];
- Top--;
- return(r);
- }
-
- static int BadStatus = FALSE;
- #define BADSTATUS (BadStatus != FALSE)
-
- #include <sys/dir.h>
- /*
- * Process directories on the Stack, by adding all the
- * files in a directory to nargv.
- */
- int ProcessDirs(nargc, nargv)
- int *nargc;
- char ***nargv;
- {
- register char *name;
- register DIR *dirp;
- register struct direct *dp;
- register int status;
- char path[MAXNAMLEN+1];
- extern DIR *opendir();
- extern struct direct *readdir();
- extern char **CopyToNargv();
- extern char *PopDir();
-
- if(BADSTATUS)
- return(~OK);
-
- if(STACK_EMPTY)
- /* Nothing more to do */
- return(OK);
-
- /* Pop a directory from Stack and process */
- if((name = PopDir()) == (char *)NULL)
- {
- /* Oh Oh */
- fprintf(stderr,"Internal Error (BUG), PopDir returns NULL\n");
- BadStatus = (~FALSE);
- return(~OK);
- }
-
- /* Open the directory */
- if((dirp = opendir(name)) == (DIR *)NULL)
- {
- /* trouble opening directory */
- perror(name);
- /* set BADSTATUS and return */
- BadStatus = (~FALSE);
- return(~OK);
- }
-
- /* for each entry in the directory, if it is a file
- add to nargv. If it is a directory, Push it onto
- the directory stack.
- */
- for (dp = readdir(dirp); dp != (struct direct *)NULL;
- dp = readdir(dirp))
- {
- if( (!((strcmp(dp->d_name,".") == 0) ||
- (strcmp(dp->d_name,"..") == 0))) &&
- (dp->d_ino != 0 )) /* not a free entry */
- {
- strcpy(path, name);
- strcat(path,"/");
- strcat(path,dp->d_name);
-
- /* If this path is on the PruneList skip */
- if(OnPruneList(PruneList, path))
- continue;
-
- if(!isdir(path))
- {
- /* not a dir -- add this to nargv */
- if((*nargv = CopyToNargv(path, *nargc, *nargv))
- == (char **)NULL)
- {
- closedir(dirp);
- BadStatus = (~FALSE);
- return(~OK);
- }
- else
- {
- *nargc += 1;
- }
-
- }
- else
- {
- /* Note: At this point we could have
- simply recursed on ProcessDirs()
- totally eliminating the directory Stack.
- This was not done as it is possible
- to run out of dirp's on deep
- file hierarchies. Yet another (ir)rational
- design decision.
- */
-
- /* Push This directory */
- if((status = PushDir(path)) != OK)
- {
- closedir(dirp);
- BadStatus = (~FALSE);
- return(status);
- }
- }
- }
- } /* for */
- closedir(dirp);
- free(name); /* done with this directory */
-
- /* go do the rest */
- return (ProcessDirs(nargc, nargv));
- }
-
- /*
- * Add a name to PruneList
- *
- */
- PRUNELIST *AddPrune(list, name)
- PRUNELIST *list;
- char *name;
- {
- extern char *malloc();
- register PRUNELIST *new;
-
- if((new = (PRUNELIST *)malloc(sizeof(PRUNELIST))) == (PRUNELIST *)NULL)
- {
- /* outa mem */
- perror(ProgName);
- return(new);
- }
-
- new->name = name;
- new->next = list;
-
- return(new);
- }
-
- /*
- * Search for name on PruneList
- *
- */
- int OnPruneList(list, name)
- register PRUNELIST *list;
- register char *name;
- {
- for(; list != (PRUNELIST *)NULL; list = list->next)
- {
- if(strcmp(list->name, name) == 0)
- return(~FALSE);
- }
-
- return(FALSE);
- }
-
-
-
- #ifdef TEST
- /* to test: cc -o name name.c -DTEST -DCASE; name ~ */
- int MAIN(argc, argv)
- int argc;
- char **argv;
- {
- register int i;
-
- for(i = 0; i < argc; i++)
- printf("%d:\t%s\n", i, argv[i]);
-
-
- return(0);
- }
- #endif /* TEST */
-
- #endif /* CWRU */
-