// Edit using vi with directive:		:se ts=4
char sccsID[] =
  "@(#) cmpd.c V1.22 Copyright Julian H. Stacey 14th May 1987 - 2022-11-27\n";
/* Copyright, Liability etc:
 *		This code was written independently by Julian H.
 *		Stacey before earlier versions were also used or
 *		delivered with any other code for Stacey/VSL clients.
 *		Clients who receive such code are permitted to use
 *		& resell code etc, but Copyright is Not assigned
 *		to recipients.  & all Liability is disclaimed, &
 *		No Warranty granted for this free code that
 *		clients/recipients have Not paid for development of.
 * Bug to check:
 *		find . -type f -exec \
 *			cmpd -d-v {} /host/blak/av/video/jes_2012-03-20 \;
 * No report of syntax error.
 *
 * MANUAL EXISTS - See cmpd.1
 *	Synopsis: similar to unix cmp.c,
 *  but with much added delete if same.
 */

#ifdef	ournix	/* { */
#include "ournix.h"
#endif		/* ournix } */
#include	<stdio.h>
#include	<fcntl.h>
#include	<sys/types.h>
#include	<sys/stat.h>
#include	<string.h>

#ifdef hpux	/* { define PATH_MAX */
#include	<limits.h> /* see also sys/fs/vx_hpux.h, X11R5/X11/Xos.h */
#endif		/* hpux } */

#ifdef _M_SYS5 /* { SCO */
#include	<ansi/limits.h>
#define 	PATH_MAX	_POSIX_PATH_MAX
#endif		/* _M_SYS5 } */

/*	cpp -dM /dev/null | grep BSD
 *	#define __FreeBSD_cc_version 700003
 *	#define __VERSION__ "4.2.1 20070719  [FreeBSD]"
 *	#define __FreeBSD__ 7
 */
#ifdef __FreeBSD__ /* { PATH_MAX 1024 max bytes in pathname */
/* #include	<sys/syslimits.h>
 * not sure what in limits.h defines PATH_MAX,
 * but 2022-12-03 // I switched to limits.h to avoid a warning.
 */
#include	<limits.h>
#endif		/* __FreeBSD__ } */

#ifndef 	scs	/* {{ Not Symmetric S375 */
#include	<unistd.h>
#else		/* !scs }{ scs */
#include	<sys/param.h>
#endif		/* scs }} */

#ifdef		BSD		/* {{ */
#include	<sys/signal.h>
#else		/* BSD }{ !BSD */
#include	<signal.h>
#endif				/* !BSD }} */

#include	<sys/errno.h>	// for perror()

#define 	MAXPATHLEN	PATH_MAX	/* 1024 */

typedef char	FLAG ;
#define STRADR	&
typedef int	FD ;

#define strequ(a,b) (strcmp((a),(b)) == 0 )

static char	**g_argv ;
static int	g_argc;

static int	err_fail = 0 ;		/* if an open or unlink error occurs */
static int	diff_no = 0 ;
/* For scs & msdos:
	typedef struct	_iobuf FILE ;
	or
	#define FILE struct  _iobuf
*/
static FILE *err_fd ;
static char **ARGV ;


static char    txt_cant_stat[]  = "cannot stat";
static char    txt_cant_lstat[] = "cannot lstat";

extern char *strcat() ;

#ifndef EMBEDDED /* { */
/* EMBEDDED was only defined for when the program was embedded into
 * a project I did: OCE/oceres
 * were I vaguely recall cmpd.c ceased to be a stand alone prog,
 * &/or was called by a graphic click interface, with no args ?
 * something of that nature.
 *
 * Only used with -m flag, skips past email/news header until a
 * blank line is detected, Code could have been integrated, for
 * efficiency, but wont often be needed, & clearer to read like
 * this.  I admit single char input is horrible !  Note blank line
 * is "\n\n", "\n\020\n" is not recognised as a mail header/body
 * separator, though it would be nice if it was.
 */
	static int
skip(descrip,name)
	FD	descrip ;
	char	*name ;
	{
	char this ;
	char last = '\n' ;
	int	rslt ;

	while ( (rslt = read(descrip,&this,1)) == 1)
		{
		if ((this == '\n') && (last == '\n')) return(0) ;
		else last = this ;
		}
	if (rslt == 0) return(0) ;
	fprintf(err_fd,"%s: Read error while skipping %s mail header\n",
		*g_argv, name);
	err_fail = 1 ;
	diff_no++  ;
	return(1)  ;
	}
