/* program to maintain copyright notices */

#include <stdio.h>
#include <strings.h>

char **argvec;

main(argc, argv)
int argc;
char **argv;
{
	char *noticeFile = NULL;
	char *keyword = NULL;
	int inquire = 0;
#define UNDEF	       -1
#define STRIP		1
#define REPLACE		2
#define ADD		3
	int cmd = UNDEF;

	argvec = argv;
	argc--;
	argv++;

	while (argc >= 1 && **argv == '-')
	 { if (strncmp(*argv,"-a",2) == 0)
	    { if (strlen(*argv) <= 2 || cmd != UNDEF)
	       { argc = -1;
		 break;
	       }
	      noticeFile = *argv+2;
	      cmd = ADD;
	    }
	   else if (strncmp(*argv,"-r",2) == 0)
	    { if (strlen(*argv) <= 2 || cmd != UNDEF)
	       { argc = -1;
		 break;
	       }
	      noticeFile = *argv+2;
	      cmd = REPLACE;
	    }
	   else if (strcmp (*argv,"-s") == 0)
	    { if (cmd != UNDEF)
	       { argc = -1;
		 break;
	       }
	      cmd = STRIP;
	    }
	   else if (strcmp (*argv,"-i") == 0)
	    { inquire = 1;
	    }
	   else if (strcmp (*argv,"-k") == 0)
	    { if (keyword || argc <= 1)
	       { argc = -1;
		 break;
	       }
	      argc--;
	      argv++;
	      keyword = *argv;
	    }
	   else
	    { argc = -1;
	      break;
	    }
	   argc--;
	   argv++;
	 }
	if (argc == -1 || cmd == UNDEF)
	 { fprintf (stderr, "\
Usage: %s [-s | -r<noticeFile> | -a<noticeFile> ] \n\
       [-i] [-k keyword] files ...\n", 
		    argvec[0]);
	   exit (-1);
	 }
	if (noticeFile && fopen(noticeFile,"r") == NULL)
	 { fprintf (stderr, "%s: can't open file %s\n", argvec[0],
			    noticeFile);
	   exit (-1);
	 }

	while (argc > 0)
	 { adjustNotice (cmd, *argv, noticeFile, inquire, keyword);
	   argc--;
	   argv++;
	 }
}

#define BUFSIZE	0x1000

adjustNotice(cmd, srcFile, noticeFile, inquire, keyword)
int cmd;
char *srcFile;
char *noticeFile;
int inquire;
char *keyword;
{
	char buf1[BUFSIZE];
	char tmpName[256];
	char *bp;
	FILE *sf;
	FILE *tf;
	int lineNo;
	int firstNoticeLine;
	int lastNoticeLine;
	int keywordMatched;
	int k;

	static FILE *nf = NULL;

	if (nf)
	 { fclose(nf);
	   nf = NULL;
	 }
	if (noticeFile)
	 { nf = fopen (noticeFile, "r");
	 }
	if ((sf = fopen (srcFile, "r")) == NULL)
	 { fprintf (stderr, "%s: can't open file %s\n", argvec[0], srcFile);
	   return;
	 }

	keywordMatched = !keyword;

	/* Determine if we have a copyright notice to get rid of */
	lineNo = 0;
	firstNoticeLine = 0;
	lastNoticeLine = 0;
	while (bp = fgets (buf1, BUFSIZE, sf))
	 { lineNo++;
	   if (!firstNoticeLine)
	    { if (contains (buf1, "Notice of Copyright"))
	       { firstNoticeLine = lineNo;
		 if (!keywordMatched)
		  { keywordMatched = contains (buf1, keyword);
		  }
		 k = 0;
	       }
	    }
	   else
	    { if (!keywordMatched)
	       { keywordMatched = contains (buf1, keyword);
	       }
	      if (contains (buf1, "-=-=-=-=-=-=-="))
	       { lastNoticeLine = lineNo;
		 break;
	       }
	      else if (++k >= 256)
	       { firstNoticeLine = 0;
		 break;
	       }
	    }
	 }
	sf = freopen (srcFile, "r", sf);

	switch (cmd)
	 { case STRIP:
	    { if (!firstNoticeLine)
	       { printf ("%s: has no notice\n", srcFile);
		 fclose (sf);
		 return;
	       }
	      else if (!keywordMatched)
	       { printf ("%s: notice does not match\n", srcFile);
		 fclose (sf);
		 return;
	       }
	      else
	       { if (inquire && 
		     !query ("strip notice from %s (y/n)? ", srcFile))
		  { printf ("leaving\n");
		    fclose (sf);
		    return;
		  }
		 printf ("%s: stripping notice\n", srcFile);
	       }
	      break;
	    }
	   case ADD:
	    { if (!firstNoticeLine)
	       { if (inquire &&
		     !query ("add notice to %s (y/n)? ", srcFile))
		  { printf ("leaving\n");
		    fclose (sf);
		    return;
		  }
		 printf ("%s: adding notice\n", srcFile);
	       }
	      else
	       { printf ("%s: already has notice\n", srcFile);
		 fclose (sf);
		 return;
	       }
	      break;
	    }
	   case REPLACE:
	    { if (firstNoticeLine && keywordMatched)
	       { if (inquire &&
		     !query ("replace notice in %s (y/n)? ", srcFile))
		  { printf ("leaving\n");
		    fclose (sf);
		    return;
		  }
		 printf ("%s: replacing notice\n", srcFile);
	       }
	      else if (firstNoticeLine)
	       { printf ("%s: notice does not match\n", srcFile);
		 fclose (sf);
		 return;
	       }
	      else
	       { printf ("%s: does not have notice\n", srcFile);
		 fclose (sf);
		 return;
	       }
	      break;
	    }
	 }

	sprintf (tmpName, "%s.tmp%d\n", srcFile, getpid());
	if ((tf = fopen (tmpName, "w")) == NULL)
	 { fprintf (stderr, "%s: can't open file %s\n", argvec[0], tmpName);
	   fclose(sf);
	   return;
	 }

	/* If we already have a notice, then copy out the preceeding part
	   of the file. */
	if (firstNoticeLine)
	 { for (lineNo=1; lineNo<firstNoticeLine; lineNo++)
	    { fgets (buf1, BUFSIZE, sf);
	      fputs (buf1, tf);
	    }
	   for ( ; lineNo<=lastNoticeLine; lineNo++)
	    { fgets (buf1, BUFSIZE, sf);
	    }
	 }

	/* If we have a new copyright notice, add that on next */
	if (noticeFile)
	 { while (fgets (buf1, BUFSIZE, nf))
	    { fputs (buf1, tf);
	    }
	 }

	/* And now add on the rest of the first file */
	while (bp = fgets (buf1, BUFSIZE, sf))
	 { fputs (buf1, tf);
	 }
	    
	fclose (sf);
	fclose (tf);

	if (rename (tmpName, srcFile) < 0)
	 { fprintf (stderr, "%s: can't move %s to %s\n", 
			    argvec[0], tmpName, srcFile);
	   unlink (tmpName);
	 }
}

contains (s1, s2)
char *s1, *s2;
{
	/* return true if string s1 contains string s2 */

	char *cp;

	for (cp = s1; cp = index(cp, s2[0]); cp++)
	 { if (strncmp (cp, s2, strlen(s2)) == 0)
	    { return (1);
	    }
	 }
	return (0);
}

query(str, file)
char *str, *file;
{
	int code;
	char c;

	printf (str, file);
	code = ((c = getchar()) == 'y');
	while (c != '\n')
	 { c = getchar();
	 }
	return (code);
}
