1107484Speter/* $NetBSD: xlint.c,v 1.36 2005/02/09 21:24:48 dsl Exp $ */ 2107484Speter 381404Speter/* 4107484Speter * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. 581404Speter * Copyright (c) 1994, 1995 Jochen Pohl 681404Speter * All Rights Reserved. 781404Speter * 881404Speter * Redistribution and use in source and binary forms, with or without 981404Speter * modification, are permitted provided that the following conditions 1081404Speter * are met: 1181404Speter * 1. Redistributions of source code must retain the above copyright 1281404Speter * notice, this list of conditions and the following disclaimer. 1381404Speter * 2. Redistributions in binary form must reproduce the above copyright 1481404Speter * notice, this list of conditions and the following disclaimer in the 1581404Speter * documentation and/or other materials provided with the distribution. 1681404Speter * 3. All advertising materials mentioning features or use of this software 1717721Speter * must display the following acknowledgement: 1817721Speter * This product includes software developed by Jochen Pohl for 1917721Speter * The NetBSD Project. 2017721Speter * 4. The name of the author may not be used to endorse or promote products 2117721Speter * derived from this software without specific prior written permission. 2217721Speter * 2317721Speter * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2417721Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2517721Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2617721Speter * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2717721Speter * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2817721Speter * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2917721Speter * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3081404Speter * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3181404Speter * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3281404Speter * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3317721Speter */ 3481404Speter 3517721Speter#include <sys/cdefs.h> 3617721Speter#if defined(__RCSID) && !defined(lint) 3717721Speter__RCSID("$NetBSD: xlint.c,v 1.36 2005/02/09 21:24:48 dsl Exp $"); 3866525Speter#endif 3981404Speter__FBSDID("$FreeBSD$"); 4081404Speter 4181404Speter#include <sys/param.h> 4281404Speter#include <sys/wait.h> 4381404Speter#include <sys/stat.h> 4481404Speter#include <sys/utsname.h> 4566525Speter#include <err.h> 4681404Speter#include <errno.h> 4766525Speter#include <fcntl.h> 4881404Speter#include <paths.h> 4981404Speter#include <signal.h> 5081404Speter#include <stdio.h> 5181404Speter#include <stdlib.h> 5281404Speter#include <string.h> 5381404Speter#include <unistd.h> 5481404Speter 5581404Speter#include "lint.h" 5681404Speter#include "pathnames.h" 5781404Speter 5881404Speter#define DEFAULT_PATH _PATH_DEFPATH 5981404Speter 60107484Speterint main(int, char *[]); 6117721Speter 6281404Speter/* directory for temporary files */ 6317721Speterstatic const char *tmpdir; 64107484Speter 65107484Speter/* path name for cpp output */ 66107484Speterstatic char *cppout; 6781404Speter 6881404Speter/* file descriptor for cpp output */ 6981404Speterstatic int cppoutfd = -1; 7081404Speter 7181404Speter/* files created by 1st pass */ 7281404Speterstatic char **p1out; 7381404Speter 7481404Speter/* input files for 2nd pass (without libraries) */ 7581404Speterstatic char **p2in; 76107484Speter 77107484Speter/* library which will be created by 2nd pass */ 78107484Speterstatic char *p2out; 79107484Speter 8081404Speter/* flags always passed to cc(1) */ 8181404Speterstatic char **cflags; 8281404Speter 8381404Speter/* flags for cc(1), controlled by sflag/tflag */ 8481404Speterstatic char **lcflags; 85107484Speter 8681404Speter/* flags for lint1 */ 8781404Speterstatic char **l1flags; 8881404Speter 8981404Speter/* flags for lint2 */ 9081404Speterstatic char **l2flags; 9181404Speter 9281404Speter/* libraries for lint2 */ 9381404Speterstatic char **l2libs; 9481404Speter 95107484Speter/* default libraries */ 9681404Speterstatic char **deflibs; 9781404Speter 9881404Speter/* additional libraries */ 99102840Speterstatic char **libs; 100102840Speter 10181404Speter/* search path for libraries */ 10281404Speterstatic char **libsrchpath; 10317721Speter 10481404Speterstatic char *libexec_path; 10517721Speter 10681404Speter/* flags */ 107107484Speterstatic int iflag, oflag, Cflag, sflag, tflag, Fflag, dflag, Bflag, Sflag; 10881404Speter 10981404Speter/* print the commands executed to run the stages of compilation */ 11081404Speterstatic int Vflag; 11181404Speter 11281404Speter/* filename for oflag */ 11381404Speterstatic char *outputfn; 11481404Speter 11581404Speter/* reset after first .c source has been processed */ 11681404Speterstatic int first = 1; 11781404Speter 118102840Speter/* 11981404Speter * name of a file which is currently written by a child and should 12081404Speter * be removed after abnormal termination of the child 12181404Speter */ 12281404Speterstatic const char *currfn; 12317721Speter 12417721Speter#if !defined(TARGET_PREFIX) 12581404Speter#define TARGET_PREFIX "" 12681404Speter#endif 12781404Speterstatic const char target_prefix[] = TARGET_PREFIX; 12817721Speter 12917721Speterstatic void appstrg(char ***, char *); 13081404Speterstatic void appcstrg(char ***, const char *); 13181404Speterstatic void applst(char ***, char *const *); 13217721Speterstatic void freelst(char ***); 13317721Speterstatic char *concat2(const char *, const char *); 13481404Speterstatic char *concat3(const char *, const char *, const char *); 13581404Speterstatic void terminate(int) __attribute__((__noreturn__)); 13681404Speterstatic const char *lbasename(const char *, int); 13781404Speterstatic void appdef(char ***, const char *); 13881404Speterstatic void usage(void) __dead2; 13981404Speterstatic void fname(const char *); 14081404Speterstatic void runchild(const char *, char *const *, const char *, int); 14181404Speterstatic void findlibs(char *const *); 14281404Speterstatic int rdok(const char *); 14381404Speterstatic void lint2(void); 14481404Speterstatic void cat(char *const *, const char *); 14581404Speter 14681404Speter/* 14781404Speter * Some functions to deal with lists of strings. 14881404Speter * Take care that we get no surprises in case of asynchronous signals. 14981404Speter */ 15081404Speterstatic void 15181404Speterappstrg(char ***lstp, char *s) 15281404Speter{ 15381404Speter char **lst, **olst; 15481404Speter int i; 15581404Speter 15681404Speter olst = *lstp; 15781404Speter for (i = 0; olst[i] != NULL; i++) 15881404Speter continue; 159107484Speter lst = xrealloc(olst, (i + 2) * sizeof (char *)); 160107484Speter lst[i] = s; 161107484Speter lst[i + 1] = NULL; 16281404Speter *lstp = lst; 16381404Speter} 16481404Speter 16581404Speterstatic void 16681404Speterappcstrg(char ***lstp, const char *s) 167107484Speter{ 168107484Speter 169107484Speter appstrg(lstp, xstrdup(s)); 17081404Speter} 17181404Speter 17281404Speterstatic void 17381404Speterapplst(char ***destp, char *const *src) 17481404Speter{ 17581404Speter int i, k; 17681404Speter char **dest, **odest; 17781404Speter 178107484Speter odest = *destp; 179107484Speter for (i = 0; odest[i] != NULL; i++) 180107484Speter continue; 18181404Speter for (k = 0; src[k] != NULL; k++) 182107484Speter continue; 18381404Speter dest = xrealloc(odest, (i + k + 1) * sizeof (char *)); 184107484Speter for (k = 0; src[k] != NULL; k++) 18581404Speter dest[i + k] = xstrdup(src[k]); 186107484Speter dest[i + k] = NULL; 18781404Speter *destp = dest; 188107484Speter} 18981404Speter 190107484Speterstatic void 19181404Speterfreelst(char ***lstp) 192107484Speter{ 19381404Speter char *s; 194107484Speter int i; 195102840Speter 196107484Speter for (i = 0; (*lstp)[i] != NULL; i++) 19781404Speter continue; 198107484Speter while (i-- > 0) { 19981404Speter s = (*lstp)[i]; 200107484Speter (*lstp)[i] = NULL; 201107484Speter free(s); 20281404Speter } 20381404Speter} 20481404Speter 20581404Speterstatic char * 206107484Speterconcat2(const char *s1, const char *s2) 207107484Speter{ 208107484Speter char *s; 209107484Speter 210107484Speter s = xmalloc(strlen(s1) + strlen(s2) + 1); 21181404Speter (void)strcpy(s, s1); 21217721Speter (void)strcat(s, s2); 21381404Speter 21481404Speter return (s); 21581404Speter} 21681404Speter 217107484Speterstatic char * 21881404Speterconcat3(const char *s1, const char *s2, const char *s3) 21981404Speter{ 22017721Speter char *s; 221102840Speter 222107484Speter s = xmalloc(strlen(s1) + strlen(s2) + strlen(s3) + 1); 22381404Speter (void)strcpy(s, s1); 22481404Speter (void)strcat(s, s2); 22581404Speter (void)strcat(s, s3); 22681404Speter 22781404Speter return (s); 22881404Speter} 229107484Speter 230107484Speter/* 23117721Speter * Clean up after a signal. 23217721Speter */ 23381404Speterstatic void 23481404Speterterminate(int signo) 23581404Speter{ 23681404Speter int i; 23781404Speter 23881404Speter if (cppoutfd != -1) 23981404Speter (void)close(cppoutfd); 24081404Speter if (cppout != NULL) 24181404Speter (void)remove(cppout); 24281404Speter 24381404Speter if (p1out != NULL) { 24481404Speter for (i = 0; p1out[i] != NULL; i++) 24581404Speter (void)remove(p1out[i]); 24681404Speter } 24781404Speter 24881404Speter if (p2out != NULL) 249107484Speter (void)remove(p2out); 250107484Speter 251102840Speter if (currfn != NULL) 252102840Speter (void)remove(currfn); 253107484Speter 254107484Speter exit(signo != 0 ? 1 : 0); 255107484Speter} 256107484Speter 257102840Speter/* 25881404Speter * Returns a pointer to the last component of strg after delim. 259107484Speter * Returns strg if the string does not contain delim. 260107484Speter */ 261107484Speterstatic const char * 262107484Speterlbasename(const char *strg, int delim) 26381404Speter{ 26481404Speter const char *cp, *cp1, *cp2; 26581404Speter 26681404Speter cp = cp1 = cp2 = strg; 26781404Speter while (*cp != '\0') { 26881404Speter if (*cp++ == delim) { 26981404Speter cp2 = cp1; 27081404Speter cp1 = cp; 27181404Speter } 27281404Speter } 27325839Speter return (*cp1 == '\0' ? cp2 : cp1); 27481404Speter} 27517721Speter 27681404Speterstatic void 27781404Speterappdef(char ***lstp, const char *def) 27881404Speter{ 27981404Speter 28017721Speter appstrg(lstp, concat2("-D__", def)); 28181404Speter appstrg(lstp, concat3("-D__", def, "__")); 28281404Speter} 28317721Speter 28481404Speterstatic void 28581404Speterusage(void) 28681404Speter{ 287107484Speter 288102840Speter (void)fprintf(stderr, 289102840Speter "usage: lint [-abceghprvwxzHFS] [-s|-t] [-i|-nu] [-Dname[=def]]" 29081404Speter " [-Uname] [-X <id>[,<id>]...\n"); 29117721Speter (void)fprintf(stderr, 29281404Speter "\t[-Idirectory] [-Ldirectory] [-llibrary] [-ooutputfile]" 29381404Speter " file...\n"); 29417721Speter (void)fprintf(stderr, 29581404Speter " lint [-abceghprvwzHFS] [-s|-t] -Clibrary [-Dname[=def]]\n" 296107484Speter " [-X <id>[,<id>]...\n"); 29781404Speter (void)fprintf(stderr, "\t[-Idirectory] [-Uname] [-Bpath] file" 29881404Speter " ...\n"); 29981404Speter terminate(-1); 30081404Speter} 30181404Speter 30281404Speter 30381404Speterint 30481404Spetermain(int argc, char *argv[]) 30581404Speter{ 30681404Speter int c; 30781404Speter char flgbuf[3], *s; 30881404Speter const char *tmp; 309102840Speter size_t len; 31081404Speter 31181404Speter if ((tmp = getenv("TMPDIR")) == NULL || (len = strlen(tmp)) == 0) { 31281404Speter tmpdir = _PATH_TMP; 313102840Speter } else { 31481404Speter s = xmalloc(len + 2); 31581404Speter (void)sprintf(s, "%s%s", tmp, tmp[len - 1] == '/' ? "" : "/"); 31681404Speter tmpdir = s; 31781404Speter } 31881404Speter 31981404Speter cppout = xmalloc(strlen(tmpdir) + sizeof ("lint0.XXXXXX")); 32081404Speter (void)sprintf(cppout, "%slint0.XXXXXX", tmpdir); 32181404Speter cppoutfd = mkstemp(cppout); 322102840Speter if (cppoutfd == -1) { 32381404Speter warn("can't make temp"); 32481404Speter terminate(-1); 32581404Speter } 32681404Speter 32781404Speter p1out = xcalloc(1, sizeof (char *)); 32881404Speter p2in = xcalloc(1, sizeof (char *)); 32981404Speter cflags = xcalloc(1, sizeof (char *)); 33081404Speter lcflags = xcalloc(1, sizeof (char *)); 33181404Speter l1flags = xcalloc(1, sizeof (char *)); 33281404Speter l2flags = xcalloc(1, sizeof (char *)); 33381404Speter l2libs = xcalloc(1, sizeof (char *)); 33481404Speter deflibs = xcalloc(1, sizeof (char *)); 33581404Speter libs = xcalloc(1, sizeof (char *)); 33681404Speter libsrchpath = xcalloc(1, sizeof (char *)); 337102840Speter 33881404Speter appcstrg(&cflags, "-E"); 33981404Speter appcstrg(&cflags, "-x"); 34081404Speter appcstrg(&cflags, "c"); 34181404Speter#if 0 34281404Speter appcstrg(&cflags, "-D__attribute__(x)="); 343102840Speter appcstrg(&cflags, "-D__extension__(x)=/*NOSTRICT*/0"); 344102840Speter#else 345102840Speter appcstrg(&cflags, "-U__GNUC__"); 346102840Speter appcstrg(&cflags, "-undef"); 347102840Speter#endif 348102840Speter#if 0 34981404Speter appcstrg(&cflags, "-Wp,-$"); 35081404Speter#endif 35181404Speter appcstrg(&cflags, "-Wp,-C"); 35281404Speter appcstrg(&cflags, "-Wcomment"); 353102840Speter appcstrg(&cflags, "-D__LINT__"); 354102840Speter appcstrg(&cflags, "-Dlint"); /* XXX don't def. with -s */ 35581404Speter 35681404Speter appdef(&cflags, "lint"); 35781404Speter 35881404Speter appcstrg(&deflibs, "c"); 35981404Speter 36081404Speter if (signal(SIGHUP, terminate) == SIG_IGN) 36181404Speter (void)signal(SIGHUP, SIG_IGN); 36281404Speter (void)signal(SIGINT, terminate); 36381404Speter (void)signal(SIGQUIT, terminate); 36481404Speter (void)signal(SIGTERM, terminate); 36581404Speter while ((c = getopt(argc, argv, "abcd:eghil:no:prstuvwxzB:C:D:FHI:L:M:SU:VX:")) != -1) { 36681404Speter switch (c) { 36781404Speter 36881404Speter case 'a': 36917721Speter case 'b': 37017721Speter case 'c': 37181404Speter case 'e': 37281404Speter case 'g': 37381404Speter case 'r': 37481404Speter case 'v': 37581404Speter case 'w': 37681404Speter case 'z': 37781404Speter (void)sprintf(flgbuf, "-%c", c); 37881404Speter appcstrg(&l1flags, flgbuf); 37981404Speter break; 38081404Speter 38181404Speter case 'F': 38281404Speter Fflag = 1; 38381404Speter /* FALLTHROUGH */ 38481404Speter case 'u': 38581404Speter case 'h': 38681404Speter (void)sprintf(flgbuf, "-%c", c); 38781404Speter appcstrg(&l1flags, flgbuf); 388 appcstrg(&l2flags, flgbuf); 389 break; 390 391 case 'X': 392 (void)sprintf(flgbuf, "-%c", c); 393 appcstrg(&l1flags, flgbuf); 394 appcstrg(&l1flags, optarg); 395 break; 396 397 case 'i': 398 if (Cflag) 399 usage(); 400 iflag = 1; 401 break; 402 403 case 'n': 404 freelst(&deflibs); 405 break; 406 407 case 'p': 408 appcstrg(&lcflags, "-Wtraditional"); 409 appcstrg(&lcflags, "-Wno-system-headers"); 410 appcstrg(&l1flags, "-p"); 411 appcstrg(&l2flags, "-p"); 412 if (*deflibs != NULL) { 413 freelst(&deflibs); 414 appcstrg(&deflibs, "c"); 415 } 416 break; 417 418 case 's': 419 if (tflag) 420 usage(); 421 freelst(&lcflags); 422 appcstrg(&lcflags, "-trigraphs"); 423 appcstrg(&lcflags, "-Wtrigraphs"); 424 appcstrg(&lcflags, "-pedantic"); 425 appcstrg(&lcflags, "-D__STRICT_ANSI__"); 426 appcstrg(&l1flags, "-s"); 427 appcstrg(&l2flags, "-s"); 428 sflag = 1; 429 break; 430 431 case 'S': 432 if (tflag) 433 usage(); 434 appcstrg(&l1flags, "-S"); 435 Sflag = 1; 436 break; 437 438#if !HAVE_CONFIG_H 439 case 't': 440 if (sflag) 441 usage(); 442 freelst(&lcflags); 443 appcstrg(&lcflags, "-traditional"); 444 appstrg(&lcflags, concat2("-D", MACHINE)); 445 appstrg(&lcflags, concat2("-D", MACHINE_ARCH)); 446 appcstrg(&l1flags, "-t"); 447 appcstrg(&l2flags, "-t"); 448 tflag = 1; 449 break; 450#endif 451 452 case 'x': 453 appcstrg(&l2flags, "-x"); 454 break; 455 456 case 'C': 457 if (Cflag || oflag || iflag) 458 usage(); 459 Cflag = 1; 460 appstrg(&l2flags, concat2("-C", optarg)); 461 p2out = xmalloc(sizeof ("llib-l.ln") + strlen(optarg)); 462 (void)sprintf(p2out, "llib-l%s.ln", optarg); 463 freelst(&deflibs); 464 break; 465 466 case 'd': 467 if (dflag) 468 usage(); 469 dflag = 1; 470 appcstrg(&cflags, "-nostdinc"); 471 appcstrg(&cflags, "-idirafter"); 472 appcstrg(&cflags, optarg); 473 break; 474 475 case 'D': 476 case 'I': 477 case 'M': 478 case 'U': 479 (void)sprintf(flgbuf, "-%c", c); 480 appstrg(&cflags, concat2(flgbuf, optarg)); 481 break; 482 483 case 'l': 484 appcstrg(&libs, optarg); 485 break; 486 487 case 'o': 488 if (Cflag || oflag) 489 usage(); 490 oflag = 1; 491 outputfn = xstrdup(optarg); 492 break; 493 494 case 'L': 495 appcstrg(&libsrchpath, optarg); 496 break; 497 498 case 'H': 499 appcstrg(&l2flags, "-H"); 500 break; 501 502 case 'B': 503 Bflag = 1; 504 libexec_path = xstrdup(optarg); 505 break; 506 507 case 'V': 508 Vflag = 1; 509 break; 510 511 default: 512 usage(); 513 /* NOTREACHED */ 514 } 515 } 516 argc -= optind; 517 argv += optind; 518 519 /* 520 * To avoid modifying getopt(3)'s state engine midstream, we 521 * explicitly accept just a few options after the first source file. 522 * 523 * In particular, only -l<lib> and -L<libdir> (and these with a space 524 * after -l or -L) are allowed. 525 */ 526 while (argc > 0) { 527 const char *arg = argv[0]; 528 529 if (arg[0] == '-') { 530 char ***list; 531 532 /* option */ 533 switch (arg[1]) { 534 case 'l': 535 list = &libs; 536 break; 537 538 case 'L': 539 list = &libsrchpath; 540 break; 541 542 default: 543 usage(); 544 /* NOTREACHED */ 545 } 546 if (arg[2]) 547 appcstrg(list, arg + 2); 548 else if (argc > 1) { 549 argc--; 550 appcstrg(list, *++argv); 551 } else 552 usage(); 553 } else { 554 /* filename */ 555 fname(arg); 556 first = 0; 557 } 558 argc--; 559 argv++; 560 } 561 562 if (first) 563 usage(); 564 565 if (iflag) 566 terminate(0); 567 568 if (!oflag) { 569 if ((tmp = getenv("LIBDIR")) == NULL || strlen(tmp) == 0) 570 tmp = PATH_LINTLIB; 571 appcstrg(&libsrchpath, tmp); 572 findlibs(libs); 573 findlibs(deflibs); 574 } 575 576 (void)printf("Lint pass2:\n"); 577 lint2(); 578 579 if (oflag) 580 cat(p2in, outputfn); 581 582 if (Cflag) 583 p2out = NULL; 584 585 terminate(0); 586 /* NOTREACHED */ 587} 588 589/* 590 * Read a file name from the command line 591 * and pass it through lint1 if it is a C source. 592 */ 593static void 594fname(const char *name) 595{ 596 const char *bn, *suff; 597 char **args, *ofn, *p, *pathname; 598 size_t len; 599 int is_stdin; 600 int fd; 601 602 is_stdin = (strcmp(name, "-") == 0); 603 bn = lbasename(name, '/'); 604 suff = lbasename(bn, '.'); 605 606 if (strcmp(suff, "ln") == 0) { 607 /* only for lint2 */ 608 if (!iflag) 609 appcstrg(&p2in, name); 610 return; 611 } 612 613 if (!is_stdin && strcmp(suff, "c") != 0 && 614 (strncmp(bn, "llib-l", 6) != 0 || bn != suff)) { 615 warnx("unknown file type: %s\n", name); 616 return; 617 } 618 619 if (!iflag || !first) 620 (void)printf("%s:\n", 621 is_stdin ? "{standard input}" : Fflag ? name : bn); 622 623 /* build the name of the output file of lint1 */ 624 if (oflag) { 625 ofn = outputfn; 626 outputfn = NULL; 627 oflag = 0; 628 } else if (iflag) { 629 if (is_stdin) { 630 warnx("-i not supported without -o for standard input"); 631 return; 632 } 633 ofn = xmalloc(strlen(bn) + (bn == suff ? 4 : 2)); 634 len = bn == suff ? strlen(bn) : (size_t)((suff - 1) - bn); 635 (void)sprintf(ofn, "%.*s", (int)len, bn); 636 (void)strcat(ofn, ".ln"); 637 } else { 638 ofn = xmalloc(strlen(tmpdir) + sizeof ("lint1.XXXXXX")); 639 (void)sprintf(ofn, "%slint1.XXXXXX", tmpdir); 640 fd = mkstemp(ofn); 641 if (fd == -1) { 642 warn("can't make temp"); 643 terminate(-1); 644 } 645 close(fd); 646 } 647 if (!iflag) 648 appcstrg(&p1out, ofn); 649 650 args = xcalloc(1, sizeof (char *)); 651 652 /* run cc */ 653 654 if (getenv("CC") == NULL) { 655 pathname = xmalloc(strlen(PATH_USRBIN) + sizeof ("/cc")); 656 (void)sprintf(pathname, "%s/cc", PATH_USRBIN); 657 appcstrg(&args, pathname); 658 } else { 659 pathname = strdup(getenv("CC")); 660 for (p = strtok(pathname, " \t"); p; p = strtok(NULL, " \t")) 661 appcstrg(&args, p); 662 } 663 664 applst(&args, cflags); 665 applst(&args, lcflags); 666 appcstrg(&args, name); 667 668 /* we reuse the same tmp file for cpp output, so rewind and truncate */ 669 if (lseek(cppoutfd, (off_t)0, SEEK_SET) != 0) { 670 warn("lseek"); 671 terminate(-1); 672 } 673 if (ftruncate(cppoutfd, (off_t)0) != 0) { 674 warn("ftruncate"); 675 terminate(-1); 676 } 677 678 runchild(pathname, args, cppout, cppoutfd); 679 free(pathname); 680 freelst(&args); 681 682 /* run lint1 */ 683 684 if (!Bflag) { 685 pathname = xmalloc(strlen(PATH_LIBEXEC) + sizeof ("/lint1") + 686 strlen(target_prefix)); 687 (void)sprintf(pathname, "%s/%slint1", PATH_LIBEXEC, 688 target_prefix); 689 } else { 690 /* 691 * XXX Unclear whether we should be using target_prefix 692 * XXX here. --thorpej@wasabisystems.com 693 */ 694 pathname = xmalloc(strlen(libexec_path) + sizeof ("/lint1")); 695 (void)sprintf(pathname, "%s/lint1", libexec_path); 696 } 697 698 appcstrg(&args, pathname); 699 applst(&args, l1flags); 700 appcstrg(&args, cppout); 701 appcstrg(&args, ofn); 702 703 runchild(pathname, args, ofn, -1); 704 free(pathname); 705 freelst(&args); 706 707 appcstrg(&p2in, ofn); 708 free(ofn); 709 710 free(args); 711} 712 713static void 714runchild(const char *path, char *const *args, const char *crfn, int fdout) 715{ 716 int status, rv, signo, i; 717 718 if (Vflag) { 719 for (i = 0; args[i] != NULL; i++) 720 (void)printf("%s ", args[i]); 721 (void)printf("\n"); 722 } 723 724 currfn = crfn; 725 726 (void)fflush(stdout); 727 728 switch (vfork()) { 729 case -1: 730 warn("cannot fork"); 731 terminate(-1); 732 /* NOTREACHED */ 733 default: 734 /* parent */ 735 break; 736 case 0: 737 /* child */ 738 739 /* setup the standard output if necessary */ 740 if (fdout != -1) { 741 dup2(fdout, STDOUT_FILENO); 742 close(fdout); 743 } 744 (void)execvp(path, args); 745 warn("cannot exec %s", path); 746 _exit(1); 747 /* NOTREACHED */ 748 } 749 750 while ((rv = wait(&status)) == -1 && errno == EINTR) ; 751 if (rv == -1) { 752 warn("wait"); 753 terminate(-1); 754 } 755 if (WIFSIGNALED(status)) { 756 signo = WTERMSIG(status); 757#if HAVE_DECL_SYS_SIGNAME 758 warnx("%s got SIG%s", path, sys_signame[signo]); 759#else 760 warnx("%s got signal %d", path, signo); 761#endif 762 terminate(-1); 763 } 764 if (WEXITSTATUS(status) != 0) 765 terminate(-1); 766 currfn = NULL; 767} 768 769static void 770findlibs(char *const *liblst) 771{ 772 int i, k; 773 const char *lib, *path; 774 char *lfn; 775 size_t len; 776 777 lfn = NULL; 778 779 for (i = 0; (lib = liblst[i]) != NULL; i++) { 780 for (k = 0; (path = libsrchpath[k]) != NULL; k++) { 781 len = strlen(path) + strlen(lib); 782 lfn = xrealloc(lfn, len + sizeof ("/llib-l.ln")); 783 (void)sprintf(lfn, "%s/llib-l%s.ln", path, lib); 784 if (rdok(lfn)) 785 break; 786 lfn = xrealloc(lfn, len + sizeof ("/lint/llib-l.ln")); 787 (void)sprintf(lfn, "%s/lint/llib-l%s.ln", path, lib); 788 if (rdok(lfn)) 789 break; 790 } 791 if (path != NULL) { 792 appstrg(&l2libs, concat2("-l", lfn)); 793 } else { 794 warnx("cannot find llib-l%s.ln", lib); 795 } 796 } 797 798 free(lfn); 799} 800 801static int 802rdok(const char *path) 803{ 804 struct stat sbuf; 805 806 if (stat(path, &sbuf) == -1) 807 return (0); 808 if (!S_ISREG(sbuf.st_mode)) 809 return (0); 810 if (access(path, R_OK) == -1) 811 return (0); 812 return (1); 813} 814 815static void 816lint2(void) 817{ 818 char *path, **args; 819 820 args = xcalloc(1, sizeof (char *)); 821 822 if (!Bflag) { 823 path = xmalloc(strlen(PATH_LIBEXEC) + sizeof ("/lint2") + 824 strlen(target_prefix)); 825 (void)sprintf(path, "%s/%slint2", PATH_LIBEXEC, 826 target_prefix); 827 } else { 828 /* 829 * XXX Unclear whether we should be using target_prefix 830 * XXX here. --thorpej@wasabisystems.com 831 */ 832 path = xmalloc(strlen(libexec_path) + sizeof ("/lint2")); 833 (void)sprintf(path, "%s/lint2", libexec_path); 834 } 835 836 appcstrg(&args, path); 837 applst(&args, l2flags); 838 applst(&args, l2libs); 839 applst(&args, p2in); 840 841 runchild(path, args, p2out, -1); 842 free(path); 843 freelst(&args); 844 free(args); 845} 846 847static void 848cat(char *const *srcs, const char *dest) 849{ 850 int ifd, ofd, i; 851 char *src, *buf; 852 ssize_t rlen; 853 854 if ((ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) { 855 warn("cannot open %s", dest); 856 terminate(-1); 857 } 858 859 buf = xmalloc(MBLKSIZ); 860 861 for (i = 0; (src = srcs[i]) != NULL; i++) { 862 if ((ifd = open(src, O_RDONLY)) == -1) { 863 free(buf); 864 warn("cannot open %s", src); 865 terminate(-1); 866 } 867 do { 868 if ((rlen = read(ifd, buf, MBLKSIZ)) == -1) { 869 free(buf); 870 warn("read error on %s", src); 871 terminate(-1); 872 } 873 if (write(ofd, buf, (size_t)rlen) == -1) { 874 free(buf); 875 warn("write error on %s", dest); 876 terminate(-1); 877 } 878 } while (rlen == MBLKSIZ); 879 (void)close(ifd); 880 } 881 (void)close(ofd); 882 free(buf); 883} 884