#endif /* !EMBEDDED } */

	static void
syntax()
	{
	fprintf(err_fd,
"Syntax:\n%s [-L] [-M] [-b] [-d] [-l[directory]] [-e] %s[-v] [--] file[s] %s\n"
		, "reference_file_or_directory_if_not_stdin.",
#ifndef EMBEDDED	/* { */
		"[-m] ",
#else			/* !EMBEDDED }{ EMBEDDED */
		" ",
#endif /* EMBEDDED	} */
		*g_argv);
	}

void exit(int);

#if MSDOS	/* { */
	/* MSDOS and some very old unixes don't have symbolic links */
	#define NO_SYMLINKS
#endif		/* MSDOS } */
#if BSD		/* { */
/* define DONT_USE_SYMLINK_SYS_CALL
	If you don't want to use the raw system call,
	and prefer to use system(".....");	*/
#undef	DONT_USE_SYMLINK_SYS_CALL
#endif		/* BSD } */

#define REF ( * (g_argv + g_argc - 1 ) )
	/* scs accepts g_argv[g_argc-1], 486 doesnt */
	/*
	 * Usually a reference directory when I use it, but could
	 * be a reference file, or a symbolic link to either a file
	 * or directory
	 */

	int
#ifdef EMBEDDED /* {{ */
	cmpd(argc, argv)
#else			/* EMBEDDED }{ !EMBEDDED */
	main(argc, argv)
