home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2020 / lktree.c < prev   
Encoding:
C/C++ Source or Header  |  1990-12-28  |  8.1 KB  |  322 lines

  1. static char RcsId[] = "$Header: /wrld/6e50/cecil/tools/RCS/lktree.c,v 1.2 89/08/04 10:40:32 cecil Exp Locker: cecil $";
  2. /*
  3.     $Log:    lktree.c,v $
  4.  * Revision 1.2  89/08/04  10:40:32  cecil
  5.  * adding lktree to RCS control.
  6.  * 
  7.  * Revision 1.1  89/08/04  08:50:07  cecil
  8.  * Initial revision
  9.  * 
  10. */
  11.  
  12. #include <stdio.h>
  13. #include <ftw.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <string.h>
  17.  
  18. FILE *fp;
  19.  
  20. int debug = 0;            /* TRUE to debug */
  21. #define DEBUG(x) {if(debug)fprintf(stderr, "%s:%d:%s\n", __FILE__,__LINE__,x);}
  22.  
  23. int dir_ignore = 0;        /* option -d == ignore directories */
  24. int link_ignore = 0;        /* option -l == ignore links */
  25.  
  26. char *head;            /* the requested root head */
  27. char head_buf[512];        /* work buffer for environmental variable */
  28.  
  29. FILE *out_fp;            /* temp file for fgrep's */
  30. char *temp_fn;            /* return from mktemp() */
  31.  
  32. FILE *incl_fp = 0, *excl_fp = 0;    /* include and exclude file ptrs */
  33. char *incl_fn, *excl_fn;        /* include and exclude file names */
  34.  
  35. char *rcs_root_fn;        /* name of root directory to start link */
  36.  
  37. /* strdup - duplicate a string */
  38. char *strdup(s)
  39. char *s;
  40. {
  41.     char *cp;
  42.  
  43.     cp = (char *)malloc(strlen(s)+1);
  44.     strcpy(cp, s);
  45.     return cp;
  46. }
  47.  
  48. /*==================================================================*/
  49. /* strsearch - search string for sub_string, return ptr to start of */
  50. /* sub_string within string, NULL if not within.                    */
  51. /*==================================================================*/
  52.  
  53. char *strsearch(string, sub_string)
  54. char *string, *sub_string;
  55. {
  56.     for(;string = (char *)index(string, *sub_string);++string){
  57.         /* found first char of substring in string */
  58.         if(strcmp(string, sub_string) == 0)
  59.         return string;
  60.     }
  61.     /* substring is not within string, return NULL */
  62.     return (char *)0;
  63. }
  64.  
  65. int print_file(fn, sbuf, ftype)
  66. char *fn;            /* name of file */
  67. struct stat *sbuf;
  68. int ftype;
  69. {
  70.     register char *name;
  71.     char buf[BUFSIZ];
  72.     char *temp;
  73.     int status;
  74.     
  75.     DEBUG(fn);
  76.     /* If this file is a symbolic link, then absolutely */
  77.     /* ignore this reference!                           */
  78.     /* This call succeeds only if fn IS a link.         */
  79.     if((status = readlink(fn, buf, BUFSIZ)) != -1){
  80.     DEBUG("ignoring symbolic link file");
  81.     return 0;
  82.     }
  83.  
  84.     /* Never descend into RCS directories, as the intent */
  85.     /* is to link an RCS directory instead ths individual*/
  86.     /* files in the directory.                           */
  87.     if(re_exec(fn) != 0) {
  88.     DEBUG("NOT descending into RCS dir");
  89.     return 0;
  90.     }
  91.  
  92.     /* must run lstat on the file */
  93.     lstat(fn, sbuf);
  94.  
  95.     if ((sbuf->st_mode & S_IFMT) == S_IFBLK)
  96.     return 0;
  97.     if ((sbuf->st_mode & S_IFMT) == S_IFSOCK)
  98.     return 0;
  99.     if ((sbuf->st_mode & S_IFMT) == S_IFIFO)
  100.     return 0;
  101.     if ((sbuf->st_mode & S_IFMT) == S_IFCHR)
  102.     return 0;
  103.     if ((sbuf->st_mode & S_IFMT) == S_IFDIR) {
  104.     struct stat xbuf;
  105.  
  106.     if (dir_ignore)
  107.         return 0;
  108.  
  109.     stat(fn, &xbuf);
  110.     /* if this is a link to a directory, ignore */
  111.     if ((xbuf.st_mode & S_IFMT) == S_IFLNK) {
  112.         return 0;
  113.     }
  114.     }
  115.     if ((sbuf->st_mode & S_IFMT) == S_IFLNK) {
  116.     if (link_ignore)
  117.         return 0;
  118.     }
  119.  
  120.     if ((sbuf->st_mode & S_IFMT) == S_IFDIR)
  121.     name = fn + strlen(head);
  122.     else
  123.     name = fn + strlen(head) + 1;
  124.  
  125.     if(strlen(name) == 0)
  126.     return 0;    /* original dir call, ignore */
  127.  
  128.     switch (ftype) {
  129.     default:
  130.     fprintf(out_fp, "echo Unknown");
  131.     fprintf(out_fp, "\t%s", fn);
  132.     fprintf(out_fp, "\t%s", name);
  133.     fprintf(out_fp, "\n");
  134.     break;
  135.     case FTW_F:
  136.     if ((sbuf->st_mode & S_IFMT) == S_IFLNK) {
  137.         fprintf(out_fp, "ln -s");
  138.         fprintf(out_fp, "\t%s", fn);
  139.         fprintf(out_fp, "\t%s", name);
  140.         fprintf(out_fp, "\n");
  141.     } else {
  142.         fprintf(out_fp, "ln -s ");
  143.         fprintf(out_fp, "\t%s", fn);
  144.         fprintf(out_fp, "\t%s", name);
  145.         fprintf(out_fp, "\n");
  146.     }
  147.     if(debug)fprintf(stderr, "ln -s\t%s\t%s\n", fn, name);
  148.     break;
  149.     case FTW_D:
  150.     /* RCS is always a link to the real base system              */
  151.     /* have to look at the LAST 4 char of name for RCS directory */
  152.     /* The RCS directory will be linked rather than mkdir'ed     */
  153.     temp = name + strlen(name) - 4;
  154.     if(strcmp(temp, "/RCS") == 0){
  155.         /* if this link already exists, do NOT do it again, */
  156.         /* an other link will lead to a loop in the master  */
  157.         /* tree.                                            */
  158.         char lbuf[BUFSIZ];
  159.         if((status = readlink(name+1, lbuf, BUFSIZ)) >= 0)
  160.         return 0;
  161.  
  162.         sprintf(buf, "ln -s %s %s", fn, name + 1);
  163.         if(debug)
  164.         fprintf(stderr, "%s\n", buf);
  165.  
  166.         if ((sbuf->st_mode & S_IFMT) == S_IFDIR) {
  167.         struct stat xbuf;
  168.  
  169.         stat(fn, &xbuf);
  170.         /* if this is a link to a directory, ignore */
  171.         if ((xbuf.st_mode & S_IFMT) == S_IFLNK) {
  172.             fprintf("%d:link to existing directory ignored:%s\n",
  173.             __FILE__, buf);
  174.             return 0;
  175.         }
  176.         }
  177.     }
  178.     else{
  179.         char xbuf[512];
  180.         strcpy(xbuf, name+1);
  181.         sprintf(buf, "mkdir %s", xbuf);
  182.         if(debug)fprintf(stderr, "%s\n", xbuf);
  183.     }
  184.  
  185. #define FOR_REAL    1
  186. #if FOR_REAL
  187.     /* NEVER create a loop by linking with a file containing RCS/RCS */
  188.     if(strsearch(buf, "RCS/RCS") == 0)
  189.         system(buf);
  190. #else
  191.     fprintf(out_fp, "%s\n", buf);
  192. #endif
  193.     break;
  194.     case FTW_NS:
  195.     fprintf(stderr, "stat_failed");
  196.     fprintf(stderr, "\t%s", fn);
  197.     fprintf(stderr, "\t%s", name);
  198.     fprintf(stderr, "\n");
  199.     break;
  200.     }
  201.     return 0;
  202. }
  203.  
  204. main(argc, argv)
  205. int argc;
  206. char *argv[];
  207. {
  208.     int save_argc;
  209.     int status;
  210.     char *prog_name;
  211.     char *s;
  212.     char buf[BUFSIZ];
  213.     char sys_cmd[BUFSIZ];
  214.     char *rcs_base_fn;
  215.  
  216.     /* parse the necessary options */
  217.     save_argc = argc;
  218.     prog_name = *argv;
  219.     while (--argc > 0 && (*++argv)[0] == '-') {
  220.     for (s = argv[0] + 1; *s != '\0'; s++) {
  221.         switch (*s) {
  222.         default:
  223.         case '?':
  224.         fprintf(stderr, "usage: %s base_dir\n", prog_name);
  225.         fprintf(stderr, "\t-Ifile = use \"file\" as an include in fgrep\n");
  226.         fprintf(stderr, "\t-Xfile = use \"file\" as an exlcude in fgrep\n");
  227.         exit(1);
  228.         case 'd':
  229.         debug = 1;
  230.         break;
  231.         case 'I':
  232.         incl_fn = ++s;
  233.         while (*++s);    /* to end of string */
  234.         --s;        /* but not too far */
  235.         break;
  236.         case 'X':
  237.         excl_fn = ++s;
  238.         while (*++s);    /* to end of string */
  239.         --s;        /* but not too far */
  240.         break;
  241.         }
  242.     }
  243.     }
  244.  
  245.     /* compile regular expression to prevent descent into */
  246.     /* an RCS linked subdirectory.                        */
  247.     if(head = (char *)re_comp("\/RCS\/")){
  248.     printf(head);
  249.     exit(1);
  250.     }
  251.  
  252.     temp_fn = (char *) mktemp("TTXXXXXX");
  253.     out_fp = fopen(temp_fn, "w");
  254.  
  255.     /* this may or may not exist */
  256.     if(argc == 0) {
  257.     head = rcs_root_fn = (char *)getenv("ROOT_TREE");
  258.     }
  259.     else
  260.     head = *argv;        /* get the head */
  261.  
  262.  
  263.     {
  264.     int i;
  265.  
  266.     /* move the environmental varialbe to a work area */
  267.     for(i = 0; i < sizeof(head_buf); head_buf[i++] = '\0');
  268.     strcpy(head_buf, head);
  269.     head = head_buf;
  270.     }
  271.  
  272.     /* prove existence/readability of RCS root file */
  273.     if ((fp = fopen(rcs_root_fn, "r")) == (FILE *) 0) {
  274.     fprintf(stderr, "Cannot open $ROOT_TREE %s\n", rcs_base_fn);
  275.     exit(1);
  276.     }
  277.     fclose(fp);
  278.  
  279.     /* open the exclusion file, if none check under the ROOT_TREE dir */
  280.     if ((excl_fp = fopen(excl_fn, "r")) == (FILE *) 0) {
  281.     sprintf(excl_fn = sys_cmd, "%s/excl_file", rcs_root_fn);
  282.     excl_fn = strdup(sys_cmd);    /* save this string */
  283.     if ((excl_fp = fopen(sys_cmd, "r")) == (FILE *) 0) {
  284.         fprintf(stderr, "Cannot read file exclusion list: %s\n",
  285.         excl_fn);
  286.         exit(1);
  287.     }
  288.     }
  289.  
  290.     /* open the inclusion file, if none check under the ROOT_TREE dir */
  291.     if ((incl_fp = fopen(incl_fn, "r")) == (FILE *) 0) {
  292.     sprintf(sys_cmd, "%s/incl_file", rcs_root_fn);
  293.     incl_fn = strdup(sys_cmd);    /* save this string */
  294.     if ((incl_fp = fopen(sys_cmd, "r")) == (FILE *) 0) {
  295.         fprintf(stderr, "Cannot read file inclusion list: %s\n",
  296.         incl_fn);
  297.         exit(1);
  298.     }
  299.     }
  300.  
  301.     ftw(rcs_root_fn, print_file, 20);
  302.  
  303.     rewind(out_fp);
  304.     sprintf(sys_cmd, "cat %s", temp_fn);
  305.     if (incl_fp) {
  306.     sprintf(buf, "| fgrep -f %s ", incl_fn);
  307.     strcat(sys_cmd, buf);
  308.     }
  309.     if (excl_fp) {
  310.     sprintf(buf, "| fgrep -v -f %s ", excl_fn);
  311.     strcat(sys_cmd, buf);
  312.     }
  313.     strcat(sys_cmd, " | /bin/csh ");
  314.     /* Do not remove temp file if debugging */
  315.     if(!debug) {
  316.     strcat(sys_cmd, "; rm ");
  317.     strcat(sys_cmd, temp_fn);
  318.     }
  319.     printf("%s\n", sys_cmd);
  320.     exit(system(sys_cmd));
  321. }
  322.