/* MakeDiffs : This program can be used to compare whole directories and
 * their subdirectories with another directory containing identically
 * named files; it is designed to look out for differences in the
 * sourcecode of large projects, but may be used in another way, too.
 *
 * You have to set the enviroment-variable DIFF to the command, that
 * will be executed in the following way : $DIFF path1/file path2/file
 *
 * If an file exists in path1, but doesn´t exist in path2, an
 * error message will be display on stderr.
 *
 * Source Code written by Thomas Hadig in April 1992. This program
 * is public domain, but may only be used in a noncomercial way !
 *
 * Compile with SAS (Lattice) C 5.10 : lc -L -cusf MakeDiffs
 */
/*{{{  #includes*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>
#include <sys/dir.h>
#include <sys/stat.h>
/*}}}  */
/*{{{  #defines*/
#define IS_READABLE 4
#define MAX 256
#define PATH_SEP "/"
/*}}}  */

/*{{{  variables*/
char *diff;

extern int errno;
/*}}}  */

/*{{{  Check file or dir existence*/
/*{{{  exist*/
int exist (char *ptr, struct stat *st)

 {
  if (stat (ptr,st)) return 0;            /* error */
  return 1;
 }
/*}}}  */
/*{{{  exist_dir*/
int exist_dir (char *ptr)

 {
  struct stat st;

  if (exist(ptr,&st))
    if (st.st_mode&S_IFDIR) return 1;
  return 0;
 }
/*}}}  */
/*}}}  */
/*{{{  loop*/
void loop (char *dir1, char *dir2)

 {
  char name[MAX];
  DIR *dfd;
  struct direct *d;
  struct stat st;
  int ret;

  if (!(dfd=opendir (dir1)))
    fprintf (stderr,"\n Can't open directory >>%s<<\n",dir1);
  else
   {
    /*{{{  handle whole directory*/
    while (d=readdir (dfd))
     {
      strcpy (name,dir2);
      if (name[strlen(name)-1]!=':') strncat (name,PATH_SEP,MAX-strlen(name));
      strncat (name,d->d_name,MAX-strlen(name));
      if (exist (name,&st))
       {
        /*{{{  handle file or directory*/
        if (st.st_mode & S_IFREG)
         {
          /*{{{  Make diffs for one file*/
          strcpy (name,diff);
          strncat (name," ",MAX-strlen(name));
          strncat (name,dir1,MAX-strlen(name));
          if (name[strlen(name)-1]!=':') strncat (name,PATH_SEP,MAX-strlen(name));
          strncat (name,d->d_name,MAX-strlen(name));
          strncat (name," ",MAX-strlen(name));
          strncat (name,dir2,MAX-strlen(name));
          if (name[strlen(name)-1]!=':') strncat (name,PATH_SEP,MAX-strlen(name));
          strncat (name,d->d_name,MAX-strlen(name));
          if (ret = system (name))
           {
            fprintf (stderr,
              "System command error : >>%s<<\n Return Code : %d\nError Number : %d\n",
              name,ret,errno);
           }
          /*}}}  */
         }
        else if (st.st_mode & S_IFDIR)
         {
          /*{{{  recursiv search through directories*/
          char name1[MAX];

          strcpy (name1,dir1);
          if (name1[strlen(name1)-1]!=':') strncat (name1,PATH_SEP,MAX-strlen(name1));
          strncat (name1,d->d_name,MAX-strlen(name1));
          loop (name1,name);
          /*}}}  */
         }
        else
          fprintf (stderr,"Unknown File Type >>%s<<\n Type : %d\n",name,
            st.st_mode);
        /*}}}  */
       }
      else
        fprintf (stderr,"Can't find file >>%s<< in directory >>%s<< !\n",
          d->d_name,dir2);
     }
    /*}}}  */
    closedir (dfd);
   }
 }
/*}}}  */

/*{{{  main*/
void main (int argc, char **argv)

 {
  if (argc!=3)
   {
    fprintf (stderr,"\nUsage : %s dir1 dir2 \n",argv[0]);
    exit (0);
   }
  if ((!exist_dir(argv[1]))||(!exist_dir(argv[2])))
   {
    fprintf (stderr,"\n Directories do not exist !\n");
    exit (1);
   }
  if (!(diff=getenv ("DIFF")))
   {
    fprintf (stderr,"\n Enviroment variable DIFF not set !\n");
    exit (2);
   }
  loop (argv[1],argv[2]);
 }
/*}}}  */