#endif			/* !EMBEDDED }} */
	int argc;
	char **argv;
	{
	char	*pointer_del, *pointer_ref;
#define BUF_SIZE 16384
		/* 16384 = 0x4000
		 * JJLATER for maximum speed I could try
		 * to ensure same as shown by eg:
		 *	statv /etc/rc
		 *		Optimal I/O 16384
		 *	but consider
		 *		stat_buf_ref.st_blksize &
		 *		stat_buf_del.st_blksize
		 *	may vary in size on different file systems
		 */
	int	buf_size = BUF_SIZE ;
	char	buf_file_del[BUF_SIZE] ;
		/* Buffer of file that may be deleted*/
	char	buf_file_ref[BUF_SIZE] ; /* Reference buffer */
	FD	fd_file_del = (FD)0 ;	/* File to compare & possibly rm */

	FD	fd_file_ref ;
		/* Reference file (or directory?), never removed */
	int	length_del, length_ref, buf_len ;
	struct stat	stat_buf_ref ;
		/* stat() of reference file/directory */
	struct stat	stat_buf_del ;
		/* stat() & lstat() of file that that may be removed */
	char	name_ref[1024] ;
		/* Comparison reference file */
	FLAG	last_is_dir = 0 ;
		/* 1 If last arg detected as directory */
	FLAG	delete_f = 0 ;
		/* 1 to delete first of 2 equal files */
	FLAG	skip_f = 0 ;
		/* 1 to prevent delete (after evaluating) */
	FLAG	suppress_absent_f = 0 ;
		/* 1 to silence complaints of absent
			reference files (when trying to
			delete duplicate trees) */
	FLAG	suppress_link_f = 0 ;
		/* 1 to silence complaints of cmpd file link_to_file
		 * 	(which occurs eg from distfiles_cmpd script )
		 * 	It only suppresses complaint, but error count
		 * 	is still incremented.
		 */
	FLAG	verbose_f = 0 ;		/* 1 for verbose commentary */

#ifndef EMBEDDED	/* { */
	FLAG	mail_f = 0 ;
		/* 1 if comparing email body content
			(but not headers with eg "Subject:" etc )
			or news items, ie dont start compare
			till after blank line.
		 */
#endif /* !EMBEDDED	} */
	FLAG	pipe_f = 0 ;	/* 1 if comparing a pipe with a file */
	long	letter, lines, bytes ;	/* Line & byte count */
#ifndef NO_SYMLINKS	/* { */
	FLAG	link_create_f = 0 ;	/* 1 to to establish a symbolic link
									after deleting a file */
	char	*link_dir = (char *)0 ;
		/* Where to establish a symbolic link to (If unset,
		 * then to REF/file ) ie delete file & establish file
		 * -> link_dir/file (only works if delete_f asserted)
		 */

	char	link_target[PATH_MAX] ;
	FLAG	link_cmp_f = 0 ;
		 /* 1 to compare symbolic links instead of file data */
	FLAG	mode_f = 0 ;
		/* 1 if to compare modes as well as 2 file content */
#if DONT_USE_SYMLINK_SYS_CALL	/* { */
	char	link_str_cmd[20 + 2 * PATH_MAX] ;
#endif	/* DONT_USE_SYMLINK_SYS_CALL } */
	int system_result ;
#endif	/* !NO_SYMLINKS } */
	int lnklen;
	char target[MAXPATHLEN + 1];	/* Allow null terminator. */

	g_argv = argv ;
#ifdef	VSL	/* { */
#include	"../../include/vsl.h"
#endif		/* VSL } */

#ifdef TRY_LATER	/* { */
	/* 2022-11-27 I merged cmpd-devel.c & cmpd.c
	 *	 both from Apr 13 2020
	 *	The TRY_LATER version contained broken code,
	 */
	fprintf(stderr,
	 "Fatal error: new untested code, remake with -undef TRY_LATER\n");
	exit(1);
#endif	/* TRY_LATER } */

	g_argc = argc;
	err_fd = stderr ;
	for (argv++, argc--; argc > 0 ; )
		{	// things
		if (**argv != '-') break ;
		switch(*++*argv)
			{	// params
			case 'd':	delete_f = 1 ;	break ;
			case 'n':	skip_f = 1 ;	break ;

			case 's':	suppress_absent_f = 1 ; break ;

			case 'S':	suppress_link_f = 1 ; break ;

			case 'v':	verbose_f = 1;	break ;
#ifndef EMBEDDED	/* { */
			case 'm':	mail_f = 1;	break ;
#endif /* !EMBEDDED	} */
			case 'b':	buf_size = 512; break ;
			case '-':	pipe_f = 1 ;	break ;
			case 'e':	err_fd = stdout ; break ;
#ifndef NO_SYMLINKS	/* { */
			case 'l':	link_create_f = 1 ;
					if (*++*argv != '\0') link_dir = *argv ;
					delete_f = 1 ;
					break ;
			case 'L':	link_cmp_f = 1 ;
					fprintf(stderr,"'-L' not supported yet\n");
					exit(1);
					break ;
#endif	/* !NO_SYMLINKS } */
#ifdef TRY_LATER	/* { */
			case 'M':	mode_f = 1 ;
					break ;
#endif /* TRY_LATER } */
			default:	syntax() ;
					return(-1) ;
					break ;
			}	// params
		argv++ ; argc-- ;
		}	// things
	if ( (argc < 1) || ((argc == 1 ) && (pipe_f == 0))
		|| ((argc > 1 ) && pipe_f ))
		{
		syntax() ;
		return(-1) ;
		}
	if (!pipe_f)
		{
#ifndef TRY_LATER	/* {{ */
#define REF_DIR ( * (g_argv + g_argc - 1 ) )
	/* scs accepts g_argv[g_argc-1], 486 doesnt */
		// printf("Debug: Looking at reference %s\n",REF_DIR);
		if (stat(REF_DIR,STRADR stat_buf_ref) && !suppress_absent_f )
#else /* !TRY_LATER }{ TRY_LATER */
		// printf("Debug: Looking at reference %s\n",REF);
		if (stat(REF,STRADR stat_buf_ref_old) && !suppress_absent_f )
#endif /* TRY_LATER }} */
			{
			fprintf(err_fd, "%s: %s %s\n", *g_argv,
#ifndef TRY_LATER	/* {{ */
				txt_cant_stat, REF_DIR
#else /* !TRY_LATER }{ */
				txt_cant_stat, REF
#endif /* TRY_LATER }} */
				);
			perror(*g_argv);
			syntax() ;
			}
#ifndef TRY_LATER	/* {{ */
		// if (stat_buf_ref.st_mode & S_IFLNK)
			// Fails. Detects normal files. Why?
		if (S_ISLNK(stat_buf_ref.st_mode))
			// OK. Does not detect normal files.
#else /* !TRY_LATER }{ */
		// if (stat_buf_ref_old.st_mode & S_IFLNK)
			// Fails. Detects normal files. Why?
		if (S_ISLNK(stat_buf_ref_old.st_mode))
			// OK. Does not detect normal files.
#endif /* TRY_LATER }} */
			{
			fprintf(err_fd, "%s: Warning: %s\n", *g_argv, "Symbolic Link" ) ;
#if 0		/* { */
			// Code not complete yet.
			//   So just let it drop through to & S_IFDIR
			//	Can one see both S_IFLNK & S_IFDIR.
#ifndef TRY_LATER	/* {{ */
			if (lstat(REF_DIR,STRADR stat_buf_ref))
				// stat_buf_ref is now reloaded
				// for symbolic link specific.
#else /* !TRY_LATER }{ */
			if (lstat(REF,STRADR stat_buf_ref_old))
				// stat_buf_ref_old is now reloaded
				// for symbolic link specific.
#endif /* TRY_LATER }} */
				{
				fprintf(err_fd,
					"%s: %s %s\n", *g_argv,
					 txt_cant_lstat,
#ifndef TRY_LATER	/* {{ */
						 REF_DIR
#else /* !TRY_LATER }{ */
						 REF
#endif /* TRY_LATER }} */
					);
				syntax() ;
				}
				// Get link path content
				// SEE man 1 readlink, man 2 readlink, as used in
				// /usr/src/usr.bin/find/ls.c
			// Store that path somewhere for later comparison.
#endif		/* 0 } */
			}
		if (
#ifndef TRY_LATER	/* {{ */
			stat_buf_ref.st_mode
#else /* !TRY_LATER }{ */
			stat_buf_ref_old.st_mode
#endif /* TRY_LATER }} */
				& S_IFDIR)
			{
			last_is_dir = 1;
			/* Detect & warn of construct such as "cmp fred jim ."
			 * (because == "cmp fred ./fred" && "cmp jim ./jim"
			 *	== TRUE (always!) ).
			 */
			if (strequ(
#ifndef TRY_LATER	/* {{ */
				REF_DIR
#else /* !TRY_LATER }{ */
				REF
#endif /* TRY_LATER }} */
				,"."))
			fprintf(err_fd, "%s: Warning: %s\n%s\n",
				*g_argv,
				"Comparison using \".\" as reference directory,",
				"will always result in equality.") ;
			}
		else if ( argc > 2 )
			{
			fprintf(err_fd,
				"%s: Error: %s should be a directory\n",
				*g_argv,
#ifndef TRY_LATER	/* {{ */
				 REF_DIR
#else /* !TRY_LATER }{ */
				 REF
#endif /* TRY_LATER }} */
				);
			syntax() ;
			}
		}	// !pipe_f
	while (argc-- >= (2 - pipe_f))
		{
		if (pipe_f)
			{
			fd_file_ref = fileno(stdin) ;
#ifdef MSDOS	/* { */
			/* JJLATER For Msdos: I dont know whether stdin is
			 * already open in binary mode, or whether something
			 * extra should be done here */
#endif		/* MSDOS } */
			}
		else
			{	// !pipe_f
			if (stat(*argv,STRADR
#ifndef TRY_LATER	/* {{ */
				 stat_buf_del
#else /* !TRY_LATER }{ */
				 stat_buf_del_old
#endif /* TRY_LATER }} */
				) )
				{
				fprintf(err_fd,
					"%s: Warning, cannot stat %s\n",
						/* JJLATER why is it Warning,
						 * cannot stat here but Error,
						 * cannot stat below.
						 */
					*g_argv,*argv);
				err_fail = 1 ; diff_no++ ; argv++ ; continue ;
				}
			/* assemble name of reference file */
			(void) strcpy(name_ref,
#ifndef TRY_LATER	/* {{ */
				 REF_DIR
#else /* !TRY_LATER }{ */
				 REF
#endif /* TRY_LATER }} */
				 );
			if (last_is_dir)
				{
				(void)strcat(name_ref,"/");
				(void)strcat(name_ref,*argv);
				}
#ifndef MSDOS	/* { */
			/* Avoid deleting a single file pointed to
			 * by different paths, such as fred &
			 * ../freds_dir/fred, whether by direct naming
			 * or by symbolic link.     Compare device
			 * major minor + inode numbers here, if all
			 * the same refuse to delete!  Unfortunately
			 * Msdos doesnt offer inode numbers, so we
			 * cant check if we are referring to the same
			 * file by 2 different pathnames ( such as
			 * ../../freds_parents_dir/freds_dir/fred, &
			 * ../freds_dir/fred )
			 */
			if (delete_f)
				{
				/* avoid deleting a file that is named by
				 * 2 different paths, but has only one link,
				 * such as cmp -d fred ../freds_dir/fred
				 */
				if (stat(name_ref, STRADR
#ifndef TRY_LATER	/* {{ */
					 stat_buf_ref
#else /* TRY_LATER }{ */
					 stat_buf_ref_old
#endif /* TRY_LATER }} */
					) )
					{
					if (!suppress_absent_f) fprintf(err_fd,
						"%s: Error, cannot stat %s\n",
						*g_argv, name_ref) ;
					err_fail = 1 ; diff_no++ ;
					argv++ ; continue ;
					}
				if ( (
#ifndef TRY_LATER	/* {{ */
					stat_buf_del.st_dev     == stat_buf_ref.st_dev
#else /* TRY_LATER }{ */
					stat_buf_del_old.st_dev == stat_buf_ref_old.st_dev
#endif /* TRY_LATER }} */
					) /* device (dev_t) */
					&& (
#ifndef TRY_LATER	/* {{ */
						stat_buf_del.st_ino     == stat_buf_ref.st_ino
#else /* TRY_LATER }{ */
						stat_buf_del_old.st_ino == stat_buf_ref_old.st_ino
#endif /* TRY_LATER }} */
					) /* inode (ino_t) */
					&& (
#ifndef TRY_LATER	/* {{ */
						stat_buf_del.st_nlink
#else /* TRY_LATER }{ */
						stat_buf_del_old.st_nlink
#endif /* TRY_LATER }} */
						== 1 ) )
					{
					/* both names point to same inode */
#ifdef	SYM_LINKS_AVAIL /* { */
					/* see if first name is just a symbolic
					  link, if so allow deletion */
					if (lstat(*argv, STRADR
#ifndef TRY_LATER	/* {{ */
						 stat_buf_del
#else /* TRY_LATER }{ */
						 stat_buf_del_old
#endif /* TRY_LATER }} */
						))
						{
						fprintf(err_fd,
							"%s: Error, cannot lstat %s\n",
							*g_argv, *argv) ;
						perror(*g_argv);
						err_fail = 1 ; diff_no++ ;
						argv++ ; continue ;
						}
#endif		/* SYM_LINKS_AVAIL } */
					if (
#ifdef	SYM_LINKS_AVAIL /* {{ */
					(
#ifndef TRY_LATER	/* {{ */
					stat_buf_del.st_mode
#else /* TRY_LATER }{ */
					stat_buf_del_old.st_mode
#endif /* TRY_LATER }} */
						 & S_IFMT) != S_IFLNK
						/* IFLNK == sym link */
#else		/* }{ !SYM_LINKS_AVAIL */
	/* no symbolic linked files on non SYM_LINKS_AVAIL unix */	1
#endif		/* !SYM_LINKS_AVAIL }} */
						) {
						/* Not an innocuous symbolic
						 * link, so avoid deleting.
						 */
					    if ( suppress_link_f == 0 ) /* Complain */
						fprintf(err_fd,
#ifdef	SYM_LINKS_AVAIL /* {{ */
				"%s: %s %s & %s %s,\n\t%s, & %s %s; %s\n",
#else		/* }{ */
				"%s: %s %s & %s %s,\n\t%s; %s\n",
#endif		/* !SYM_LINKS_AVAIL }} */
						*g_argv, "Error: ", *argv, name_ref,
				"share same device (major & minor) & inode ",
						"link count is 1",
#ifdef	SYM_LINKS_AVAIL /* { */
						*argv, "is not a symbolic link",
#endif		/* SYM_LINKS_AVAIL } */
						"Skipping."
							);
						diff_no++ ; argv++ ; continue ;
						}
					}
				}
#endif		/* } !MSDOS */
			if ((fd_file_ref = open(name_ref,O_RDONLY
#ifdef	MSDOS	/* { */
							| O_BINARY
#endif		/* MSDOS } */
								)) == -1)
				{
				fprintf(err_fd,"%s: Cannot open %s\n",
					*g_argv,name_ref);
				if (fd_file_del != (FD)0) (void) close(fd_file_del) ;
				err_fail = 1 ; diff_no++ ;
				argv++ ; continue ;
				}
#ifdef TRY_LATER	/* { */
				  // JJLATER what if name_ref is a dir not a file ?
			if (mode_f)	// flag 'M'
				{
				if (stat(name_ref, &stat_buf_ref_new))
					{
					perror(*g_argv) ;
					fprintf(stderr,"%s\n",name_ref);
					err_fail = 1 ; diff_no++ ;
					argv++ ; continue ;
					}
				} // JJLATER what if name_ref is a dir not a file ?

#endif /* TRY_LATER } */
			}
		/* now check if we are comparing device with device */
#ifndef TRY_LATER	/* {{ */
		if (((stat_buf_del.st_mode & S_IFMT) != S_IFREG )
			&& ((stat_buf_del.st_mode & S_IFMT) ==
				(stat_buf_ref.st_mode & S_IFMT))
			&&  (stat_buf_del.st_rdev == stat_buf_ref.st_rdev) )
#else /* TRY_LATER }{ */
		if (((stat_buf_del_old.st_mode & S_IFMT) != S_IFREG )
			&& ((stat_buf_del_old.st_mode & S_IFMT) ==
				(stat_buf_ref_old.st_mode & S_IFMT))
			&&  (stat_buf_del_old.st_rdev ==
					 stat_buf_ref_old.st_rdev) )
#endif /* TRY_LATER }} */
			{
			/* JJ add code here, do something about comparing
			 *  2 sym links, & a sym link to a fifo
			 *		386bsd values:
			 *		S_IFMT		0170000 type of file
			 *		S_IFIFO 	0010000 named pipe (fifo)
			 *		S_IFCHR 	0020000 character special
			 *		S_IFDIR 	0040000 directory
			 *		S_IFBLK 	0060000 block special
			 *		S_IFREG 	0100000 regular
			 *		S_IFLNK 	0120000 symbolic link
			 *		S_IFSOCK	0140000 socket
			 */
			}
		if ((fd_file_del = open(*argv,O_RDONLY
#ifdef	MSDOS	/* { */
						| O_BINARY
#endif		/* } */
				))	== -1)
			{
			fprintf(err_fd,"%s: Cannot open %s\n",*g_argv,*argv);
			err_fail = 1 ; diff_no++ ; argv++ ; continue ;
			}
#ifdef TRY_LATER	/* { */
		if (mode_f)	// flag 'M'
			{
			if (stat(*argv, &stat_buf_del_new))
				{
				perror(*g_argv) ;
				fprintf(stderr,"%s\n",*argv);
				err_fail = 1 ; diff_no++ ;
				argv++ ; continue ;
				}
			}
#endif /* TRY_LATER } */
		letter = lines = bytes = 1 ;
#ifndef EMBEDDED	/* { */
		if (mail_f)
			{
			skip(fd_file_ref,name_ref) ;
			skip(fd_file_del, (pipe_f) ? "pipe input" :*argv);
			}
#endif /* EMBEDDED	} */
		for (;;)
			{
			length_del = 0 ;
			if ( ( ( length_ref =
				read(fd_file_ref, buf_file_ref, buf_size) ) < 0)
			|| ( ( length_del =
				read(fd_file_del, buf_file_del,
					(length_ref == 0) ? buf_size : length_ref
					/* not just buf_size as
					 *		{ read on a pipe  |
					 *		buf_size might be > 4K,
					 *		 but read on a pipe }
					 *	cannot return more than 4K
					 */
					)) < 0 ) )
				{
				fprintf(err_fd,"%s: Read error on ", *g_argv);
				if (length_del < 0 )
					fprintf(err_fd,"%s\n",
						(pipe_f) ? "pipe input" : *argv);
				else	{
					if (last_is_dir) fprintf(err_fd,"%s/%s\n",
#ifndef TRY_LATER	/* {{ */
						REF_DIR
#else /* TRY_LATER }{ */
						REF
#endif /* TRY_LATER }} */
							, *argv);
					else fprintf(err_fd,"%s\n",*argv);
					}
				err_fail = 1 ; diff_no++ ; break ;
				}
			if ((length_del == 0) && (length_ref == 0))
				{
				if (verbose_f)
					{
					if (last_is_dir )
						// JJLATER is last_is_dir wrong ?
						// Surely I want to delete even
						// if just 2 files are
						// the same & no directory as last arg ?
						printf("%s ",*argv);
#ifndef TRY_LATER	/* {{ */
						printf( delete_f ?
							"Deleted\n": "Same\n");
#else /* TRY_LATER }{ */
						{
						printf( delete_f ?
							"Zero size, Can Delete\n":
							 "Same Content\n");
						if (mode_f)	// delete if modes also match
							{
							printf("%s ",*argv);
							if (stat_buf_ref_new.st_mode ==
								 stat_buf_del_new.st_mode)
							printf("Same Modes\n");
							else printf("Different Modes.\n");
							}
						}
#endif /* TRY_LATER }} */
					}
				if (delete_f)
					{
#ifndef NO_SYMLINKS	/* { */
					if (link_create_f)
						 (void) signal(SIGINT, SIG_IGN);
#endif	/* !NO_SYMLINKS */ /* } */
#ifndef TRY_LATER	/* {{ */
					if (!skip_f)
#else /* TRY_LATER }{ */
					if (!skip_f &&
						! ( mode_f &&
							( stat_buf_ref_new.st_mode ==
			    		stat_buf_del_new.st_mode ) ) )
#endif /* TRY_LATER }} */
						{
#ifdef TRY_LATER	/* { */
						if (verbose_f)
							 printf("Deleting %s\n", *argv);
#endif /* TRY_LATER } */
						if (unlink(*argv))
							{
	/* JJLATER consider adding "if !suppress_absent_f" */
							perror(*g_argv);
							diff_no++ ;
							err_fail = 1 ;
							}
						}
#ifndef NO_SYMLINKS		/* { */
					if (link_create_f)
						{
						/* create a sym. link */
						if (link_dir == (char *)0)
							strcpy(link_target,
							name_ref );
						else sprintf(link_target,
							"%s/%s",link_dir,*argv);
#if DONT_USE_SYMLINK_SYS_CALL	/* { */
						sprintf(link_str_cmd,
							"ln -s %s %s\n",
							link_target,*argv);
						if (system_result =
							system(link_str_cmd))
#else							/* DONT_USE_SYMLINK_SYS_CALL }{
									 !DONT_USE_SYMLINK_SYS_CALL */
						if ((system_result =
							symlink(link_target,
							*argv)))
							/* I put un-necessary brackets in
							   to silence the gcc -Wall warning:
								"suggest parentheses around
								 assignment
									 used as truth value"
							*/
#endif							/* !DONT_USE_SYMLINK_SYS_CALL } */
							{
							extern int errno;
							perror(*g_argv);
							printf(
								"Error %d sym. linking %s -> %s\n",
								errno,*argv,link_target);
							err_fail = 1 ;
							}
						(void) signal(SIGINT, SIG_DFL);
						}
#endif						/* !NO_SYMLINKS } */
					}
				break ;
				}
			buf_len = (length_del < length_ref ) ?
				length_del : length_ref ;
			pointer_del = buf_file_del; pointer_ref = buf_file_ref ;
			while (buf_len && (*pointer_del == *pointer_ref) )
				{
				bytes++ ; letter++ ;
				if ((*pointer_del & 0xFF) == '\n')
					{ letter = 1 ; lines++ ; }
				buf_len--; pointer_del++; pointer_ref++ ;
				}
			if ((buf_len == 0) && (length_del == length_ref))
				continue ;
			if (!delete_f || verbose_f)
				{
				if (last_is_dir) printf("%s ",*argv);
				printf(
			"Different: char %ld in line %ld, (byte %ld)\n",
					letter, lines, bytes);
				}
			diff_no++ ;
			break ;
			}
		if (!pipe_f) (void) close(fd_file_ref) ;
		(void) close(fd_file_del);
		argv++ ;
		}
	if (err_fail) return(-diff_no)	; else return(diff_no) ;
	}
