/*=~=~=~=~ McGill-Computer-Vision-and-Robotics-Laboratory--C-Module ~=~=~=~=
 *		
 * NAME:	tcmp - compare access or modify times for two files
 *
 * USAGE:	tcmp <file1> <file2> [-a] [-s] [-f]
 *
 * DESCRIPTION: tcmp compares the modify times of its two file arguments
 *		and prints a message describing the result. If either of
 *		the files is a symbolic link, then the information is based
 *		on the link reference.
 *
 *		A returns value of -1 is generated if the modify time of 
 *		file1 is less than the modify time of file2, 0 if it is equal,
 *		and 1 if it is greater.
 * 
 *		A value of 2 is returned in the event of errors.
 *
 * ARGUMENTS:	file1 and file2 -- files to be tested
 *
 *		-a --	use the access time for the file instead of the modify
 *			time as the basis for the compare.
 *
 *		-c --   use the last stat change time as the basis for
 *			comparison.
 *
 *		-s --   supress non-diagnostic messages
 *
 *		-f --   force program to return a value in the event of error.
 *			 1 is returned if the right file does not exist,
 *			-1 is returned if the left file does not exist,
 *			 0 is returned if neither file exists.
 *
 * NOTES:	This was mainly written to be used in scripts which have
 *		to maintain several sets of files.
 *
 * AUTHOR/DATE: John Lloyd, November, 1986
 *
 * UPDATES:
 *
 *~=~=~=~=~=~= McGill-Computer-Vision-and-Robotics-Laboratory ~=~=~=~=~=~=*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

#define MODIFY_TIME	1
#define ACCESS_TIME	2
#define STAT_TIME	3

int compareBasis = 0;
int silentMode = 0;
int force = 0;

main(argc, argv)
int argc;
char *argv[];
{
	char *name1 = NULL, *name2 = NULL;
	struct stat s1, s2;	
	int rcode;
	
#define ARGUMENT(s)	(strcmp(*argv,(s)) == 0)
#define ARGUMENTS(s)	(strncmp(*argv,(s),strlen(s)) == 0)

	argc--; argv++;
	while (argc > 0)
	 { if (ARGUMENT("-a"))
	    { if (compareBasis)
	       { fprintf (stderr, "-a: comparison type previously set\n");
		 exit (2);
	       }
	      compareBasis = ACCESS_TIME;
	    }
	   else if (ARGUMENT ("-c"))
	    { if (compareBasis)
	       { fprintf (stderr, "-c: comparison type previously set\n");
		 exit (2);
	       }
	      compareBasis = STAT_TIME;
	    }
	   else if (ARGUMENT ("-s"))
	    { silentMode = 1;
	    }
	   else if (ARGUMENT ("-f"))
	    { force = 1;
	    }
	   else if (ARGUMENTS ("-"))
	    { fprintf (stderr, "tcmp file1 file2 [-s] [-a] [-f]\n");
	      exit (2);
	    }
	   else if (name1 == NULL)
	    { name1 = *argv;
	    }
	   else if (name2 == NULL)
	    { name2 = *argv;
	    }
	   else
	    { fprintf (stderr, "more than two file names specified\n");
	      exit (2);
	    }
	   argc--; argv++;
	 }

	if (!compareBasis)
	 { compareBasis = MODIFY_TIME;
	 }
	if (stat (name1, &s1) == -1)
	 { if (force)
	    { if (stat (name2, &s2) == -1)
	       { return (0);
	       }
	      else
	       { return (-1);
	       }
	    }
	   else
	    { fprintf (stderr, "Cannot stat file %s\n", name1);
	      exit (2);
	    }
	 }
	if (stat (name2, &s2) == -1)
	 { if (force)
	    { return (1);
	    }
	   else
	    { fprintf (stderr, "Cannot stat file %s\n", name2);
	      exit (2);
	    }
	 }

	switch (compareBasis)
	 { case ACCESS_TIME:
		if (s1.st_atime > s2.st_atime)
	         { rcode = 1;
		 }
		else if (s1.st_atime == s2.st_atime)
		 { rcode = 0;
		 }
	        else
		 { rcode = -1;
		 }
		break;
	   case MODIFY_TIME:
		if (s1.st_mtime > s2.st_mtime)
	         { rcode = 1;
		 }
		else if (s1.st_mtime == s2.st_mtime)
		 { rcode = 0;
		 }
	        else
		 { rcode = -1;
		 }
		break;
	   case STAT_TIME:
		if (s1.st_ctime > s2.st_ctime)
	         { rcode = 1;
		 }
		else if (s1.st_ctime == s2.st_ctime)
		 { rcode = 0;
		 }
	        else
		 { rcode = -1;
		 }
		break;
	 }

	if (!silentMode)
	 { switch (rcode)
	    { case 1:
	       { printf ("%s is more recent than %s.\n", name1, name2);
		 break;
	       }
	      case 0:
	       { printf ("both files have the same times.\n", name1, name2);
		 break;
	       }
	      case -1:
	       { printf ("%s is more recent than %s.\n", name2, name1);
		 break;
	       }
	    }
	 }

	return (rcode);
}
	
