xref: /openbsd-src/usr.bin/diff/diff.c (revision 9de32c1b16a474659d7d2e1ce129916fb601409c)
1 /*	$OpenBSD: diff.c,v 1.9 2003/06/25 22:14:43 millert Exp $	*/
2 
3 /*
4  * Copyright (C) Caldera International Inc.  2001-2002.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code and documentation must retain the above
11  *    copyright notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed or owned by Caldera
18  *	International, Inc.
19  * 4. Neither the name of Caldera International, Inc. nor the names of other
20  *    contributors may be used to endorse or promote products derived from
21  *    this software without specific prior written permission.
22  *
23  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
24  * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
26  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27  * IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE FOR ANY DIRECT,
28  * INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #include <stdlib.h>
38 #include <unistd.h>
39 
40 #include "diff.h"
41 #include "pathnames.h"
42 
43 #if 0
44 static char const sccsid[] = "@(#)diff.c 4.7 5/11/89";
45 #endif
46 
47 /*
48  * diff - driver and subroutines
49  */
50 
51 char diff[] = _PATH_DIFF;
52 char diffh[] = _PATH_DIFFH;
53 char pr[] = _PATH_PR;
54 
55 static void noroom(void);
56 __dead void usage(void);
57 
58 int
59 main(int argc, char **argv)
60 {
61 	int ch;
62 
63 	ifdef1 = "FILE1";
64 	ifdef2 = "FILE2";
65 	status = 2;
66 	diffargv = argv;
67 
68 	while ((ch = getopt(argc, argv, "bC:cD:efhilnrS:stU:uw")) != -1) {
69 		switch (ch) {
70 		case 'b':
71 			bflag++;
72 			break;
73 		case 'C':
74 			opt = D_CONTEXT;
75 			if (!isdigit(*optarg))
76 				usage();
77 			context = atoi(optarg);	/* XXX - use strtol */
78 			break;
79 		case 'c':
80 			opt = D_CONTEXT;
81 			context = 3;
82 			break;
83 		case 'D':
84 			/* -Dfoo = -E -1 -2foo */
85 			opt = D_IFDEF;
86 			ifdef1 = "";
87 			ifdef2 = optarg;
88 			wantelses++;
89 			break;
90 		case 'e':
91 			opt = D_EDIT;
92 			break;
93 		case 'f':
94 			opt = D_REVERSE;
95 			break;
96 		case 'h':
97 			hflag++;
98 			break;
99 		case 'i':
100 			iflag++;
101 			break;
102 		case 'l':
103 			lflag++;
104 			break;
105 		case 'n':
106 			opt = D_NREVERSE;
107 			break;
108 		case 'r':
109 			opt = D_REVERSE;
110 			break;
111 		case 'S':
112 			start = optarg;
113 			break;
114 		case 's':
115 			sflag++;
116 			break;
117 		case 't':
118 			tflag++;
119 			break;
120 		case 'U':
121 			opt = D_UNIFIED;
122 			if (!isdigit(*optarg))
123 				usage();
124 			context = atoi(optarg);	/* XXX - use strtol */
125 			break;
126 		case 'u':
127 			opt = D_UNIFIED;
128 			context = 3;
129 			break;
130 		case 'w':
131 			wflag++;
132 			break;
133 		default:
134 			usage();
135 			break;
136 		}
137 	}
138 	argc -= optind;
139 	argv += optind;
140 
141 	if (argc != 2)
142 		errx(1, "two filename arguments required");
143 	file1 = argv[0];
144 	file2 = argv[1];
145 	if (hflag && opt)
146 		errx(1, "-h doesn't support -D, -c, -C, -e, -f, -I, -n, -u or -U");
147 	if (!strcmp(file1, "-"))
148 		stb1.st_mode = S_IFREG;
149 	else if (stat(file1, &stb1) < 0)
150 		err(1, "%s", file1);
151 	if (!strcmp(file2, "-"))
152 		stb2.st_mode = S_IFREG;
153 	else if (stat(file2, &stb2) < 0)
154 		err(1, "%s", file2);
155 	if (S_ISDIR(stb1.st_mode) && S_ISDIR(stb2.st_mode))
156 		diffdir(argv);
157 	else
158 		diffreg();
159 	done(0);
160 }
161 
162 int
163 min(int a, int b)
164 {
165 
166 	return (a < b ? a : b);
167 }
168 
169 int
170 max(int a, int b)
171 {
172 
173 	return (a > b ? a : b);
174 }
175 
176 __dead void
177 done(int sig)
178 {
179 	if (tempfile)
180 		unlink(tempfile);
181 	if (sig)
182 		_exit(status);
183 	exit(status);
184 }
185 
186 void *
187 emalloc(size_t n)
188 {
189 	void *p;
190 
191 	if ((p = malloc(n)) == NULL)
192 		noroom();
193 	return (p);
194 }
195 
196 void *
197 erealloc(void *p, size_t n)
198 {
199 	void *q;
200 
201 	if ((q = realloc(p, n)) == NULL)
202 		noroom();
203 	return (q);
204 }
205 
206 static void
207 noroom(void)
208 {
209 	warn("files too big, try -h");
210 	done(0);
211 }
212 
213 __dead void
214 usage(void)
215 {
216 	(void)fprintf(stderr, "usage: diff [-bitw] [-c | -e | -f | -h | -n | -u ] file1 file2\n"
217 	    "       diff [-biw] -Dstring file1 file2\n"
218 	    "       diff [-biwt] [-c | -e | -f | -h | -n | -u ] [-l] [-r] [-s] [-Sname]\n            dir1 dir2\n"
219 	    "       diff [-bitw] -Cnumber [file1 file2 | dir1 dir2]\n"
220 	    "       diff [-bitw] -Unumber [file1 file2 | dir1 dir2]\n");
221 
222 	exit(1);
223 }
224