diff.c (10273B)
1 /* 2 * This code contains changes by 3 * Gunnar Ritter, Freiburg i. Br., Germany, March 2003. All rights reserved. 4 * 5 * Conditions 1, 2, and 4 and the no-warranty notice below apply 6 * to these changes. 7 * 8 * 9 * Copyright (c) 1991 10 * The Regents of the University of California. All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * 41 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved. 42 * 43 * Redistribution and use in source and binary forms, with or without 44 * modification, are permitted provided that the following conditions 45 * are met: 46 * Redistributions of source code and documentation must retain the 47 * above copyright notice, this list of conditions and the following 48 * disclaimer. 49 * Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed or owned by Caldera 55 * International, Inc. 56 * Neither the name of Caldera International, Inc. nor the names of 57 * other contributors may be used to endorse or promote products 58 * derived from this software without specific prior written permission. 59 * 60 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA 61 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR 62 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 63 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64 * ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE 65 * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR 66 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 67 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 68 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 69 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 70 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 71 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 72 */ 73 74 /* Sccsid @(#)diff.c 1.24 (gritter) 3/27/05> */ 75 /* from 4.3BSD diff.c 4.6 4/3/86 */ 76 77 #include "diff.h" 78 #include <unistd.h> 79 #include <locale.h> 80 #include <iblok.h> 81 /* 82 * diff - driver and subroutines 83 */ 84 85 const char diff[] = "diff"; 86 const char diffh[] = DIFFH; 87 const char pr[] = "pr"; 88 const char *progname; 89 const char *argv0; 90 91 static void usage(void); 92 static void xadd(const char *); 93 static void Xadd(const char *); 94 95 int 96 main(int argc, char **argv) 97 { 98 int i, invalid = 0; 99 100 progname = basename(argv[0]); 101 setlocale(LC_CTYPE, ""); 102 mb_cur_max = MB_CUR_MAX; 103 if (getenv("SYSV3") != NULL) 104 sysv3 = 1; 105 ifdef1 = "FILE1"; ifdef2 = "FILE2"; 106 status = 2; 107 argv0 = argv[0]; 108 diffargv = argv; 109 while ((i = getopt(argc, argv, ":D:efnbBwitcC:uU:hS:rslNx:a12pX:")) 110 != EOF) { 111 switch (i) { 112 #ifdef notdef 113 case 'I': 114 opt = D_IFDEF; 115 wantelses = 0; 116 break; 117 case 'E': 118 opt = D_IFDEF; 119 wantelses = 1; 120 break; 121 case '1': 122 opt = D_IFDEF; 123 ifdef1 = optarg; 124 break; 125 #endif 126 case 'D': 127 /* -Dfoo = -E -1 -2foo */ 128 wantelses = 1; 129 ifdef1 = ""; 130 /* fall through */ 131 #ifdef notdef 132 case '2': 133 #endif 134 opt = D_IFDEF; 135 ifdef2 = optarg; 136 break; 137 case 'e': 138 opt = D_EDIT; 139 break; 140 case 'f': 141 opt = D_REVERSE; 142 break; 143 case 'n': 144 opt = D_NREVERSE; 145 break; 146 case 'b': 147 bflag = 1; 148 break; 149 case 'B': 150 Bflag = 1; 151 break; 152 case 'w': 153 wflag = 1; 154 break; 155 case 'i': 156 iflag = 1; 157 break; 158 case 't': 159 tflag = 1; 160 break; 161 case 'c': 162 opt = D_CONTEXT; 163 context = 3; 164 break; 165 case 'C': { 166 char *x; 167 168 opt = D_CONTEXT; 169 context = strtol(optarg, &x, 10); 170 if (*x != '\0' || *optarg == '+' || *optarg == '-') { 171 fprintf(stderr, "%s: use -C num\n", progname); 172 done(); 173 } 174 break; 175 } 176 case 'u': 177 opt = D_UNIFIED; 178 context = 3; 179 break; 180 case 'U': { 181 char *x; 182 183 opt = D_UNIFIED; 184 context = strtol(optarg, &x, 10); 185 if (*x != '\0' || *optarg == '+' || *optarg == '-') { 186 fprintf(stderr, "%s: use -U num\n", progname); 187 done(); 188 } 189 break; 190 } 191 case 'h': 192 hflag++; 193 break; 194 case 'S': 195 start = optarg; 196 break; 197 case 'r': 198 rflag++; 199 break; 200 case 's': 201 sflag++; 202 break; 203 case 'l': 204 lflag++; 205 break; 206 case 'N': 207 Nflag |= 3; 208 break; 209 case '1': 210 Nflag |= 1; 211 break; 212 case '2': 213 Nflag |= 2; 214 break; 215 case 'x': 216 xadd(optarg); 217 break; 218 case 'a': 219 aflag++; 220 break; 221 case 'p': 222 pflag++; 223 break; 224 case 'X': 225 Xadd(optarg); 226 break; 227 default: 228 if (invalid == 0 && !sysv3) 229 invalid = optopt; 230 } 231 } 232 argv += optind, argc -= optind; 233 if (argc != 2) { 234 fprintf(stderr, sysv3 ? "%s: arg count\n" : 235 "%s: two filename arguments required\n", 236 progname); 237 done(); 238 } 239 file1 = argv[0]; 240 file2 = argv[1]; 241 if (invalid) { 242 fprintf(stderr, "%s: invalid option -%c\n", progname, invalid); 243 usage(); 244 } 245 if (pflag) { 246 if (opt == D_UNIFIED || opt == D_CONTEXT) 247 /*EMPTY*/; 248 else if (opt == 0) { 249 opt = D_CONTEXT; 250 context = 3; 251 } else { 252 fprintf(stderr, 253 "%s: -p doesn't support -e, -f, -n, or -I\n", 254 progname); 255 done(); 256 } 257 } 258 if (hflag && opt) { 259 fprintf(stderr, 260 "%s: -h doesn't support -e, -f, -n, -c, -u, or -I\n", 261 progname); 262 done(); 263 } 264 diffany(argv); 265 /*NOTREACHED*/ 266 return 0; 267 } 268 269 void 270 diffany(char **argv) 271 { 272 if (!strcmp(file1, "-")) 273 stb1.st_mode = S_IFREG; 274 else if (stat(file1, &stb1) < 0) { 275 if (sysv3) 276 stb1.st_mode = S_IFREG; 277 else { 278 fprintf(stderr, "%s: %s: %s\n", progname, file1, 279 strerror(errno)); 280 done(); 281 } 282 } 283 if (!strcmp(file2, "-")) 284 stb2.st_mode = S_IFREG; 285 else if (stat(file2, &stb2) < 0) { 286 if (sysv3) 287 stb2.st_mode = S_IFREG; 288 else { 289 fprintf(stderr, "%s: %s: %s\n", progname, file2, 290 strerror(errno)); 291 done(); 292 } 293 } 294 if ((stb1.st_mode & S_IFMT) == S_IFDIR && 295 (stb2.st_mode & S_IFMT) == S_IFDIR) { 296 diffdir(argv); 297 } else 298 diffreg(); 299 done(); 300 } 301 302 static void 303 usage(void) 304 { 305 fprintf(stderr, "\ 306 usage: %s [ -bcefhilnrstw -C num -D string -S name ] file1 file2\n", 307 progname); 308 done(); 309 } 310 311 int 312 min(int a,int b) 313 { 314 315 return (a < b ? a : b); 316 } 317 318 int 319 max(int a,int b) 320 { 321 322 return (a > b ? a : b); 323 } 324 325 void 326 done(void) 327 { 328 if (tempfile1) { 329 unlink(tempfile1); 330 tempfile1 = NULL; 331 } 332 if (tempfile2) { 333 unlink(tempfile2); 334 tempfile2 = NULL; 335 } 336 if (recdepth == 0) 337 exit(status); 338 else 339 longjmp(recenv, 1); 340 } 341 342 static void noroom(void); 343 344 void * 345 dalloc(size_t n) 346 { 347 struct stackblk *sp; 348 349 if ((sp = malloc(n + sizeof *sp)) != NULL) { 350 sp->s_prev = NULL; 351 sp->s_next = curstack; 352 if (curstack) 353 curstack->s_prev = sp; 354 curstack = sp; 355 return (char *)sp + sizeof *sp; 356 } else 357 return NULL; 358 } 359 360 void * 361 talloc(size_t n) 362 { 363 register void *p; 364 365 if ((p = dalloc(n)) == NULL) 366 noroom(); 367 return p; 368 } 369 370 void * 371 ralloc(void *p,size_t n) 372 { 373 struct stackblk *sp, *sq; 374 375 if (p == NULL) 376 return talloc(n); 377 sp = (struct stackblk *)((char *)p - sizeof *sp); 378 if ((sq = realloc(sp, n + sizeof *sp)) == NULL) 379 noroom(); 380 if (sq->s_prev) 381 sq->s_prev->s_next = sq; 382 if (sq->s_next) 383 sq->s_next->s_prev = sq; 384 if (curstack == sp) 385 curstack = sq; 386 return (char *)sq + sizeof *sq; 387 } 388 389 void 390 tfree(void *p) 391 { 392 struct stackblk *sp; 393 394 if (p == NULL) 395 return; 396 sp = (struct stackblk *)((char *)p - sizeof *sp); 397 if (sp->s_prev) 398 sp->s_prev->s_next = sp->s_next; 399 if (sp->s_next) 400 sp->s_next->s_prev = sp->s_prev; 401 if (sp == curstack) 402 curstack = sp->s_next; 403 free(sp); 404 } 405 406 void 407 purgestack(void) 408 { 409 struct stackblk *sp = curstack, *sq = NULL; 410 411 do { 412 free(sq); 413 sq = sp; 414 if (sp) 415 sp = sp->s_next; 416 } while (sq); 417 } 418 419 static void 420 noroom(void) 421 { 422 oomsg(": files too big, try -h\n"); 423 status = 2; 424 done(); 425 } 426 427 static void 428 xadd(const char *cp) 429 { 430 struct xclusion *xp; 431 432 xp = talloc(sizeof *xp); 433 xp->x_pat = cp; 434 xp->x_nxt = xflag; 435 xflag = xp; 436 } 437 438 static void 439 Xadd(const char *name) 440 { 441 struct iblok *ip; 442 char *line = NULL; 443 size_t size = 0, len; 444 445 if (name[0] == '-' && name[1] == '\0') 446 ip = ib_alloc(0, 0); 447 else 448 ip = ib_open(name, 0); 449 if (ip == NULL) { 450 fprintf(stderr, "%s: -X %s: %s\n", progname, name, 451 strerror(errno)); 452 done(); 453 } 454 while ((len = ib_getlin(ip, &line, &size, realloc)) != 0) { 455 if (line[len-1] == '\n') 456 line[--len] = '\0'; 457 xadd(line); 458 line = NULL; 459 size = 0; 460 } 461 free(line); 462 if (ip->ib_fd) 463 ib_close(ip); 464 else 465 ib_free(ip); 466 } 467 468 void 469 oomsg(const char *s) 470 { 471 write(2, progname, strlen(progname)); 472 write(2, s, strlen(s)); 473 }