home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / utility / unixtool / unixrzsz / expndrgs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-17  |  9.0 KB  |  463 lines

  1. #ifdef CWRU
  2.  
  3.     /* CWRU specific extention(hack :-)
  4.      *     Examine each argument given to main,
  5.      *     If it is a directory, then expand it
  6.      *    to all its component files, recursively
  7.      *    till you bottom out.
  8.      *    If it is not a directory, then just pass it on.
  9.      *
  10.      *    Inputs: argc, argv
  11.      *    Outputs: nargc, nargv (calls MAIN(nargc, nargv))
  12.      *    To test: compile with -DCASE -DTEST
  13.      *         run with a directory as an arg
  14.      *    Hacker: JRB
  15.      *    Requirements: BSD 4.2/3    specific routines used
  16.      *              only tested on Vax BSD 4.3
  17.      *
  18.      *    Added -P name prune option at the suggestion of dietz@zhmti
  19.      *    Multiple -P's may be given on the command line.
  20.      *    -P name may be given anywhere on the command line. -P name
  21.      *    will prune the subdirectories named as arguement to -P.
  22.      *    ie: when the program is decending the file hierarchy it
  23.      *    will not visit the pruned branches.
  24.      *     NOTE that the option is -P and not -p
  25.      *          (-p is a valid sz option).
  26.      *    NOTE that the arguement given to -P can be the name
  27.      *     of a file or a directory. In case it is a file,
  28.      *    that file is skipped.
  29.      *
  30.      */
  31.  
  32. /*
  33.  * Expand argc, so that the called MAIN(nargc,nargv) receives only
  34.  * filenames, in nargv[][]
  35.  *
  36.  *    WARNING: Contains BSD specific code, tested on BSD4.3 ONLY.
  37.  *
  38.  *    Jwahar Bammi
  39.  *    usenet: {decvax,cbatt,cbosgd,sun}!cwruecmp!bammi
  40.  *    csnet:       bammi@case
  41.  *    arpa:        bammi%case@csnet-relay
  42.  *    compuServe:  71515,155
  43.  *
  44.  */
  45. #include <stdio.h>
  46.  
  47. #define OK     0
  48. #define FALSE     0
  49. #define Realloc     realloc
  50.  
  51. typedef struct _prunelist {
  52.     char *name;            /* name of subdirectory to prune */
  53.     struct _prunelist *next;    /* ptr to next */
  54. } PRUNELIST;
  55.  
  56. static char *ProgName;
  57. static PRUNELIST *PruneList = (PRUNELIST *)NULL; /* Head of PruneList */
  58.  
  59.  
  60. main(argc, argv)
  61. int argc;
  62. char **argv;
  63. {
  64.     register int status;
  65.     int nargc = 0;
  66.     char **nargv = (char **)NULL;
  67.     extern int MAIN();
  68.     extern char **CopyToNargv();
  69.     extern PRUNELIST *AddPrune();
  70.  
  71.     ProgName = *argv;
  72.     
  73.     /* copy argv[0] blindly */
  74.     if((nargv = CopyToNargv(*argv, nargc, nargv)) == (char **)NULL)
  75.         return(~OK);
  76.  
  77.     nargc++;
  78.     
  79.     while((--argc) > 0)
  80.     {
  81.         argv++;
  82.         if(**argv == '-')
  83.         {
  84.             /* copy any options except -P */
  85.             if( (*argv)[1] == 'P')
  86.             {
  87.                 if((--argc) <= 0)
  88.                 {
  89.                     fprintf(stderr,"no argument given to -P\n");
  90.                     return(~OK);
  91.                 }
  92.                 if((PruneList = AddPrune(PruneList,*++argv))
  93.                    == (PRUNELIST *)NULL)
  94.                     return(~OK);
  95.             }
  96.             else
  97.             {
  98.                 if((nargv = CopyToNargv(*argv, nargc, nargv))
  99.                    == (char **)NULL)
  100.                     return(~OK);
  101.                 else
  102.                     nargc++;
  103.             }
  104.             
  105.         }
  106.         else
  107.         {
  108.             /* If its not on the PruneList then */
  109.             if(!OnPruneList(PruneList, *argv))
  110.             {
  111.                 /* if it is a directory, push it */
  112.                 if(isdir(*argv))
  113.                 {
  114.                     if((status = PushDir(*argv)) != OK)
  115.                     {
  116.                         return(status);
  117.                     }
  118.                 }
  119.                 else
  120.                 {
  121.                     /* it is NOT a directory, copy to nargv */
  122.                     if((nargv = CopyToNargv(*argv, nargc, nargv))
  123.                        == (char **)NULL)
  124.                         return(~OK);
  125.                     else
  126.                         nargc++;
  127.                 }
  128.             }
  129.         }
  130.     } /* while */
  131.  
  132.     /* process pushed directories if any */
  133.     if((status = ProcessDirs(&nargc, &nargv)) != OK)
  134.         return(status);
  135.     /* else Free the Stack and call MAIN */
  136.     FreeStack();
  137.     return (MAIN(nargc, nargv));
  138. }
  139.  
  140. #include <sys/types.h>
  141. #include <sys/stat.h>
  142.  
  143. /*
  144.  * is name a directory ?
  145.  *
  146.  */
  147. int isdir(name)
  148. char *name;
  149. {
  150.     struct stat st;
  151.     
  152.     if(stat(name, &st) != 0)
  153.         return (FALSE);    /* assume its not a directory */
  154.  
  155.     /* NOTE: the expression below eliminates Sockets.
  156.        (st.st_mode & S_IFMT)& S_IFDIR does not!
  157.      */
  158.     return( ( (st.st_mode & S_IFMT) == S_IFDIR) );
  159. }
  160.  
  161. /*
  162.  * Expand nargv by an element and copy a String into the new element
  163.  *
  164.  */
  165. char **CopyToNargv(string, nargc, nargv)
  166. char *string;
  167. int nargc;
  168. char **nargv;
  169. {
  170.     extern char *malloc(), *Realloc(), *strcpy();
  171.     extern int strlen();
  172.     
  173.     /* expand nargv by 1 element */
  174.     if(nargv == (char **)NULL)
  175.         /* do it with malloc for the first one */
  176.         nargv = (char **)malloc(sizeof(char **));
  177.     else
  178.         /* do it with Realloc for others */
  179.         nargv = (char **)Realloc(nargv, (nargc+1)*sizeof(char **));
  180.     
  181.     if(nargv == (char **)NULL)
  182.     {
  183.         /* failed to get memory */
  184.         perror(ProgName);
  185.         return ((char **)NULL);
  186.     }
  187.  
  188.     /* Get mem for string */
  189.     if(( nargv[nargc] = malloc(strlen(string)+1)) == (char *)NULL)
  190.     {
  191.         /* failed to get memory */
  192.         perror(ProgName);
  193.         return ((char **)NULL);
  194.     }
  195.  
  196.     /* copy string into nargv[nargc] */
  197.     (void)strcpy( nargv[nargc], string);
  198.     return(nargv);
  199. }
  200.  
  201. static char **Stack = (char **)NULL;    /* directory stack */
  202. static char StackSize = 0;        /* Size of current Stack */
  203. static int    Top   = -1;
  204. #define STACK_EMPTY    (Top < 0)
  205. #define CHUNKSIZE    16
  206.  
  207. /*
  208.  * Grow the Stack by one chunk of CHUNKSIZE elements
  209.  *
  210.  */
  211. char **ExpandStack(Stack)
  212. char **Stack;
  213. {
  214.     extern char *malloc(), *Realloc();
  215.     
  216.     /* Grow Stack */
  217.     if(Stack == (char **)NULL)
  218.         /* with malloc */
  219.         Stack = (char **)malloc(CHUNKSIZE * sizeof(char **));
  220.     else
  221.         /* with Realloc */
  222.         Stack = (char **)Realloc(Stack, (StackSize+CHUNKSIZE) *
  223.                              sizeof(char **));
  224.  
  225.     if(Stack == (char **)NULL)
  226.     {
  227.         /* outa mem */
  228.         perror(ProgName);
  229.         return((char **)NULL);
  230.     }
  231.     StackSize += CHUNKSIZE;
  232.     return(Stack);
  233. }
  234.  
  235. /*
  236.  * Free the Stack
  237.  *
  238.  */
  239. FreeStack()
  240. {
  241.     if(StackSize > 0)
  242.         (void)free(Stack);
  243. }
  244.  
  245.  
  246. /*
  247.  * Push a directory name on Stack
  248.  *
  249.  */
  250. int PushDir(name)
  251. char *name;
  252. {
  253.     register int status;
  254.     extern char *malloc(), *strcpy();
  255.     extern int strlen();
  256.     extern char **ExpandStack();
  257.  
  258.     ++Top;
  259.     if(Top >= StackSize)
  260.     {
  261.         if((Stack = ExpandStack(Stack)) == (char **)NULL)
  262.             return(~OK);
  263.     }
  264.     
  265.     if((Stack[Top] = malloc(strlen(name)+1)) == (char *)NULL)
  266.     {
  267.         /* outa mem */
  268.         perror(ProgName);
  269.         return(~OK);
  270.     }
  271.     (void)strcpy(Stack[Top], name);
  272.     return(OK);
  273. }
  274.  
  275. /*
  276.  * Pop a directory name from the stack
  277.  *
  278.  */
  279. char *PopDir()
  280. {
  281.     register char *r;
  282.     extern char **ShrinkStack();
  283.     
  284.     if(STACK_EMPTY)
  285.         return ((char *)NULL);
  286.     
  287.     r = Stack[Top];
  288.     Top--;
  289.     return(r);
  290. }
  291.  
  292. static int BadStatus = FALSE;
  293. #define BADSTATUS (BadStatus != FALSE)
  294.  
  295. #include <sys/dir.h>
  296. /*
  297.  * Process directories on the Stack, by adding all the
  298.  * files in a directory to nargv.
  299.  */
  300. int ProcessDirs(nargc, nargv)
  301. int *nargc;
  302. char ***nargv;
  303. {
  304.     register char *name;
  305.     register DIR *dirp;
  306.     register struct direct *dp;
  307.     register int status;
  308.     char path[MAXNAMLEN+1];
  309.     extern DIR *opendir();
  310.     extern struct direct *readdir();
  311.     extern char **CopyToNargv();
  312.     extern char *PopDir();
  313.     
  314.     if(BADSTATUS)
  315.         return(~OK);
  316.  
  317.     if(STACK_EMPTY)
  318.         /* Nothing more to do */
  319.         return(OK);
  320.  
  321.     /* Pop a directory from Stack and process */
  322.     if((name = PopDir()) == (char *)NULL)
  323.     {
  324.         /* Oh Oh */
  325.         fprintf(stderr,"Internal Error (BUG), PopDir returns NULL\n");
  326.         BadStatus = (~FALSE);
  327.         return(~OK);
  328.     }
  329.     
  330.     /* Open the directory */
  331.     if((dirp = opendir(name)) == (DIR *)NULL)
  332.     {
  333.         /* trouble opening directory */
  334.         perror(name);
  335.         /* set BADSTATUS and return */
  336.         BadStatus = (~FALSE);
  337.         return(~OK);
  338.     }
  339.     
  340.     /* for each entry in the directory, if it is a file
  341.        add to nargv. If it is a directory, Push it onto
  342.        the directory stack.
  343.      */
  344.     for (dp = readdir(dirp); dp != (struct direct *)NULL;
  345.          dp = readdir(dirp))
  346.     {
  347.         if( (!((strcmp(dp->d_name,".") == 0) ||
  348.               (strcmp(dp->d_name,"..") == 0))) &&
  349.            (dp->d_ino != 0 ))  /* not a free entry */
  350.         {
  351.             strcpy(path, name);
  352.             strcat(path,"/");
  353.             strcat(path,dp->d_name);
  354.  
  355.             /* If this path is on the PruneList skip */
  356.             if(OnPruneList(PruneList, path))
  357.                 continue;
  358.  
  359.             if(!isdir(path))
  360.             {
  361.                 /* not a dir -- add this to nargv */
  362.                 if((*nargv = CopyToNargv(path, *nargc, *nargv))
  363.                    == (char **)NULL)
  364.                 {
  365.                     closedir(dirp);
  366.                     BadStatus = (~FALSE);
  367.                     return(~OK);
  368.                 }
  369.                 else
  370.                 {
  371.                     *nargc += 1;
  372.                 }
  373.                 
  374.             }
  375.             else
  376.             {
  377.                 /* Note: At this point we could have
  378.                    simply recursed on ProcessDirs()
  379.                    totally eliminating the directory Stack.
  380.                    This was not done as it is possible
  381.                    to run out of dirp's on deep
  382.                    file hierarchies. Yet another (ir)rational
  383.                    design decision.
  384.                  */
  385.  
  386.                 /* Push This directory */
  387.                 if((status = PushDir(path)) != OK)
  388.                 {
  389.                     closedir(dirp);
  390.                     BadStatus = (~FALSE);
  391.                     return(status);
  392.                 }
  393.             }
  394.         }
  395.     } /* for */
  396.     closedir(dirp);
  397.     free(name);    /* done with this directory */
  398.     
  399.     /* go do the rest */
  400.     return (ProcessDirs(nargc, nargv));
  401. }
  402.  
  403. /*
  404.  * Add a name to PruneList
  405.  *
  406.  */
  407. PRUNELIST *AddPrune(list, name)
  408. PRUNELIST *list;
  409. char *name;
  410. {
  411.     extern char *malloc();
  412.     register PRUNELIST *new;
  413.     
  414.     if((new = (PRUNELIST *)malloc(sizeof(PRUNELIST))) == (PRUNELIST *)NULL)
  415.     {
  416.         /* outa mem */
  417.         perror(ProgName);
  418.         return(new);
  419.     }
  420.  
  421.     new->name = name;
  422.     new->next = list;
  423.     
  424.     return(new);
  425. }
  426.  
  427. /*
  428.  * Search for name on PruneList
  429.  *
  430.  */
  431. int OnPruneList(list, name)
  432. register PRUNELIST *list;
  433. register char *name;        
  434. {
  435.     for(; list != (PRUNELIST *)NULL; list = list->next)
  436.     {
  437.         if(strcmp(list->name, name) == 0)
  438.             return(~FALSE);
  439.     }
  440.     
  441.     return(FALSE);
  442. }
  443.  
  444.     
  445.  
  446. #ifdef TEST
  447. /* to test: cc -o name name.c -DTEST -DCASE; name ~ */
  448. int MAIN(argc, argv)
  449. int argc;
  450. char **argv;
  451. {
  452.     register int i;
  453.     
  454.     for(i = 0; i < argc; i++)
  455.         printf("%d:\t%s\n", i, argv[i]);
  456.  
  457.  
  458.     return(0);
  459. }
  460. #endif /* TEST */
  461.  
  462. #endif /* CWRU */
  463.