home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Distributions / ucb / spencer_2bsd.tar.gz / 2bsd.tar / src / diffdir.c < prev    next >
C/C++ Source or Header  |  1980-02-17  |  7KB  |  379 lines

  1. /* Copyright (c) 1979 Regents of the University of California */
  2. #include <retrofit.h>
  3. #include <stdio.h>
  4.  
  5. /*
  6.  * Diffdir - a (first) directory difference program
  7.  * Bill Joy UCB March 16, 1978
  8.  *
  9.  * This is a difference program which operates on the entire contents of
  10.  * a directory.  It reports common files which are different, running
  11.  * diff if the files are ASCII files.  It also reports files which are
  12.  * unique to one of the two directories.
  13.  *
  14.  * An option "h" (for header) causes diffdir to print each difference
  15.  * on a new page (using an appropriate "pr") and to summarize missing
  16.  * files and differences in binary files on a final page.
  17.  *
  18.  * Option "s" causes files which are the same to be reported also.
  19.  *
  20.  * It would be nice if this were "difftree", and if it knew a few
  21.  * more things, e.g to "size" objects which are different or some
  22.  * such or at least to not say that "directories are different" calling
  23.  * them files, i.e. "Files ex-1.1/temp and ex-1.2/temp are different".
  24.  */
  25.  
  26. typedef    char bool;
  27.  
  28. struct entry {
  29.     char    *name;
  30.     int    flags;
  31. } *dir1, *dir2;
  32.  
  33. #define    ONLY    1
  34. #define    DIFFER    2
  35.  
  36. bool    hflg;
  37. bool    vflg;
  38. bool    sflg;
  39.  
  40. #define    vprintf    if (vflg) printf
  41.  
  42. main(argc, argv)
  43.     int argc;
  44.     char *argv[];
  45. {
  46.     register struct entry *d1, *d2;
  47.     register char *cp;
  48.  
  49.     while (argc > 1) {
  50.         cp = argv[1];
  51.         if (*cp++ != '-')
  52.             break;
  53.         while (*cp) switch (*cp++) {
  54.  
  55.         case 'h':
  56.             hflg++;
  57.             continue;
  58.  
  59.         case 'v':
  60.             vflg++;
  61.             continue;
  62.  
  63.         case 's':
  64.             sflg++;
  65.             continue;
  66.  
  67.         default:
  68. usage:
  69.             panic("Usage: diffdir [ -h ] dir1 dir2");
  70.         }
  71.         argc--, argv++;
  72.     }
  73.     if (argc != 3)
  74.         goto usage;
  75.     setupdir(argv[1], &dir1);
  76.     setupdir(argv[2], &dir2);
  77.     d1 = dir1; d2 = dir2;
  78.     while (d1->name != 0 || d2->name != 0) {
  79.         if (useless(d1->name)) {
  80.             d1++;
  81.             continue;
  82.         }
  83.         if (useless(d2->name)) {
  84.             d2++;
  85.             continue;
  86.         }
  87.         if (d1->name != 0 && d2->name != 0)
  88.             switch (sgn(strcmp(d1->name, d2->name))) {
  89.  
  90.             case -1:
  91. onlyin1:
  92.                 if (hflg)
  93.                     d1->flags =| ONLY;
  94.                 else
  95.                     printf("Only in %s: %s\n", argv[1], d1->name);
  96.                 d1++;
  97.                 continue;
  98.  
  99.             case 0:
  100.                 vprintf("In both: %s\n", d1->name);
  101.                 compare(d1, argv[1], argv[2]);
  102.                 d1++;
  103.                 d2++;
  104.                 continue;
  105.  
  106.             case 1:
  107. onlyin2:            if (hflg)
  108.                     d2->flags =| ONLY;
  109.                 else
  110.                     printf("Only in %s: %s\n", argv[2], d2->name);
  111.                 d2++;
  112.                 continue;
  113.             }
  114.         if (d1->name != 0)
  115.             goto onlyin1;
  116.         else
  117.             goto onlyin2;
  118.     }
  119.     if (hflg) {
  120.         int header = 0;
  121.  
  122.         for (d1 = dir1; d1->name; d1++)
  123.             if (d1->flags & ONLY) {
  124.                 if (header == 0) {
  125.                     printf("\fOnly in %s\n", argv[1]);
  126.                     header = 1;
  127.                 }
  128.                 printf("\t%s\n", d1->name);
  129.             }
  130.         for (d2 = dir2; d2->name != 0; d2++) {
  131.             if (d2->flags & ONLY) {
  132.                 if (header == 0)
  133.                     printf("\f");
  134.                 if ((header & 2) == 0) {
  135.                     printf("Only in %s\n", argv[2]);
  136.                     header =| 2;
  137.                 }
  138.                 printf("\t%s\n", d2->name);
  139.             }
  140.         }
  141.         for (d1 = dir1; d1->name; d1++)
  142.             if (d1->flags & DIFFER) {
  143.                 if (header == 0) {
  144.                     printf("\f");
  145.                     header = 1;
  146.                 }
  147.                 if ((header & 4) == 0) {
  148.                     printf("Non-ascii files which differ:\n");
  149.                     header =| 4;
  150.                 }
  151.                 printf("\t%s\n", d1->name);
  152.             }
  153.     }
  154.     exit(0);
  155. }
  156.  
  157. int    entcmp();
  158. setupdir(cp, head)
  159.     char *cp;
  160.     struct entry **head;
  161. {
  162.     int count = 1;
  163.     struct dirent0 {
  164.         short ino;
  165.         char fname[14];
  166.     };
  167.  
  168.     struct dirent1 {
  169.         short ino;
  170.         char fname1[16];
  171.     } dirent;
  172.     register struct entry *hp;
  173.  
  174.     close(0);
  175.     if (open(cp, 0) < 0) {
  176.         perror(cp);
  177.         exit(1);
  178.     }
  179.     while (read(0, &dirent, sizeof (struct dirent0)) == sizeof (struct dirent0))
  180.     if (dirent.ino)
  181.         count++;
  182.     lseek(0, (long) 0, 0);
  183.     hp = *head = Calloc(count, sizeof **head);
  184.     while (read(0, &dirent, sizeof (struct dirent0)) == sizeof (struct dirent0))
  185.     if (dirent.ino) {
  186.         hp->name = savestr(dirent.fname);
  187.         hp++;
  188.     }
  189.     qsort(*head, count - 1, sizeof **head, entcmp);
  190. }
  191.  
  192. entcmp(ep, ep2)
  193.     struct entry *ep, *ep2;
  194. {
  195.  
  196.     return (strcmp(ep->name, ep2->name));
  197. }
  198.  
  199. Calloc(i, n)
  200.     int i, n;
  201. {
  202.     register unsigned mem;
  203.  
  204.     mem = calloc(i, n);
  205.     if (mem == 0)
  206.         panic("Ran out of memory");
  207.     return (mem);
  208. }
  209.  
  210. savestr(cp)
  211.     register char *cp;
  212. {
  213.  
  214.     return (strcpy(calloc(strlen(cp)+1, sizeof (char)), cp));
  215. }
  216.  
  217. panic(cp)
  218.     char *cp;
  219. {
  220.  
  221.     fprintf(stderr, "%s\n", cp);
  222.     exit(1);
  223. }
  224.  
  225. sgn(i)
  226.     int i;
  227. {
  228.     if (i > 0)
  229.         return (1);
  230.     else if (i < 0)
  231.         return (-1);
  232.     return (0);
  233. }
  234.  
  235. compare(dp, d1, d2)
  236.     struct entry *dp;
  237.     char *d1, *d2;
  238. {
  239.     register int i;
  240.     char path1[100], path2[100];
  241.     int t1, t2;
  242.     char header[250];
  243.     char *name = dp->name;
  244.  
  245.     if (max(strlen(d1), strlen(d2)) + strlen(name) + 2 >= 100)
  246.         panic("Path names too long");
  247.     strcat(strcat(strcpy(path1, d1), "/"), name);
  248.     strcat(strcat(strcpy(path2, d2), "/"), name);
  249.     i = callit("/usr/bin/cmp", "cmp", "-s", path1, path2, 0);
  250.     if (i == 0) {
  251.         if (sflg)
  252.             printf("Files %s and %s same\n", path1, path2);
  253.         return;
  254.     }
  255.     if (!ascii(path1) || !ascii(path2)) {
  256.         if (hflg)
  257.             dp->flags =| DIFFER;
  258.         else
  259.             printf("Files %s and %s differ\n", path1, path2);
  260.         return;
  261.     }
  262.     if (hflg) {
  263.         sprintf(header, "diff %s %s", path1, path2);
  264.         prcallit(header, "/usr/bin/diff", "diff", path1, path2, 0);
  265.     } else {
  266.         printf("diff %s %s\n", path1, path2);
  267.         callit("/usr/bin/diff", "diff", path1, path2, 0);
  268.     }
  269. }
  270.  
  271. prcallit(header, path, av)
  272.     char *header, *path;
  273. {
  274.     int status;
  275.     int pid;
  276.     int pv[2];
  277.  
  278.     fflush(stdout);
  279.     pipe(pv);
  280.     pid = fork();
  281.     if (pid == -1)
  282.         panic("No more processes");
  283.     if (pid == 0) {
  284.         close(0);
  285.         dup(pv[0]);
  286.         close(pv[0]);
  287.         close(pv[1]);
  288.         execl("/bin/pr", "pr", "-h", header, 0);
  289.         execl("/usr/bin/pr", "pr", "-h", header, 0);
  290.         perror("/usr/bin/pr");
  291.         exit(1);
  292.     }
  293.     pid = fork();
  294.     if (pid == -1)
  295.         panic("No more processes");
  296.     if (pid == 0) {
  297.         close(1);
  298.         dup(pv[1]);
  299.         close(pv[0]);
  300.         close(pv[1]);
  301.         execv(path+4, &av);
  302.         execv(path, &av);
  303.         perror(path);
  304.         exit(1);
  305.     }
  306.     close(pv[0]);
  307.     close(pv[1]);
  308.     while (wait(&status) != -1)
  309.         continue;
  310. }
  311.  
  312. callit(path, av)
  313.     char *path;
  314. {
  315.     int status;
  316.     int pid;
  317.  
  318.     fflush(stdout);
  319.     pid = fork();
  320.     if (pid == -1)
  321.         panic("No more processes");
  322.     if (pid == 0) {
  323.         execv(path+4, &av);
  324.         execv(path, &av);
  325.         perror(path);
  326.         exit(1);
  327.     }
  328.     wait(&status);
  329.     return (((status >> 8) & 0377) | (status & 0377));
  330. }
  331.  
  332. max(a,b)
  333.     int a,b;
  334. {
  335.  
  336.     return (a > b ? a : b);
  337. }
  338.  
  339. ascii(cp)
  340.     char *cp;
  341. {
  342.     int f;
  343.     short w;
  344.  
  345.     f = open(cp, 0);
  346.     if (f < 0)
  347.         return (0);
  348.     if (read(f, &w, sizeof w) != sizeof w) {
  349.         close(f);
  350.         return (1);
  351.     }
  352.     close(f);
  353.     switch (w) {
  354.  
  355.     case 0405:    /* Overlay executable */
  356.     case 0407:    /* Executable */
  357.     case 0410:    /* Pure executable */
  358.     case 0411:    /* Separate executable */
  359.     case 0177545:    /* Archive */
  360.     case 0177555:    /* Old archive */
  361.         return (0);
  362.     default:
  363.         if (w & 0100200)
  364.             return (0);
  365.         return (1);
  366.     }
  367. }
  368.  
  369. useless(cp)
  370.     char *cp;
  371. {
  372.  
  373.     if (strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0)
  374.         return (1);
  375.     if (cp[0] == '.')
  376.         return (1);        /* For now */
  377.     return (0);
  378. }
  379.