xref: /titanic_53/usr/src/cmd/sdiff/sdiff.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate 	/*
34*7c478bd9Sstevel@tonic-gate 	 *	sdiff [-l] [-s] [-w #] [-o output] file1 file2
35*7c478bd9Sstevel@tonic-gate 	 *	does side by side diff listing
36*7c478bd9Sstevel@tonic-gate 	 *	-l leftside only for identical lines
37*7c478bd9Sstevel@tonic-gate 	 *	-s silent; only print differences
38*7c478bd9Sstevel@tonic-gate 	 *	-w # width of output
39*7c478bd9Sstevel@tonic-gate 	 *	-o output  interactive creation of new output commands:
40*7c478bd9Sstevel@tonic-gate 	 *		s	silent; do not print identical lines
41*7c478bd9Sstevel@tonic-gate 	 *		v	turn off silent
42*7c478bd9Sstevel@tonic-gate 	 *		l	copy left side to output
43*7c478bd9Sstevel@tonic-gate 	 *		r	copy right side to output
44*7c478bd9Sstevel@tonic-gate 	 *		e l	call ed with left side
45*7c478bd9Sstevel@tonic-gate 	 *		e r	call ed with right side
46*7c478bd9Sstevel@tonic-gate 	 *		e b	call ed with cat of left and right
47*7c478bd9Sstevel@tonic-gate 	 *		e	call ed with empty file
48*7c478bd9Sstevel@tonic-gate 	 *		q	exit from program
49*7c478bd9Sstevel@tonic-gate 	 *
50*7c478bd9Sstevel@tonic-gate 	 *	functions:
51*7c478bd9Sstevel@tonic-gate 	 *	cmd	decode diff commands
52*7c478bd9Sstevel@tonic-gate 	 *	put1	output left side
53*7c478bd9Sstevel@tonic-gate 	 *	put2	output right side
54*7c478bd9Sstevel@tonic-gate 	 *	putmid	output gutter
55*7c478bd9Sstevel@tonic-gate 	 *	putline	output n chars to indicated file
56*7c478bd9Sstevel@tonic-gate 	 *	getlen	calculate length of strings with tabs
57*7c478bd9Sstevel@tonic-gate 	 *	cmdin	read and process interactive cmds
58*7c478bd9Sstevel@tonic-gate 	 *	cpp	copy from file to file
59*7c478bd9Sstevel@tonic-gate 	 *	edit	call ed with file
60*7c478bd9Sstevel@tonic-gate 	 */
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate #include <stdio.h>
63*7c478bd9Sstevel@tonic-gate #include <ctype.h>
64*7c478bd9Sstevel@tonic-gate #include <signal.h>
65*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
66*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
67*7c478bd9Sstevel@tonic-gate #include <sys/wait.h>
68*7c478bd9Sstevel@tonic-gate #include <unistd.h>
69*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
70*7c478bd9Sstevel@tonic-gate #include <locale.h>
71*7c478bd9Sstevel@tonic-gate #include <limits.h>
72*7c478bd9Sstevel@tonic-gate #include <string.h>
73*7c478bd9Sstevel@tonic-gate #include <wchar.h>
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate #define	LMAX	BUFSIZ
76*7c478bd9Sstevel@tonic-gate #define	BMAX	BUFSIZ
77*7c478bd9Sstevel@tonic-gate #define	STDOUT	1
78*7c478bd9Sstevel@tonic-gate #define	WGUTTER	6
79*7c478bd9Sstevel@tonic-gate #define	WLEN	(WGUTTER * 2 + WGUTTER + 2)
80*7c478bd9Sstevel@tonic-gate #define	PROMPT	'%'
81*7c478bd9Sstevel@tonic-gate 
82*7c478bd9Sstevel@tonic-gate static const char	twoblanks[3] = "  ";
83*7c478bd9Sstevel@tonic-gate 
84*7c478bd9Sstevel@tonic-gate static const char	*DIFF	= "diff -b ";
85*7c478bd9Sstevel@tonic-gate static char	diffcmd[BMAX];
86*7c478bd9Sstevel@tonic-gate static char	inbuf[10];
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate static int	llen = 130;	/* Default maximum line length written out */
89*7c478bd9Sstevel@tonic-gate static int	hlen;		/* Half line length with space for gutter */
90*7c478bd9Sstevel@tonic-gate static int	len1;		/* Calculated length of left side */
91*7c478bd9Sstevel@tonic-gate static int	nchars;		/* Number of characters in left side - */
92*7c478bd9Sstevel@tonic-gate 					/* used for tab expansion */
93*7c478bd9Sstevel@tonic-gate static char	change = ' ';
94*7c478bd9Sstevel@tonic-gate static int	leftonly = 0;	/* if set print left side only for */
95*7c478bd9Sstevel@tonic-gate 					/* identical lines */
96*7c478bd9Sstevel@tonic-gate static int	silent = 0;	/* if set do not print identical lines */
97*7c478bd9Sstevel@tonic-gate static int	midflg = 0;	/* set after middle was output */
98*7c478bd9Sstevel@tonic-gate static int	rcode = 0;	/* return code */
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate 
101*7c478bd9Sstevel@tonic-gate static char	*file1;
102*7c478bd9Sstevel@tonic-gate static FILE	*fdes1;
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate static char	*file2;
105*7c478bd9Sstevel@tonic-gate static FILE	*fdes2;
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate static FILE	*diffdes;
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate static int oflag;
110*7c478bd9Sstevel@tonic-gate static char	*ofile;
111*7c478bd9Sstevel@tonic-gate static FILE	*odes;
112*7c478bd9Sstevel@tonic-gate 
113*7c478bd9Sstevel@tonic-gate static char	*ltemp;
114*7c478bd9Sstevel@tonic-gate static FILE	*left;
115*7c478bd9Sstevel@tonic-gate 
116*7c478bd9Sstevel@tonic-gate static char	*rtemp;
117*7c478bd9Sstevel@tonic-gate static FILE	*right;
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate static FILE *tempdes;
120*7c478bd9Sstevel@tonic-gate static char *temp;
121*7c478bd9Sstevel@tonic-gate 
122*7c478bd9Sstevel@tonic-gate /* decoded diff cmd- left side from to; right side from, to */
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate static int from1, to1, from2, to2;
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate static int num1, num2;		/* line count for left side file and right */
127*7c478bd9Sstevel@tonic-gate static int tempfd = -1;
128*7c478bd9Sstevel@tonic-gate 
129*7c478bd9Sstevel@tonic-gate static char	*filename(char *, char *);
130*7c478bd9Sstevel@tonic-gate static char	*fgetline(FILE *);
131*7c478bd9Sstevel@tonic-gate static int	put1(void);
132*7c478bd9Sstevel@tonic-gate static int	put2(void);
133*7c478bd9Sstevel@tonic-gate static void	putline(FILE *, char *, int);
134*7c478bd9Sstevel@tonic-gate static int	cmd(char *);
135*7c478bd9Sstevel@tonic-gate static int	getlen(int, char *);
136*7c478bd9Sstevel@tonic-gate static void	putmid(int);
137*7c478bd9Sstevel@tonic-gate static void	error(char *, char *);
138*7c478bd9Sstevel@tonic-gate static void	onintr(void);
139*7c478bd9Sstevel@tonic-gate static void	sremove(void);
140*7c478bd9Sstevel@tonic-gate static void	cmdin(void);
141*7c478bd9Sstevel@tonic-gate static void	cpp(char *, FILE *, FILE *);
142*7c478bd9Sstevel@tonic-gate static void	edit(char *);
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate void
145*7c478bd9Sstevel@tonic-gate main(int argc, char **argv)
146*7c478bd9Sstevel@tonic-gate {
147*7c478bd9Sstevel@tonic-gate 	int	com;
148*7c478bd9Sstevel@tonic-gate 	int	n1, n2, n;
149*7c478bd9Sstevel@tonic-gate 	char	*bp;
150*7c478bd9Sstevel@tonic-gate 	int	lfd = -1;
151*7c478bd9Sstevel@tonic-gate 	int	rfd = -1;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
154*7c478bd9Sstevel@tonic-gate 		(void) signal((int)SIGHUP, (void (*)(int))onintr);
155*7c478bd9Sstevel@tonic-gate 	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
156*7c478bd9Sstevel@tonic-gate 		(void) signal((int)SIGINT, (void (*)(int))onintr);
157*7c478bd9Sstevel@tonic-gate 	if (signal(SIGPIPE, SIG_IGN) != SIG_IGN)
158*7c478bd9Sstevel@tonic-gate 		(void) signal((int)SIGPIPE, (void (*)(int))onintr);
159*7c478bd9Sstevel@tonic-gate 	if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
160*7c478bd9Sstevel@tonic-gate 		(void) signal((int)SIGTERM, (void (*)(int))onintr);
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
163*7c478bd9Sstevel@tonic-gate #if	!defined(TEXT_DOMAIN)
164*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"
165*7c478bd9Sstevel@tonic-gate #endif
166*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate 	while (--argc > 1 && **++argv == '-') {
169*7c478bd9Sstevel@tonic-gate 		switch (*++*argv) {
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 		case 'w':
172*7c478bd9Sstevel@tonic-gate 			/* -w# instead of -w # */
173*7c478bd9Sstevel@tonic-gate 			if (*++*argv)
174*7c478bd9Sstevel@tonic-gate 				llen = atoi(*argv);
175*7c478bd9Sstevel@tonic-gate 			else {
176*7c478bd9Sstevel@tonic-gate 				argc--;
177*7c478bd9Sstevel@tonic-gate 				llen = atoi(*++argv);
178*7c478bd9Sstevel@tonic-gate 			}
179*7c478bd9Sstevel@tonic-gate 			if (llen < WLEN)
180*7c478bd9Sstevel@tonic-gate 				error(gettext("Wrong line length %s"), *argv);
181*7c478bd9Sstevel@tonic-gate 			if (llen > LMAX)
182*7c478bd9Sstevel@tonic-gate 				llen = LMAX;
183*7c478bd9Sstevel@tonic-gate 			break;
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 		case 'l':
186*7c478bd9Sstevel@tonic-gate 			leftonly++;
187*7c478bd9Sstevel@tonic-gate 			break;
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 		case 's':
190*7c478bd9Sstevel@tonic-gate 			silent++;
191*7c478bd9Sstevel@tonic-gate 			break;
192*7c478bd9Sstevel@tonic-gate 		case 'o':
193*7c478bd9Sstevel@tonic-gate 			oflag++;
194*7c478bd9Sstevel@tonic-gate 			argc--;
195*7c478bd9Sstevel@tonic-gate 			ofile = *++argv;
196*7c478bd9Sstevel@tonic-gate 			break;
197*7c478bd9Sstevel@tonic-gate 		default:
198*7c478bd9Sstevel@tonic-gate 			error(gettext("Illegal argument: %s"), *argv);
199*7c478bd9Sstevel@tonic-gate 		}
200*7c478bd9Sstevel@tonic-gate 	}
201*7c478bd9Sstevel@tonic-gate 	if (argc != 2) {
202*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, gettext(
203*7c478bd9Sstevel@tonic-gate 		"Usage: sdiff [-l] [-s] [-o output] [-w #] file1 file2\n"));
204*7c478bd9Sstevel@tonic-gate 		exit(2);
205*7c478bd9Sstevel@tonic-gate 	}
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 	file1 = *argv++;
208*7c478bd9Sstevel@tonic-gate 	file2 = *argv;
209*7c478bd9Sstevel@tonic-gate 	file1 = filename(file1, file2);
210*7c478bd9Sstevel@tonic-gate 	file2 = filename(file2, file1);
211*7c478bd9Sstevel@tonic-gate 	hlen = (llen - WGUTTER +1)/2;
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 	if ((fdes1 = fopen(file1, "r")) == NULL)
214*7c478bd9Sstevel@tonic-gate 		error(gettext("Cannot open: %s"), file1);
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate 	if ((fdes2 = fopen(file2, "r")) == NULL)
217*7c478bd9Sstevel@tonic-gate 		error(gettext("Cannot open: %s"), file2);
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	if (oflag) {
220*7c478bd9Sstevel@tonic-gate 		if (tempfd == -1) {
221*7c478bd9Sstevel@tonic-gate 			temp = strdup("/tmp/sdiffXXXXXX");
222*7c478bd9Sstevel@tonic-gate 			tempfd = mkstemp(temp);
223*7c478bd9Sstevel@tonic-gate 			if (tempfd == -1) {
224*7c478bd9Sstevel@tonic-gate 				error(gettext(
225*7c478bd9Sstevel@tonic-gate 					"Cannot open/create temp %s"), temp);
226*7c478bd9Sstevel@tonic-gate 				free(temp);
227*7c478bd9Sstevel@tonic-gate 				temp = 0;
228*7c478bd9Sstevel@tonic-gate 			}
229*7c478bd9Sstevel@tonic-gate 		}
230*7c478bd9Sstevel@tonic-gate 		ltemp = strdup("/tmp/sdifflXXXXXX");
231*7c478bd9Sstevel@tonic-gate 		if ((lfd = mkstemp(ltemp)) == -1 ||
232*7c478bd9Sstevel@tonic-gate 			(left = fdopen(lfd, "w")) == NULL)
233*7c478bd9Sstevel@tonic-gate 				error(gettext(
234*7c478bd9Sstevel@tonic-gate 					"Cannot open/create temp %s"),
235*7c478bd9Sstevel@tonic-gate 					ltemp);
236*7c478bd9Sstevel@tonic-gate 		rtemp = strdup("/tmp/sdiffrXXXXXX");
237*7c478bd9Sstevel@tonic-gate 		if ((rfd = mkstemp(rtemp)) == -1 ||
238*7c478bd9Sstevel@tonic-gate 			(right = fdopen(rfd, "w")) == NULL)
239*7c478bd9Sstevel@tonic-gate 				error(gettext(
240*7c478bd9Sstevel@tonic-gate 					"Cannot open/create temp file %s"),
241*7c478bd9Sstevel@tonic-gate 					rtemp);
242*7c478bd9Sstevel@tonic-gate 		if ((odes = fopen(ofile, "w")) == NULL)
243*7c478bd9Sstevel@tonic-gate 			error(gettext("Cannot open output %s"), ofile);
244*7c478bd9Sstevel@tonic-gate 	}
245*7c478bd9Sstevel@tonic-gate 	/* Call DIFF command */
246*7c478bd9Sstevel@tonic-gate 	(void) strcpy(diffcmd, DIFF);
247*7c478bd9Sstevel@tonic-gate 	(void) strcat(diffcmd, file1);
248*7c478bd9Sstevel@tonic-gate 	(void) strcat(diffcmd, " ");
249*7c478bd9Sstevel@tonic-gate 	(void) strcat(diffcmd, file2);
250*7c478bd9Sstevel@tonic-gate 	diffdes = popen(diffcmd, "r");
251*7c478bd9Sstevel@tonic-gate 
252*7c478bd9Sstevel@tonic-gate 	num1 = num2 = 0;
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 	/*
255*7c478bd9Sstevel@tonic-gate 	 * Read in diff output and decode commands
256*7c478bd9Sstevel@tonic-gate 	 * "change" is used to determine character to put in gutter
257*7c478bd9Sstevel@tonic-gate 	 *  num1 and num2 counts the number of lines in file1 and 2
258*7c478bd9Sstevel@tonic-gate 	 */
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 	n = 0;
261*7c478bd9Sstevel@tonic-gate 	while ((bp = fgetline(diffdes)) != NULL) {
262*7c478bd9Sstevel@tonic-gate 		change = ' ';
263*7c478bd9Sstevel@tonic-gate 		com = cmd(bp);
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 	/*
266*7c478bd9Sstevel@tonic-gate 	 * handles all diff output that is not cmd
267*7c478bd9Sstevel@tonic-gate 	 * lines starting with <, >, ., ---
268*7c478bd9Sstevel@tonic-gate 	 */
269*7c478bd9Sstevel@tonic-gate 		if (com == 0)
270*7c478bd9Sstevel@tonic-gate 			continue;
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	/* Catch up to from1 and from2 */
273*7c478bd9Sstevel@tonic-gate 		rcode = 1;
274*7c478bd9Sstevel@tonic-gate 		n1 = from1 - num1;
275*7c478bd9Sstevel@tonic-gate 		n2 = from2 - num2;
276*7c478bd9Sstevel@tonic-gate 		n = n1 > n2 ? n2 : n1;
277*7c478bd9Sstevel@tonic-gate 		if (com == 'c' && n > 0)
278*7c478bd9Sstevel@tonic-gate 			n--;
279*7c478bd9Sstevel@tonic-gate 		if (silent)
280*7c478bd9Sstevel@tonic-gate 			(void) fputs(bp, stdout);
281*7c478bd9Sstevel@tonic-gate 		while (n-- > 0) {
282*7c478bd9Sstevel@tonic-gate 			(void) put1();
283*7c478bd9Sstevel@tonic-gate 			(void) put2();
284*7c478bd9Sstevel@tonic-gate 			if (!silent)
285*7c478bd9Sstevel@tonic-gate 				(void) putc('\n', stdout);
286*7c478bd9Sstevel@tonic-gate 			midflg = 0;
287*7c478bd9Sstevel@tonic-gate 		}
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	/* Process diff cmd */
290*7c478bd9Sstevel@tonic-gate 		switch (com) {
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 		case 'a':
293*7c478bd9Sstevel@tonic-gate 			change = '>';
294*7c478bd9Sstevel@tonic-gate 			while (num2 < to2) {
295*7c478bd9Sstevel@tonic-gate 				(void) put2();
296*7c478bd9Sstevel@tonic-gate 				(void) putc('\n', stdout);
297*7c478bd9Sstevel@tonic-gate 				midflg = 0;
298*7c478bd9Sstevel@tonic-gate 			}
299*7c478bd9Sstevel@tonic-gate 			break;
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate 		case 'd':
302*7c478bd9Sstevel@tonic-gate 			change = '<';
303*7c478bd9Sstevel@tonic-gate 			while (num1 < to1) {
304*7c478bd9Sstevel@tonic-gate 				(void) put1();
305*7c478bd9Sstevel@tonic-gate 				(void) putc('\n', stdout);
306*7c478bd9Sstevel@tonic-gate 				midflg = 0;
307*7c478bd9Sstevel@tonic-gate 			}
308*7c478bd9Sstevel@tonic-gate 			break;
309*7c478bd9Sstevel@tonic-gate 
310*7c478bd9Sstevel@tonic-gate 		case 'c':
311*7c478bd9Sstevel@tonic-gate 			n1 = to1 - from1;
312*7c478bd9Sstevel@tonic-gate 			n2 = to2 - from2;
313*7c478bd9Sstevel@tonic-gate 			n = n1 > n2 ? n2 : n1;
314*7c478bd9Sstevel@tonic-gate 			change = '|';
315*7c478bd9Sstevel@tonic-gate 			do {
316*7c478bd9Sstevel@tonic-gate 				(void) put1();
317*7c478bd9Sstevel@tonic-gate 				(void) put2();
318*7c478bd9Sstevel@tonic-gate 				(void) putc('\n', stdout);
319*7c478bd9Sstevel@tonic-gate 				midflg = 0;
320*7c478bd9Sstevel@tonic-gate 			} while (n--);
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 			change = '<';
323*7c478bd9Sstevel@tonic-gate 			while (num1 < to1) {
324*7c478bd9Sstevel@tonic-gate 				(void) put1();
325*7c478bd9Sstevel@tonic-gate 				(void) putc('\n', stdout);
326*7c478bd9Sstevel@tonic-gate 				midflg = 0;
327*7c478bd9Sstevel@tonic-gate 			}
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate 			change = '>';
330*7c478bd9Sstevel@tonic-gate 			while (num2 < to2) {
331*7c478bd9Sstevel@tonic-gate 				(void) put2();
332*7c478bd9Sstevel@tonic-gate 				(void) putc('\n', stdout);
333*7c478bd9Sstevel@tonic-gate 				midflg = 0;
334*7c478bd9Sstevel@tonic-gate 			}
335*7c478bd9Sstevel@tonic-gate 			break;
336*7c478bd9Sstevel@tonic-gate 
337*7c478bd9Sstevel@tonic-gate 		default:
338*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
339*7c478bd9Sstevel@tonic-gate 				"%c: cmd not found\n"), cmd);
340*7c478bd9Sstevel@tonic-gate 			break;
341*7c478bd9Sstevel@tonic-gate 		}
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 		if (oflag == 1 && com != 0) {
344*7c478bd9Sstevel@tonic-gate 			cmdin();
345*7c478bd9Sstevel@tonic-gate 			if ((left = fopen(ltemp, "w")) == NULL)
346*7c478bd9Sstevel@tonic-gate 				error(gettext(
347*7c478bd9Sstevel@tonic-gate 					"main: Cannot open temp %s"), ltemp);
348*7c478bd9Sstevel@tonic-gate 			if ((right = fopen(rtemp, "w")) == NULL)
349*7c478bd9Sstevel@tonic-gate 				error(gettext(
350*7c478bd9Sstevel@tonic-gate 					"main: Cannot open temp %s"), rtemp);
351*7c478bd9Sstevel@tonic-gate 		}
352*7c478bd9Sstevel@tonic-gate 	}
353*7c478bd9Sstevel@tonic-gate 	/* put out remainder of input files */
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 	while (put1()) {
356*7c478bd9Sstevel@tonic-gate 		(void) put2();
357*7c478bd9Sstevel@tonic-gate 		if (!silent)
358*7c478bd9Sstevel@tonic-gate 			(void) putc('\n', stdout);
359*7c478bd9Sstevel@tonic-gate 		midflg = 0;
360*7c478bd9Sstevel@tonic-gate 	}
361*7c478bd9Sstevel@tonic-gate 	if (odes)
362*7c478bd9Sstevel@tonic-gate 		(void) fclose(odes);
363*7c478bd9Sstevel@tonic-gate 	sremove();
364*7c478bd9Sstevel@tonic-gate 	exit(rcode);
365*7c478bd9Sstevel@tonic-gate }
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate static int
368*7c478bd9Sstevel@tonic-gate put1(void)
369*7c478bd9Sstevel@tonic-gate {
370*7c478bd9Sstevel@tonic-gate 	/* len1 = length of left side */
371*7c478bd9Sstevel@tonic-gate 	/* nchars = num of chars including tabs */
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 	char	*bp;
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 	if ((bp = fgetline(fdes1)) != NULL) {
377*7c478bd9Sstevel@tonic-gate 		len1 = getlen(0, bp);
378*7c478bd9Sstevel@tonic-gate 		if ((!silent || change != ' ') && len1 != 0)
379*7c478bd9Sstevel@tonic-gate 			putline(stdout, bp, nchars);
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 		if (oflag) {
382*7c478bd9Sstevel@tonic-gate 		/*
383*7c478bd9Sstevel@tonic-gate 		 * put left side either to output file
384*7c478bd9Sstevel@tonic-gate 		 * if identical to right
385*7c478bd9Sstevel@tonic-gate 		 * or left temp file if not
386*7c478bd9Sstevel@tonic-gate 		 */
387*7c478bd9Sstevel@tonic-gate 
388*7c478bd9Sstevel@tonic-gate 			if (change == ' ')
389*7c478bd9Sstevel@tonic-gate 				putline(odes, bp, strlen(bp));
390*7c478bd9Sstevel@tonic-gate 			else
391*7c478bd9Sstevel@tonic-gate 				putline(left, bp, strlen(bp));
392*7c478bd9Sstevel@tonic-gate 		}
393*7c478bd9Sstevel@tonic-gate 		if (change != ' ')
394*7c478bd9Sstevel@tonic-gate 			putmid(1);
395*7c478bd9Sstevel@tonic-gate 		num1++;
396*7c478bd9Sstevel@tonic-gate 		return (1);
397*7c478bd9Sstevel@tonic-gate 	} else
398*7c478bd9Sstevel@tonic-gate 		return (0);
399*7c478bd9Sstevel@tonic-gate }
400*7c478bd9Sstevel@tonic-gate 
401*7c478bd9Sstevel@tonic-gate static int
402*7c478bd9Sstevel@tonic-gate put2(void)
403*7c478bd9Sstevel@tonic-gate {
404*7c478bd9Sstevel@tonic-gate 	char	*bp;
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 	if ((bp = fgetline(fdes2)) != NULL) {
407*7c478bd9Sstevel@tonic-gate 		(void) getlen((hlen + WGUTTER) % 8, bp);
408*7c478bd9Sstevel@tonic-gate 
409*7c478bd9Sstevel@tonic-gate 		/*
410*7c478bd9Sstevel@tonic-gate 		 * if the left and right are different they are always
411*7c478bd9Sstevel@tonic-gate 		 * printed.
412*7c478bd9Sstevel@tonic-gate 		 * If the left and right are identical
413*7c478bd9Sstevel@tonic-gate 		 * right is only printed if leftonly is not specified
414*7c478bd9Sstevel@tonic-gate 		 * or silent mode is not specified
415*7c478bd9Sstevel@tonic-gate 		 * or the right contains other than white space (len1 !=0)
416*7c478bd9Sstevel@tonic-gate 		 */
417*7c478bd9Sstevel@tonic-gate 		if (change != ' ') {
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 		/*
420*7c478bd9Sstevel@tonic-gate 		 * put right side to right temp file only
421*7c478bd9Sstevel@tonic-gate 		 * because left side was written to output for
422*7c478bd9Sstevel@tonic-gate 		 * identical lines
423*7c478bd9Sstevel@tonic-gate 		 */
424*7c478bd9Sstevel@tonic-gate 
425*7c478bd9Sstevel@tonic-gate 			if (oflag)
426*7c478bd9Sstevel@tonic-gate 				putline(right, bp, strlen(bp));
427*7c478bd9Sstevel@tonic-gate 
428*7c478bd9Sstevel@tonic-gate 			if (midflg == 0)
429*7c478bd9Sstevel@tonic-gate 				putmid(1);
430*7c478bd9Sstevel@tonic-gate 			putline(stdout, bp, nchars);
431*7c478bd9Sstevel@tonic-gate 		} else
432*7c478bd9Sstevel@tonic-gate 			if (!silent && !leftonly && len1 != 0) {
433*7c478bd9Sstevel@tonic-gate 				if (midflg == 0)
434*7c478bd9Sstevel@tonic-gate 					putmid(1);
435*7c478bd9Sstevel@tonic-gate 				putline(stdout, bp, nchars);
436*7c478bd9Sstevel@tonic-gate 			}
437*7c478bd9Sstevel@tonic-gate 		num2++;
438*7c478bd9Sstevel@tonic-gate 		len1 = 0;
439*7c478bd9Sstevel@tonic-gate 		return (1);
440*7c478bd9Sstevel@tonic-gate 	} else {
441*7c478bd9Sstevel@tonic-gate 		len1 = 0;
442*7c478bd9Sstevel@tonic-gate 		return (0);
443*7c478bd9Sstevel@tonic-gate 	}
444*7c478bd9Sstevel@tonic-gate }
445*7c478bd9Sstevel@tonic-gate 
446*7c478bd9Sstevel@tonic-gate static void
447*7c478bd9Sstevel@tonic-gate putline(FILE *file, char *start, int num)
448*7c478bd9Sstevel@tonic-gate {
449*7c478bd9Sstevel@tonic-gate 	char	*cp, *end;
450*7c478bd9Sstevel@tonic-gate 	int	i, len, d_col;
451*7c478bd9Sstevel@tonic-gate 	wchar_t	wc;
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 	cp = start;
454*7c478bd9Sstevel@tonic-gate 	end = cp + num;
455*7c478bd9Sstevel@tonic-gate 	while (cp < end) {
456*7c478bd9Sstevel@tonic-gate 		if (isascii(*cp)) {
457*7c478bd9Sstevel@tonic-gate 			(void) putc(*cp++, file);
458*7c478bd9Sstevel@tonic-gate 			continue;
459*7c478bd9Sstevel@tonic-gate 		}
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 		if ((len = end - cp) > MB_LEN_MAX)
462*7c478bd9Sstevel@tonic-gate 			len = MB_LEN_MAX;
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate 		if ((len = mbtowc(&wc, cp, len)) <= 0) {
465*7c478bd9Sstevel@tonic-gate 			(void) putc(*cp++, file);
466*7c478bd9Sstevel@tonic-gate 			continue;
467*7c478bd9Sstevel@tonic-gate 		}
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 		if ((d_col = wcwidth(wc)) <= 0)
470*7c478bd9Sstevel@tonic-gate 			d_col = len;
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate 		if ((cp + d_col) > end)
473*7c478bd9Sstevel@tonic-gate 			return;
474*7c478bd9Sstevel@tonic-gate 
475*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < len; i++)
476*7c478bd9Sstevel@tonic-gate 			(void) putc(*cp++, file);
477*7c478bd9Sstevel@tonic-gate 	}
478*7c478bd9Sstevel@tonic-gate }
479*7c478bd9Sstevel@tonic-gate 
480*7c478bd9Sstevel@tonic-gate static int
481*7c478bd9Sstevel@tonic-gate cmd(char *start)
482*7c478bd9Sstevel@tonic-gate {
483*7c478bd9Sstevel@tonic-gate 	unsigned char	*cp;
484*7c478bd9Sstevel@tonic-gate 	char	*cps;
485*7c478bd9Sstevel@tonic-gate 	int	com;
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 	if (*start == '>' || *start == '<' || *start == '-' || *start == '.')
488*7c478bd9Sstevel@tonic-gate 		return (0);
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 	cp = (unsigned char *)start;
491*7c478bd9Sstevel@tonic-gate 	cps = start;
492*7c478bd9Sstevel@tonic-gate 	while (isdigit(*cp))
493*7c478bd9Sstevel@tonic-gate 		cp++;
494*7c478bd9Sstevel@tonic-gate 	from1 = atoi(cps);
495*7c478bd9Sstevel@tonic-gate 	to1 = from1;
496*7c478bd9Sstevel@tonic-gate 	if (*cp == ',') {
497*7c478bd9Sstevel@tonic-gate 		cp++;
498*7c478bd9Sstevel@tonic-gate 		cps = (char *)cp;
499*7c478bd9Sstevel@tonic-gate 		while (isdigit(*cp))
500*7c478bd9Sstevel@tonic-gate 			cp++;
501*7c478bd9Sstevel@tonic-gate 		to1 = atoi(cps);
502*7c478bd9Sstevel@tonic-gate 	}
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate 	com = *cp++;
505*7c478bd9Sstevel@tonic-gate 	cps = (char *)cp;
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	while (isdigit(*cp))
508*7c478bd9Sstevel@tonic-gate 		cp++;
509*7c478bd9Sstevel@tonic-gate 	from2 = atoi(cps);
510*7c478bd9Sstevel@tonic-gate 	to2 = from2;
511*7c478bd9Sstevel@tonic-gate 	if (*cp == ',') {
512*7c478bd9Sstevel@tonic-gate 		cp++;
513*7c478bd9Sstevel@tonic-gate 		cps = (char *)cp;
514*7c478bd9Sstevel@tonic-gate 		while (isdigit(*cp))
515*7c478bd9Sstevel@tonic-gate 			cp++;
516*7c478bd9Sstevel@tonic-gate 		to2 = atoi(cps);
517*7c478bd9Sstevel@tonic-gate 	}
518*7c478bd9Sstevel@tonic-gate 	return (com);
519*7c478bd9Sstevel@tonic-gate }
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate static int
522*7c478bd9Sstevel@tonic-gate getlen(int startpos, char *buffer)
523*7c478bd9Sstevel@tonic-gate {
524*7c478bd9Sstevel@tonic-gate 	/*
525*7c478bd9Sstevel@tonic-gate 	 * get the length of the string in buffer
526*7c478bd9Sstevel@tonic-gate 	 *  expand tabs to next multiple of 8
527*7c478bd9Sstevel@tonic-gate 	 */
528*7c478bd9Sstevel@tonic-gate 	unsigned char	*cp;
529*7c478bd9Sstevel@tonic-gate 	int	slen, tlen, len, d_col;
530*7c478bd9Sstevel@tonic-gate 	int	notspace;
531*7c478bd9Sstevel@tonic-gate 	wchar_t	wc;
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate 	nchars = 0;
534*7c478bd9Sstevel@tonic-gate 	notspace = 0;
535*7c478bd9Sstevel@tonic-gate 	tlen = startpos;
536*7c478bd9Sstevel@tonic-gate 	for (cp = (unsigned char *)buffer; (*cp != '\n') && (*cp); cp++) {
537*7c478bd9Sstevel@tonic-gate 		if (*cp == '\t') {
538*7c478bd9Sstevel@tonic-gate 			slen = tlen;
539*7c478bd9Sstevel@tonic-gate 			tlen += 8 - (tlen % 8);
540*7c478bd9Sstevel@tonic-gate 			if (tlen >= hlen) {
541*7c478bd9Sstevel@tonic-gate 				tlen = slen;
542*7c478bd9Sstevel@tonic-gate 				break;
543*7c478bd9Sstevel@tonic-gate 			}
544*7c478bd9Sstevel@tonic-gate 			nchars++;
545*7c478bd9Sstevel@tonic-gate 			continue;
546*7c478bd9Sstevel@tonic-gate 		}
547*7c478bd9Sstevel@tonic-gate 
548*7c478bd9Sstevel@tonic-gate 		if (isascii(*cp)) {
549*7c478bd9Sstevel@tonic-gate 			slen = tlen;
550*7c478bd9Sstevel@tonic-gate 			tlen++;
551*7c478bd9Sstevel@tonic-gate 			if (tlen >= hlen) {
552*7c478bd9Sstevel@tonic-gate 				tlen = slen;
553*7c478bd9Sstevel@tonic-gate 				break;
554*7c478bd9Sstevel@tonic-gate 			}
555*7c478bd9Sstevel@tonic-gate 			if (!isspace(*cp))
556*7c478bd9Sstevel@tonic-gate 				notspace = 1;
557*7c478bd9Sstevel@tonic-gate 			nchars++;
558*7c478bd9Sstevel@tonic-gate 			continue;
559*7c478bd9Sstevel@tonic-gate 		}
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate 		if ((len = mbtowc(&wc, (char *)cp, MB_LEN_MAX)) <= 0) {
562*7c478bd9Sstevel@tonic-gate 			slen = tlen;
563*7c478bd9Sstevel@tonic-gate 			tlen++;
564*7c478bd9Sstevel@tonic-gate 			if (tlen >= hlen) {
565*7c478bd9Sstevel@tonic-gate 				tlen = slen;
566*7c478bd9Sstevel@tonic-gate 				break;
567*7c478bd9Sstevel@tonic-gate 			}
568*7c478bd9Sstevel@tonic-gate 			notspace = 1;
569*7c478bd9Sstevel@tonic-gate 			nchars++;
570*7c478bd9Sstevel@tonic-gate 			continue;
571*7c478bd9Sstevel@tonic-gate 		}
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 		if ((d_col = wcwidth(wc)) <= 0)
574*7c478bd9Sstevel@tonic-gate 			d_col = len;
575*7c478bd9Sstevel@tonic-gate 
576*7c478bd9Sstevel@tonic-gate 		slen = tlen;
577*7c478bd9Sstevel@tonic-gate 		tlen += d_col;
578*7c478bd9Sstevel@tonic-gate 		if (tlen > hlen) {
579*7c478bd9Sstevel@tonic-gate 			tlen = slen;
580*7c478bd9Sstevel@tonic-gate 			break;
581*7c478bd9Sstevel@tonic-gate 		}
582*7c478bd9Sstevel@tonic-gate 		notspace = 1;
583*7c478bd9Sstevel@tonic-gate 		cp += len - 1;
584*7c478bd9Sstevel@tonic-gate 		nchars += len;
585*7c478bd9Sstevel@tonic-gate 	}
586*7c478bd9Sstevel@tonic-gate 	return (notspace ? tlen : 0);
587*7c478bd9Sstevel@tonic-gate }
588*7c478bd9Sstevel@tonic-gate 
589*7c478bd9Sstevel@tonic-gate static void
590*7c478bd9Sstevel@tonic-gate putmid(int bflag)
591*7c478bd9Sstevel@tonic-gate {
592*7c478bd9Sstevel@tonic-gate 	int	i;
593*7c478bd9Sstevel@tonic-gate 
594*7c478bd9Sstevel@tonic-gate 	/*
595*7c478bd9Sstevel@tonic-gate 	 * len1 set by getlen to the possibly truncated
596*7c478bd9Sstevel@tonic-gate 	 *  length of left side
597*7c478bd9Sstevel@tonic-gate 	 *  hlen is length of half line
598*7c478bd9Sstevel@tonic-gate 	 */
599*7c478bd9Sstevel@tonic-gate 
600*7c478bd9Sstevel@tonic-gate 	midflg = 1;
601*7c478bd9Sstevel@tonic-gate 	if (bflag) {
602*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < hlen - len1; i++)
603*7c478bd9Sstevel@tonic-gate 			(void) putc(' ', stdout);
604*7c478bd9Sstevel@tonic-gate 	}
605*7c478bd9Sstevel@tonic-gate 	(void) fputs(twoblanks, stdout);
606*7c478bd9Sstevel@tonic-gate 	(void) putc((int)change, stdout);
607*7c478bd9Sstevel@tonic-gate 	(void) fputs(twoblanks, stdout);
608*7c478bd9Sstevel@tonic-gate }
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate static void
611*7c478bd9Sstevel@tonic-gate error(char *s1, char *s2)
612*7c478bd9Sstevel@tonic-gate {
613*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "sdiff: ");
614*7c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, s1, s2);
615*7c478bd9Sstevel@tonic-gate 	(void) putc('\n', stderr);
616*7c478bd9Sstevel@tonic-gate 	sremove();
617*7c478bd9Sstevel@tonic-gate 	exit(2);
618*7c478bd9Sstevel@tonic-gate }
619*7c478bd9Sstevel@tonic-gate 
620*7c478bd9Sstevel@tonic-gate static void
621*7c478bd9Sstevel@tonic-gate onintr(void)
622*7c478bd9Sstevel@tonic-gate {
623*7c478bd9Sstevel@tonic-gate 	sremove();
624*7c478bd9Sstevel@tonic-gate 	exit(rcode);
625*7c478bd9Sstevel@tonic-gate }
626*7c478bd9Sstevel@tonic-gate 
627*7c478bd9Sstevel@tonic-gate static void
628*7c478bd9Sstevel@tonic-gate sremove(void)
629*7c478bd9Sstevel@tonic-gate {
630*7c478bd9Sstevel@tonic-gate 	if (ltemp) {
631*7c478bd9Sstevel@tonic-gate 		(void) unlink(ltemp);
632*7c478bd9Sstevel@tonic-gate 		free(ltemp);
633*7c478bd9Sstevel@tonic-gate 	}
634*7c478bd9Sstevel@tonic-gate 	if (rtemp) {
635*7c478bd9Sstevel@tonic-gate 		(void) unlink(rtemp);
636*7c478bd9Sstevel@tonic-gate 		free(rtemp);
637*7c478bd9Sstevel@tonic-gate 	}
638*7c478bd9Sstevel@tonic-gate 	if (temp) {
639*7c478bd9Sstevel@tonic-gate 		(void) unlink(temp);
640*7c478bd9Sstevel@tonic-gate 		free(temp);
641*7c478bd9Sstevel@tonic-gate 	}
642*7c478bd9Sstevel@tonic-gate }
643*7c478bd9Sstevel@tonic-gate 
644*7c478bd9Sstevel@tonic-gate static void
645*7c478bd9Sstevel@tonic-gate cmdin(void)
646*7c478bd9Sstevel@tonic-gate {
647*7c478bd9Sstevel@tonic-gate 	char	*cp, *ename;
648*7c478bd9Sstevel@tonic-gate 	int	notacc;
649*7c478bd9Sstevel@tonic-gate 
650*7c478bd9Sstevel@tonic-gate 	(void) fclose(left);
651*7c478bd9Sstevel@tonic-gate 	(void) fclose(right);
652*7c478bd9Sstevel@tonic-gate 	notacc = 1;
653*7c478bd9Sstevel@tonic-gate 	while (notacc) {
654*7c478bd9Sstevel@tonic-gate 		(void) putc(PROMPT, stdout);
655*7c478bd9Sstevel@tonic-gate 		if ((cp = fgets(inbuf, 10, stdin)) == NULL) {
656*7c478bd9Sstevel@tonic-gate 			(void) putc('\n', stdout);
657*7c478bd9Sstevel@tonic-gate 			break;
658*7c478bd9Sstevel@tonic-gate 		}
659*7c478bd9Sstevel@tonic-gate 		switch (*cp) {
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 		case 's':
662*7c478bd9Sstevel@tonic-gate 			silent = 1;
663*7c478bd9Sstevel@tonic-gate 			break;
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 		case 'v':
666*7c478bd9Sstevel@tonic-gate 			silent = 0;
667*7c478bd9Sstevel@tonic-gate 			break;
668*7c478bd9Sstevel@tonic-gate 
669*7c478bd9Sstevel@tonic-gate 		case 'q':
670*7c478bd9Sstevel@tonic-gate 			sremove();
671*7c478bd9Sstevel@tonic-gate 			exit(rcode);
672*7c478bd9Sstevel@tonic-gate 			/* NOTREACHED */
673*7c478bd9Sstevel@tonic-gate 			break;
674*7c478bd9Sstevel@tonic-gate 
675*7c478bd9Sstevel@tonic-gate 		case 'l':
676*7c478bd9Sstevel@tonic-gate 			cpp(ltemp, left, odes);
677*7c478bd9Sstevel@tonic-gate 			notacc = 0;
678*7c478bd9Sstevel@tonic-gate 			break;
679*7c478bd9Sstevel@tonic-gate 
680*7c478bd9Sstevel@tonic-gate 		case 'r':
681*7c478bd9Sstevel@tonic-gate 			cpp(rtemp, right, odes);
682*7c478bd9Sstevel@tonic-gate 			notacc = 0;
683*7c478bd9Sstevel@tonic-gate 			break;
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate 		case 'e':
686*7c478bd9Sstevel@tonic-gate 			while (*++cp == ' ')
687*7c478bd9Sstevel@tonic-gate 				;
688*7c478bd9Sstevel@tonic-gate 			switch (*cp) {
689*7c478bd9Sstevel@tonic-gate 			case 'l':
690*7c478bd9Sstevel@tonic-gate 			case '<':
691*7c478bd9Sstevel@tonic-gate 				notacc = 0;
692*7c478bd9Sstevel@tonic-gate 				ename = ltemp;
693*7c478bd9Sstevel@tonic-gate 				edit(ename);
694*7c478bd9Sstevel@tonic-gate 				break;
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 			case 'r':
697*7c478bd9Sstevel@tonic-gate 			case '>':
698*7c478bd9Sstevel@tonic-gate 				notacc = 0;
699*7c478bd9Sstevel@tonic-gate 				ename = rtemp;
700*7c478bd9Sstevel@tonic-gate 				edit(ename);
701*7c478bd9Sstevel@tonic-gate 				break;
702*7c478bd9Sstevel@tonic-gate 
703*7c478bd9Sstevel@tonic-gate 			case 'b':
704*7c478bd9Sstevel@tonic-gate 			case '|':
705*7c478bd9Sstevel@tonic-gate 				if ((tempdes = fopen(temp, "w")) == NULL)
706*7c478bd9Sstevel@tonic-gate 					error(gettext(
707*7c478bd9Sstevel@tonic-gate 						"Cannot open temp file %s"),
708*7c478bd9Sstevel@tonic-gate 						temp);
709*7c478bd9Sstevel@tonic-gate 				cpp(ltemp, left, tempdes);
710*7c478bd9Sstevel@tonic-gate 				cpp(rtemp, right, tempdes);
711*7c478bd9Sstevel@tonic-gate 				(void) fclose(tempdes);
712*7c478bd9Sstevel@tonic-gate 				notacc = 0;
713*7c478bd9Sstevel@tonic-gate 				ename = temp;
714*7c478bd9Sstevel@tonic-gate 				edit(ename);
715*7c478bd9Sstevel@tonic-gate 				break;
716*7c478bd9Sstevel@tonic-gate 
717*7c478bd9Sstevel@tonic-gate 			case '\n':
718*7c478bd9Sstevel@tonic-gate 				if ((tempdes = fopen(temp, "w")) == NULL)
719*7c478bd9Sstevel@tonic-gate 					error(gettext(
720*7c478bd9Sstevel@tonic-gate 						"Cannot open temp file %s"),
721*7c478bd9Sstevel@tonic-gate 						temp);
722*7c478bd9Sstevel@tonic-gate 				(void) fclose(tempdes);
723*7c478bd9Sstevel@tonic-gate 				notacc = 0;
724*7c478bd9Sstevel@tonic-gate 				ename = temp;
725*7c478bd9Sstevel@tonic-gate 				edit(ename);
726*7c478bd9Sstevel@tonic-gate 				break;
727*7c478bd9Sstevel@tonic-gate 			default:
728*7c478bd9Sstevel@tonic-gate 				(void) fprintf(stderr, gettext(
729*7c478bd9Sstevel@tonic-gate 					"Illegal command %s reenter\n"),
730*7c478bd9Sstevel@tonic-gate 					cp);
731*7c478bd9Sstevel@tonic-gate 				break;
732*7c478bd9Sstevel@tonic-gate 			}
733*7c478bd9Sstevel@tonic-gate 			if (notacc == 0)
734*7c478bd9Sstevel@tonic-gate 				cpp(ename, tempdes, odes);
735*7c478bd9Sstevel@tonic-gate 			break;
736*7c478bd9Sstevel@tonic-gate 
737*7c478bd9Sstevel@tonic-gate 		default:
738*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, gettext(
739*7c478bd9Sstevel@tonic-gate 				"Illegal command reenter\n"));
740*7c478bd9Sstevel@tonic-gate 			break;
741*7c478bd9Sstevel@tonic-gate 		}
742*7c478bd9Sstevel@tonic-gate 	}
743*7c478bd9Sstevel@tonic-gate }
744*7c478bd9Sstevel@tonic-gate 
745*7c478bd9Sstevel@tonic-gate static void
746*7c478bd9Sstevel@tonic-gate cpp(char *from, FILE *fromdes, FILE *todes)
747*7c478bd9Sstevel@tonic-gate {
748*7c478bd9Sstevel@tonic-gate 	char	tempbuf[BMAX + 1];
749*7c478bd9Sstevel@tonic-gate 
750*7c478bd9Sstevel@tonic-gate 	if ((fromdes = fopen(from, "r")) == NULL)
751*7c478bd9Sstevel@tonic-gate 		error(gettext(
752*7c478bd9Sstevel@tonic-gate 			"cpp: Cannot open %s"), from);
753*7c478bd9Sstevel@tonic-gate 	while ((fgets(tempbuf, BMAX, fromdes) != NULL))
754*7c478bd9Sstevel@tonic-gate 		(void) fputs(tempbuf, todes);
755*7c478bd9Sstevel@tonic-gate 	(void) fclose(fromdes);
756*7c478bd9Sstevel@tonic-gate }
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate static void
759*7c478bd9Sstevel@tonic-gate edit(char *file)
760*7c478bd9Sstevel@tonic-gate {
761*7c478bd9Sstevel@tonic-gate 	int	i;
762*7c478bd9Sstevel@tonic-gate 	pid_t	pid;
763*7c478bd9Sstevel@tonic-gate 	void (*oldintr)(int);
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate 	switch (pid = fork()) {
766*7c478bd9Sstevel@tonic-gate 	case (pid_t)-1:
767*7c478bd9Sstevel@tonic-gate 		error(gettext("Cannot fork"), NULL);
768*7c478bd9Sstevel@tonic-gate 		/* NOTREACHED */
769*7c478bd9Sstevel@tonic-gate 		break;
770*7c478bd9Sstevel@tonic-gate 	case (pid_t)0:
771*7c478bd9Sstevel@tonic-gate 		(void) execl("/usr/bin/ed", "ed", file, NULL);
772*7c478bd9Sstevel@tonic-gate 	}
773*7c478bd9Sstevel@tonic-gate 
774*7c478bd9Sstevel@tonic-gate 	oldintr = signal(SIGINT, SIG_IGN);	/* ignore interrupts in ed */
775*7c478bd9Sstevel@tonic-gate 	while (pid != wait(&i))
776*7c478bd9Sstevel@tonic-gate 		;
777*7c478bd9Sstevel@tonic-gate 	/* restore previous interrupt proc */
778*7c478bd9Sstevel@tonic-gate 	(void) signal(SIGINT, oldintr);
779*7c478bd9Sstevel@tonic-gate }
780*7c478bd9Sstevel@tonic-gate 
781*7c478bd9Sstevel@tonic-gate static char *
782*7c478bd9Sstevel@tonic-gate filename(char *pa1, char *pa2)
783*7c478bd9Sstevel@tonic-gate {
784*7c478bd9Sstevel@tonic-gate 	int	c;
785*7c478bd9Sstevel@tonic-gate 	char 	*a1, *b1, *a2;
786*7c478bd9Sstevel@tonic-gate 	struct stat	stbuf;
787*7c478bd9Sstevel@tonic-gate 	a1 = pa1;
788*7c478bd9Sstevel@tonic-gate 	a2 = pa2;
789*7c478bd9Sstevel@tonic-gate 	if (stat(a1, &stbuf) != -1 && ((stbuf.st_mode&S_IFMT) == S_IFDIR)) {
790*7c478bd9Sstevel@tonic-gate 		b1 = pa1 = (char *)malloc(strlen(a1) + strlen(a2) + 2);
791*7c478bd9Sstevel@tonic-gate 		while (*b1++ = *a1++);
792*7c478bd9Sstevel@tonic-gate 		b1[-1] = '/';
793*7c478bd9Sstevel@tonic-gate 		a1 = b1;
794*7c478bd9Sstevel@tonic-gate 		while (*a1++ = *a2++)
795*7c478bd9Sstevel@tonic-gate 			if (*a2 && *a2 != '/' && a2[-1] == '/')
796*7c478bd9Sstevel@tonic-gate 				a1 = b1;
797*7c478bd9Sstevel@tonic-gate 	} else if (a1[0] == '-' && a1[1] == 0 && temp == 0) {
798*7c478bd9Sstevel@tonic-gate 		if (fstat(fileno(stdin), &stbuf) == -1)
799*7c478bd9Sstevel@tonic-gate 			error(gettext("Cannot process stdin"), NULL);
800*7c478bd9Sstevel@tonic-gate 		pa1 = temp = strdup("/tmp/sdiffXXXXXX");
801*7c478bd9Sstevel@tonic-gate 		if ((tempfd = mkstemp(temp)) == -1 ||
802*7c478bd9Sstevel@tonic-gate 			(tempdes = fdopen(tempfd, "w")) == NULL)
803*7c478bd9Sstevel@tonic-gate 				error(gettext("Cannot open/create temp %s"),
804*7c478bd9Sstevel@tonic-gate 					temp);
805*7c478bd9Sstevel@tonic-gate 		while ((c = getc(stdin)) != EOF)
806*7c478bd9Sstevel@tonic-gate 			(void) putc(c, tempdes);
807*7c478bd9Sstevel@tonic-gate 		(void) fclose(tempdes);
808*7c478bd9Sstevel@tonic-gate 	}
809*7c478bd9Sstevel@tonic-gate 	return (pa1);
810*7c478bd9Sstevel@tonic-gate }
811*7c478bd9Sstevel@tonic-gate 
812*7c478bd9Sstevel@tonic-gate /*
813*7c478bd9Sstevel@tonic-gate  * like fgets, but reads upto and including a newline,
814*7c478bd9Sstevel@tonic-gate  * the data is stored in a reusable dynamic buffer that grows to fit
815*7c478bd9Sstevel@tonic-gate  * the largest line in the file, the buffer is NULL terminated
816*7c478bd9Sstevel@tonic-gate  * returns a pointer to the dynamic buffer.
817*7c478bd9Sstevel@tonic-gate  */
818*7c478bd9Sstevel@tonic-gate static char *
819*7c478bd9Sstevel@tonic-gate fgetline(FILE *fp)
820*7c478bd9Sstevel@tonic-gate {
821*7c478bd9Sstevel@tonic-gate 	static char	*bp = NULL;
822*7c478bd9Sstevel@tonic-gate 	static int	blen = 0;
823*7c478bd9Sstevel@tonic-gate 	int	sl;
824*7c478bd9Sstevel@tonic-gate 
825*7c478bd9Sstevel@tonic-gate 	if (bp == NULL) {
826*7c478bd9Sstevel@tonic-gate 		/* allocate it for the first time */
827*7c478bd9Sstevel@tonic-gate 		bp = (char *)malloc(BUFSIZ);
828*7c478bd9Sstevel@tonic-gate 		if (bp == NULL)
829*7c478bd9Sstevel@tonic-gate 			error(gettext("fgetline: malloc failed"), NULL);
830*7c478bd9Sstevel@tonic-gate 		blen = BUFSIZ;
831*7c478bd9Sstevel@tonic-gate 	}
832*7c478bd9Sstevel@tonic-gate 
833*7c478bd9Sstevel@tonic-gate 	/* check for error or nothing read */
834*7c478bd9Sstevel@tonic-gate 	if (fgets(bp, blen, fp) == NULL)
835*7c478bd9Sstevel@tonic-gate 		return (NULL);
836*7c478bd9Sstevel@tonic-gate 
837*7c478bd9Sstevel@tonic-gate 	if (feof(fp))
838*7c478bd9Sstevel@tonic-gate 		return (bp);
839*7c478bd9Sstevel@tonic-gate 
840*7c478bd9Sstevel@tonic-gate 	while ((sl = strlen(bp)) == blen-1 && *(bp+blen-2) != '\n') {
841*7c478bd9Sstevel@tonic-gate 		/* still more data, grow the buffer */
842*7c478bd9Sstevel@tonic-gate 		blen *= 2;
843*7c478bd9Sstevel@tonic-gate 		bp = (char *)realloc(bp, blen);
844*7c478bd9Sstevel@tonic-gate 		if (bp == NULL)
845*7c478bd9Sstevel@tonic-gate 			error(gettext("fgetline: realloc failed"), NULL);
846*7c478bd9Sstevel@tonic-gate 		/* continue reading and add to end of buffer */
847*7c478bd9Sstevel@tonic-gate 		(void) fgets(bp+sl, blen-sl, fp);
848*7c478bd9Sstevel@tonic-gate 	}
849*7c478bd9Sstevel@tonic-gate 	return (bp);
850*7c478bd9Sstevel@tonic-gate }
851