/*
 * DIFFPW -- report password file entries which differ
 *
 * USAGE
 * diffnewpw new [ old ]
 *	old and new are assumed to be password files sorted by the
 *	first field.  Lines in new with the same first field as a
 *	line in old, but with different second fields, are printed;
 *	lines in new not in old are also printed.  If new is omitted,
 *	the contents of old is printed.
 *	(Note for System V based systems: the password field does NOT
 *	include the aging component, so if ONLY that changes, the lines
 *	will still match.)
 */	
/****************************************************************
 * Copyright notice.						*
 * This software is copyrighted (c) 1991 by Matt Bishop and the *
 * Trustees of Dartmouth College.  All rights reserved.		*
 *								*
 * Author:	Matt Bishop					*
 * Address:	Department of Mathematics and Computer Science	*
 *		Dartmouth College				*
 *		Hanover, NH  03755-1831				*
 *		USA						*
 * telephone:	+1 603 646 3267					*
 * fax:		+1 603 646 1312					*
 * internet:	Matt.Bishop@dartmouth.edu			*
 * usenet:	...!decvax!dartvax!Matt.Bishop			*
 ****************************************************************/
 
#ifndef lint
static char *version = "Version GAMMA 6/31/91 Matt.Bishop@dartmouth.edu";
#endif

#include <stdio.h>
#ifdef __STDC__
#	include <stdlib.h>
#	include <strings.h>
#else
#	include "stdlib.h"
#	include "string.h"
#endif

/*
 * structure used to hold password file entry
 */
struct field {
	char namef[BUFSIZ];		/* name field */
	char passwdf[BUFSIZ];		/* password field */
	char restf[BUFSIZ];		/* rest of the line */
} fold, fnew;			/* one for old and one for new */

/*
 * forward declaration
 */
char *getfield();		/* get next line of password file */

/*
 * library functions
 */
void exit();

void main(argc, argv)
int argc;
char *argv[];
{
	register int getnew;	/* 1 if you need to read a line from new */
	register int getold;	/* 1 if you need to read a line from old */
	register FILE *fnewp, *foldp;	/* file pointers */
	register int cmp;	/* result of comparison of field 1 */
	register int prt;	/* 1 if new line to be printed */
	char buf[BUFSIZ];	/* input buffer for overflow */

	/*
	 * open new file -- abort on error
	 */
	if ((fnewp = fopen(argv[1], "r")) == NULL){
		perror(argv[1]);
		exit(1);
	}
	/*
	 * open old file -- if error, print new file
	 */
	if ((foldp = fopen(argv[2], "r")) == NULL){
		while(fgets(buf, BUFSIZ, fnewp) != NULL)
			fputs(buf, stdout);
		exit(0);
	}

	/*
	 * comparison loop
	 * initially, need a line from each file
	 */
	getold = getnew = 1;
	while(!feof(fnewp) && !feof(foldp)){
		/* read the required line */
		if (getnew && getfield(&fnew, fnewp) == NULL)
			break;
		if (getold && getfield(&fold, foldp) == NULL)
			break;
		/* assume a complete match and nothing more in files */
		getnew = getold = prt = 0;
		/* first fields match -- print if seconds differ */
		/* also advance to next line in both files       */
/*###93 [cc] warning: implicit declaration of function `strcmp'%%%*/
		if ((cmp = strcmp(fnew.namef, fold.namef)) == 0){
			prt = (strcmp(fnew.passwdf, fold.passwdf) != 0);
			getnew = getold = 1;
		}
		/* first fields in "new" before that in "old"    */
		/* print the line, advance to next line in "new" */
		else if (cmp < 0)
			getnew = prt = 1;
		/* first fields in "old" before that in "new"    */
		/* advance to next line in "old"		 */
		else
			getold = 1;
		/* print the line */
		if (prt){
			printf("%s%s%s", fnew.namef, fnew.passwdf, fnew.restf);
			prt = 0;
		}
	}
	/*
	 * copy out the rest of the new file
	 */
	while(fgets(buf, BUFSIZ, fnewp) != NULL)
		fputs(buf, stdout);
	exit(0);
/*###117 [cc] warning: control reaches end of non-void function%%%*/
}

/*
 * return a pointer to the next line in the file, and split it into
 * a field structure: first field is name, next is password, and last
 * is rest of the line
 */
char *getfield(ptr, fp)
struct field *ptr;		/* pointer to structure to be filled */
FILE *fp;			/* pointer to relevant file */
{
	static char buf[BUFSIZ];	/* input buffer */
	register char *f, *b;		/* used to walk char arrays */

	/*
	 * read the input line
	 */
	if (fgets(buf, BUFSIZ, fp) == NULL)
		return(NULL);
	/*
	 * break out the first field (name)
	 */
	f = ptr->namef;
	b = buf;
	while((*f = *b) != '\0' && *f != ':'){
		f++;
		b++;
	}
	*f = '\0';
	/*
	 * break out the second field (password)
	 */
	f = ptr->passwdf;
	b++;
	while((*f = *b) != '\0' && *f != ':' && *f != ','){
		f++;
		b++;
	}
	*f = '\0';
	/*
	 * save the third field (everything else)
	 * and return pointer to input
	 */
/*###160 [cc] warning: implicit declaration of function `strcpy'%%%*/
	strcpy(ptr->restf, b);
	return(buf);
}
