Annotation of src/usr.bin/xlint/xlint/xlint.c, Revision 1.25
1.25 ! tv 1: /* $NetBSD: xlint.c,v 1.24 2001/10/24 02:31:10 thorpej Exp $ */
1.2 cgd 2:
1.1 cgd 3: /*
1.4 cgd 4: * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved.
1.1 cgd 5: * Copyright (c) 1994, 1995 Jochen Pohl
6: * All Rights Reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by Jochen Pohl for
19: * The NetBSD Project.
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
1.6 christos 35: #include <sys/cdefs.h>
1.1 cgd 36: #ifndef lint
1.25 ! tv 37: __RCSID("$NetBSD: xlint.c,v 1.24 2001/10/24 02:31:10 thorpej Exp $");
1.1 cgd 38: #endif
39:
1.3 jpo 40: #include <sys/param.h>
1.1 cgd 41: #include <sys/wait.h>
42: #include <sys/stat.h>
1.3 jpo 43: #include <sys/utsname.h>
1.25 ! tv 44: #include <errno.h>
! 45: #include <fcntl.h>
! 46: #include <paths.h>
! 47: #include <signal.h>
1.1 cgd 48: #include <stdio.h>
49: #include <stdlib.h>
50: #include <string.h>
51: #include <unistd.h>
52:
53: #include "lint.h"
54: #include "pathnames.h"
55:
1.23 lukem 56: int main(int, char *[]);
1.6 christos 57:
1.1 cgd 58: /* directory for temporary files */
59: static const char *tmpdir;
60:
61: /* path name for cpp output */
62: static char *cppout;
63:
1.10 mrg 64: /* file descriptor for cpp output */
65: static int cppoutfd = -1;
66:
1.1 cgd 67: /* files created by 1st pass */
68: static char **p1out;
69:
70: /* input files for 2nd pass (without libraries) */
71: static char **p2in;
72:
73: /* library which will be created by 2nd pass */
74: static char *p2out;
75:
1.10 mrg 76: /* flags always passed to cc(1) */
77: static char **cflags;
1.1 cgd 78:
1.10 mrg 79: /* flags for cc(1), controled by sflag/tflag */
80: static char **lcflags;
1.1 cgd 81:
82: /* flags for lint1 */
83: static char **l1flags;
84:
85: /* flags for lint2 */
86: static char **l2flags;
87:
88: /* libraries for lint2 */
89: static char **l2libs;
90:
91: /* default libraries */
92: static char **deflibs;
93:
94: /* additional libraries */
95: static char **libs;
96:
97: /* search path for libraries */
98: static char **libsrchpath;
99:
1.17 garbled 100: static char *libexec_path;
101:
1.1 cgd 102: /* flags */
1.17 garbled 103: static int iflag, oflag, Cflag, sflag, tflag, Fflag, dflag, Bflag;
1.1 cgd 104:
105: /* print the commands executed to run the stages of compilation */
106: static int Vflag;
107:
108: /* filename for oflag */
109: static char *outputfn;
110:
111: /* reset after first .c source has been processed */
112: static int first = 1;
113:
114: /*
115: * name of a file which is currently written by a child and should
116: * be removed after abnormal termination of the child
117: */
118: static const char *currfn;
119:
1.24 thorpej 120: #if !defined(TARGET_PREFIX)
121: #define TARGET_PREFIX ""
122: #endif
123: static const char target_prefix[] = TARGET_PREFIX;
1.1 cgd 124:
1.23 lukem 125: static void appstrg(char ***, char *);
126: static void appcstrg(char ***, const char *);
127: static void applst(char ***, char *const *);
128: static void freelst(char ***);
129: static char *concat2(const char *, const char *);
130: static char *concat3(const char *, const char *, const char *);
131: static void terminate(int) __attribute__((__noreturn__));
1.25 ! tv 132: static const char *lbasename(const char *, int);
1.23 lukem 133: static void appdef(char ***, const char *);
134: static void usage(void);
135: static void fname(const char *, int);
136: static void runchild(const char *, char *const *, const char *, int);
137: static void findlibs(char *const *);
138: static int rdok(const char *);
139: static void lint2(void);
140: static void cat(char *const *, const char *);
1.1 cgd 141:
142: /*
143: * Some functions to deal with lists of strings.
144: * Take care that we get no surprises in case of asyncron signals.
145: */
146: static void
1.23 lukem 147: appstrg(char ***lstp, char *s)
1.1 cgd 148: {
149: char **lst, **olst;
150: int i;
151:
152: olst = *lstp;
1.23 lukem 153: for (i = 0; olst[i] != NULL; i++)
154: continue;
1.8 itohy 155: lst = xrealloc(olst, (i + 2) * sizeof (char *));
1.3 jpo 156: lst[i] = s;
1.1 cgd 157: lst[i + 1] = NULL;
158: *lstp = lst;
1.23 lukem 159: }
1.1 cgd 160:
161: static void
1.23 lukem 162: appcstrg(char ***lstp, const char *s)
1.1 cgd 163: {
1.23 lukem 164:
1.3 jpo 165: appstrg(lstp, xstrdup(s));
1.1 cgd 166: }
167:
168: static void
1.23 lukem 169: applst(char ***destp, char *const *src)
1.1 cgd 170: {
171: int i, k;
172: char **dest, **odest;
173:
174: odest = *destp;
1.23 lukem 175: for (i = 0; odest[i] != NULL; i++)
176: continue;
177: for (k = 0; src[k] != NULL; k++)
178: continue;
1.8 itohy 179: dest = xrealloc(odest, (i + k + 1) * sizeof (char *));
1.1 cgd 180: for (k = 0; src[k] != NULL; k++)
181: dest[i + k] = xstrdup(src[k]);
182: dest[i + k] = NULL;
183: *destp = dest;
184: }
185:
186: static void
1.23 lukem 187: freelst(char ***lstp)
1.1 cgd 188: {
189: char *s;
190: int i;
191:
1.23 lukem 192: for (i = 0; (*lstp)[i] != NULL; i++)
193: continue;
1.1 cgd 194: while (i-- > 0) {
195: s = (*lstp)[i];
196: (*lstp)[i] = NULL;
197: free(s);
198: }
199: }
200:
1.3 jpo 201: static char *
1.23 lukem 202: concat2(const char *s1, const char *s2)
1.3 jpo 203: {
204: char *s;
205:
206: s = xmalloc(strlen(s1) + strlen(s2) + 1);
207: (void)strcpy(s, s1);
208: (void)strcat(s, s2);
209:
210: return (s);
211: }
212:
213: static char *
1.23 lukem 214: concat3(const char *s1, const char *s2, const char *s3)
1.3 jpo 215: {
216: char *s;
217:
218: s = xmalloc(strlen(s1) + strlen(s2) + strlen(s3) + 1);
219: (void)strcpy(s, s1);
220: (void)strcat(s, s2);
221: (void)strcat(s, s3);
222:
223: return (s);
224: }
225:
1.1 cgd 226: /*
227: * Clean up after a signal.
228: */
229: static void
1.23 lukem 230: terminate(int signo)
1.1 cgd 231: {
232: int i;
233:
1.10 mrg 234: if (cppoutfd != -1)
235: (void)close(cppoutfd);
1.1 cgd 236: if (cppout != NULL)
237: (void)remove(cppout);
238:
239: if (p1out != NULL) {
240: for (i = 0; p1out[i] != NULL; i++)
241: (void)remove(p1out[i]);
242: }
243:
244: if (p2out != NULL)
245: (void)remove(p2out);
246:
247: if (currfn != NULL)
248: (void)remove(currfn);
249:
250: exit(signo != 0 ? 1 : 0);
251: }
252:
253: /*
254: * Returns a pointer to the last component of strg after delim.
255: * Returns strg if the string does not contain delim.
256: */
257: static const char *
1.25 ! tv 258: lbasename(const char *strg, int delim)
1.1 cgd 259: {
260: const char *cp, *cp1, *cp2;
261:
262: cp = cp1 = cp2 = strg;
263: while (*cp != '\0') {
264: if (*cp++ == delim) {
265: cp2 = cp1;
266: cp1 = cp;
267: }
268: }
269: return (*cp1 == '\0' ? cp2 : cp1);
270: }
271:
272: static void
1.23 lukem 273: appdef(char ***lstp, const char *def)
1.3 jpo 274: {
1.23 lukem 275:
1.3 jpo 276: appstrg(lstp, concat2("-D__", def));
277: appstrg(lstp, concat3("-D__", def, "__"));
278: }
279:
280: static void
1.23 lukem 281: usage(void)
1.1 cgd 282: {
1.22 cgd 283:
1.12 christos 284: (void)fprintf(stderr,
1.20 christos 285: "Usage: %s [-abceghprvwxzHF] [-s|-t] [-i|-nu] [-Dname[=def]]"
1.22 cgd 286: " [-Uname] [-X <id>[,<id>]...\n", getprogname());
1.23 lukem 287: (void)fprintf(stderr,
1.20 christos 288: "\t[-Idirectory] [-Ldirectory] [-llibrary] [-ooutputfile]"
289: " file...\n");
1.12 christos 290: (void)fprintf(stderr,
1.20 christos 291: " %s [-abceghprvwzHF] [-s|-t] -Clibrary [-Dname[=def]]\n"
1.22 cgd 292: " [-X <id>[,<id>]...\n", getprogname());
1.20 christos 293: (void)fprintf(stderr, "\t[-Idirectory] [-Uname] [-Bpath] file"
294: " ...\n");
1.1 cgd 295: terminate(-1);
296: }
1.6 christos 297:
1.1 cgd 298:
299: int
1.23 lukem 300: main(int argc, char *argv[])
1.1 cgd 301: {
302: int c;
303: char flgbuf[3], *tmp, *s;
304: size_t len;
305:
306: if ((tmp = getenv("TMPDIR")) == NULL || (len = strlen(tmp)) == 0) {
307: tmpdir = xstrdup(_PATH_TMP);
308: } else {
309: s = xmalloc(len + 2);
310: (void)sprintf(s, "%s%s", tmp, tmp[len - 1] == '/' ? "" : "/");
311: tmpdir = s;
312: }
313:
314: cppout = xmalloc(strlen(tmpdir) + sizeof ("lint0.XXXXXX"));
315: (void)sprintf(cppout, "%slint0.XXXXXX", tmpdir);
1.10 mrg 316: cppoutfd = mkstemp(cppout);
317: if (cppoutfd == -1) {
1.1 cgd 318: warn("can't make temp");
319: terminate(-1);
320: }
321:
322: p1out = xcalloc(1, sizeof (char *));
323: p2in = xcalloc(1, sizeof (char *));
1.10 mrg 324: cflags = xcalloc(1, sizeof (char *));
325: lcflags = xcalloc(1, sizeof (char *));
1.1 cgd 326: l1flags = xcalloc(1, sizeof (char *));
327: l2flags = xcalloc(1, sizeof (char *));
328: l2libs = xcalloc(1, sizeof (char *));
329: deflibs = xcalloc(1, sizeof (char *));
330: libs = xcalloc(1, sizeof (char *));
331: libsrchpath = xcalloc(1, sizeof (char *));
332:
1.10 mrg 333: appcstrg(&cflags, "-E");
334: appcstrg(&cflags, "-x");
335: appcstrg(&cflags, "c");
1.12 christos 336: #if 0
1.10 mrg 337: appcstrg(&cflags, "-D__attribute__(x)=");
1.11 christos 338: appcstrg(&cflags, "-D__extension__(x)=/*NOSTRICT*/0");
1.12 christos 339: #else
340: appcstrg(&cflags, "-U__GNUC__");
341: #endif
1.10 mrg 342: appcstrg(&cflags, "-Wp,-$");
343: appcstrg(&cflags, "-Wp,-CC");
344: appcstrg(&cflags, "-Wcomment");
1.16 kleink 345: appcstrg(&cflags, "-D__LINT__");
1.10 mrg 346: appcstrg(&cflags, "-Dlint"); /* XXX don't def. with -s */
347:
348: appdef(&cflags, "lint");
349:
350: appcstrg(&lcflags, "-Wtraditional");
351:
1.3 jpo 352: appcstrg(&deflibs, "c");
1.1 cgd 353:
354: if (signal(SIGHUP, terminate) == SIG_IGN)
355: (void)signal(SIGHUP, SIG_IGN);
356: (void)signal(SIGINT, terminate);
357: (void)signal(SIGQUIT, terminate);
358: (void)signal(SIGTERM, terminate);
359:
360: while (argc > optind) {
361:
362:
1.20 christos 363: c = getopt(argc, argv, "abcd:eghil:no:prstuvwxzB:C:D:FHI:L:U:VX:");
1.1 cgd 364:
365: switch (c) {
366:
367: case 'a':
368: case 'b':
369: case 'c':
370: case 'e':
371: case 'g':
372: case 'r':
373: case 'v':
1.20 christos 374: case 'w':
1.1 cgd 375: case 'z':
376: (void)sprintf(flgbuf, "-%c", c);
1.3 jpo 377: appcstrg(&l1flags, flgbuf);
1.1 cgd 378: break;
379:
380: case 'F':
381: Fflag = 1;
382: /* FALLTHROUGH */
383: case 'u':
384: case 'h':
385: (void)sprintf(flgbuf, "-%c", c);
1.3 jpo 386: appcstrg(&l1flags, flgbuf);
387: appcstrg(&l2flags, flgbuf);
1.20 christos 388: break;
389:
390: case 'X':
391: (void)sprintf(flgbuf, "-%c", c);
392: appcstrg(&l1flags, flgbuf);
393: appcstrg(&l1flags, optarg);
1.1 cgd 394: break;
395:
396: case 'i':
397: if (Cflag)
398: usage();
399: iflag = 1;
400: break;
401:
402: case 'n':
403: freelst(&deflibs);
404: break;
405:
406: case 'p':
1.3 jpo 407: appcstrg(&l1flags, "-p");
408: appcstrg(&l2flags, "-p");
1.1 cgd 409: if (*deflibs != NULL) {
410: freelst(&deflibs);
1.3 jpo 411: appcstrg(&deflibs, "c");
1.1 cgd 412: }
413: break;
414:
415: case 's':
416: if (tflag)
417: usage();
1.10 mrg 418: freelst(&lcflags);
419: appcstrg(&lcflags, "-trigraphs");
420: appcstrg(&lcflags, "-Wtrigraphs");
421: appcstrg(&lcflags, "-pedantic");
422: appcstrg(&lcflags, "-D__STRICT_ANSI__");
1.3 jpo 423: appcstrg(&l1flags, "-s");
424: appcstrg(&l2flags, "-s");
1.1 cgd 425: sflag = 1;
426: break;
427:
1.25 ! tv 428: #if !HAVE_CONFIG_H
1.1 cgd 429: case 't':
430: if (sflag)
431: usage();
1.10 mrg 432: freelst(&lcflags);
433: appcstrg(&lcflags, "-traditional");
434: appstrg(&lcflags, concat2("-D", MACHINE));
435: appstrg(&lcflags, concat2("-D", MACHINE_ARCH));
1.3 jpo 436: appcstrg(&l1flags, "-t");
437: appcstrg(&l2flags, "-t");
1.1 cgd 438: tflag = 1;
439: break;
1.25 ! tv 440: #endif
1.1 cgd 441:
442: case 'x':
1.3 jpo 443: appcstrg(&l2flags, "-x");
1.1 cgd 444: break;
445:
446: case 'C':
447: if (Cflag || oflag || iflag)
448: usage();
449: Cflag = 1;
1.3 jpo 450: appstrg(&l2flags, concat2("-C", optarg));
1.1 cgd 451: p2out = xmalloc(sizeof ("llib-l.ln") + strlen(optarg));
452: (void)sprintf(p2out, "llib-l%s.ln", optarg);
453: freelst(&deflibs);
454: break;
455:
1.7 sommerfe 456: case 'd':
457: if (dflag)
458: usage();
459: dflag = 1;
1.10 mrg 460: appcstrg(&cflags, "-nostdinc");
461: appcstrg(&cflags, "-idirafter");
462: appcstrg(&cflags, optarg);
1.7 sommerfe 463: break;
1.23 lukem 464:
1.1 cgd 465: case 'D':
466: case 'I':
467: case 'U':
468: (void)sprintf(flgbuf, "-%c", c);
1.10 mrg 469: appstrg(&cflags, concat2(flgbuf, optarg));
1.1 cgd 470: break;
471:
472: case 'l':
1.3 jpo 473: appcstrg(&libs, optarg);
1.1 cgd 474: break;
475:
476: case 'o':
477: if (Cflag || oflag)
478: usage();
479: oflag = 1;
480: outputfn = xstrdup(optarg);
481: break;
482:
483: case 'L':
1.3 jpo 484: appcstrg(&libsrchpath, optarg);
1.1 cgd 485: break;
486:
487: case 'H':
1.3 jpo 488: appcstrg(&l2flags, "-H");
1.1 cgd 489: break;
490:
1.17 garbled 491: case 'B':
492: Bflag = 1;
493: libexec_path = xstrdup(optarg);
494: break;
495:
1.1 cgd 496: case 'V':
497: Vflag = 1;
498: break;
499:
500: case -1:
501: /* filename */
1.21 wiz 502: fname(argv[optind], argc == optind+1);
1.1 cgd 503: first = 0;
1.21 wiz 504: optind++;
1.25 ! tv 505:
! 506: default:
! 507: usage();
! 508: /* NOTREACHED */
1.1 cgd 509: }
510:
511: }
1.21 wiz 512: argc -= optind;
513: argv += optind;
1.1 cgd 514:
515: if (first)
516: usage();
517:
518: if (iflag)
519: terminate(0);
520:
521: if (!oflag) {
522: if ((s = getenv("LIBDIR")) == NULL || strlen(s) == 0)
523: s = PATH_LINTLIB;
1.3 jpo 524: appcstrg(&libsrchpath, s);
1.1 cgd 525: findlibs(libs);
526: findlibs(deflibs);
527: }
528:
529: (void)printf("Lint pass2:\n");
530: lint2();
531:
532: if (oflag)
533: cat(p2in, outputfn);
534:
535: if (Cflag)
536: p2out = NULL;
537:
538: terminate(0);
539: /* NOTREACHED */
540: }
541:
542: /*
543: * Read a file name from the command line
544: * and pass it through lint1 if it is a C source.
545: */
546: static void
1.23 lukem 547: fname(const char *name, int last)
1.1 cgd 548: {
549: const char *bn, *suff;
550: char **args, *ofn, *path;
551: size_t len;
1.4 cgd 552: int is_stdin;
1.10 mrg 553: int fd;
1.1 cgd 554:
1.4 cgd 555: is_stdin = (strcmp(name, "-") == 0);
1.25 ! tv 556: bn = lbasename(name, '/');
! 557: suff = lbasename(bn, '.');
1.1 cgd 558:
559: if (strcmp(suff, "ln") == 0) {
560: /* only for lint2 */
561: if (!iflag)
1.3 jpo 562: appcstrg(&p2in, name);
1.1 cgd 563: return;
564: }
565:
1.4 cgd 566: if (!is_stdin && strcmp(suff, "c") != 0 &&
1.1 cgd 567: (strncmp(bn, "llib-l", 6) != 0 || bn != suff)) {
568: warnx("unknown file type: %s\n", name);
569: return;
570: }
571:
572: if (!iflag || !first || !last)
1.4 cgd 573: (void)printf("%s:\n",
574: is_stdin ? "{standard input}" : Fflag ? name : bn);
1.1 cgd 575:
576: /* build the name of the output file of lint1 */
577: if (oflag) {
578: ofn = outputfn;
579: outputfn = NULL;
580: oflag = 0;
581: } else if (iflag) {
1.4 cgd 582: if (is_stdin) {
583: warnx("-i not supported without -o for standard input");
584: return;
585: }
1.1 cgd 586: ofn = xmalloc(strlen(bn) + (bn == suff ? 4 : 2));
587: len = bn == suff ? strlen(bn) : (suff - 1) - bn;
588: (void)sprintf(ofn, "%.*s", (int)len, bn);
589: (void)strcat(ofn, ".ln");
590: } else {
591: ofn = xmalloc(strlen(tmpdir) + sizeof ("lint1.XXXXXX"));
592: (void)sprintf(ofn, "%slint1.XXXXXX", tmpdir);
1.10 mrg 593: fd = mkstemp(ofn);
594: if (fd == -1) {
1.1 cgd 595: warn("can't make temp");
596: terminate(-1);
597: }
1.10 mrg 598: close(fd);
1.1 cgd 599: }
600: if (!iflag)
1.3 jpo 601: appcstrg(&p1out, ofn);
1.1 cgd 602:
603: args = xcalloc(1, sizeof (char *));
604:
1.10 mrg 605: /* run cc */
1.1 cgd 606:
1.17 garbled 607: if (getenv("CC") == NULL) {
608: path = xmalloc(strlen(PATH_USRBIN) + sizeof ("/cc"));
609: (void)sprintf(path, "%s/cc", PATH_USRBIN);
610: } else {
611: path = strdup(getenv("CC"));
612: }
1.1 cgd 613:
1.3 jpo 614: appcstrg(&args, path);
1.10 mrg 615: applst(&args, cflags);
616: applst(&args, lcflags);
1.3 jpo 617: appcstrg(&args, name);
1.1 cgd 618:
1.15 jwise 619: /* we reuse the same tmp file for cpp output, so rewind and truncate */
620: if (lseek(cppoutfd, SEEK_SET, (off_t)0) != 0) {
621: warn("lseek");
622: terminate(-1);
623: }
624: if (ftruncate(cppoutfd, (off_t)0) != 0) {
625: warn("ftruncate");
626: terminate(-1);
627: }
1.23 lukem 628:
1.10 mrg 629: runchild(path, args, cppout, cppoutfd);
1.1 cgd 630: free(path);
631: freelst(&args);
632:
633: /* run lint1 */
634:
1.17 garbled 635: if (!Bflag) {
1.24 thorpej 636: path = xmalloc(strlen(PATH_LIBEXEC) + sizeof ("/lint1") +
637: strlen(target_prefix));
638: (void)sprintf(path, "%s/%slint1", PATH_LIBEXEC,
639: target_prefix);
1.17 garbled 640: } else {
1.24 thorpej 641: /*
642: * XXX Unclear whether we should be using target_prefix
643: * XXX here. --thorpej@wasabisystems.com
644: */
1.17 garbled 645: path = xmalloc(strlen(libexec_path) + sizeof ("/lint1"));
646: (void)sprintf(path, "%s/lint1", libexec_path);
647: }
1.1 cgd 648:
1.3 jpo 649: appcstrg(&args, path);
1.1 cgd 650: applst(&args, l1flags);
1.3 jpo 651: appcstrg(&args, cppout);
652: appcstrg(&args, ofn);
1.1 cgd 653:
1.10 mrg 654: runchild(path, args, ofn, -1);
1.1 cgd 655: free(path);
656: freelst(&args);
657:
1.3 jpo 658: appcstrg(&p2in, ofn);
1.1 cgd 659: free(ofn);
660:
661: free(args);
662: }
663:
664: static void
1.23 lukem 665: runchild(const char *path, char *const *args, const char *crfn, int fdout)
1.1 cgd 666: {
667: int status, rv, signo, i;
668:
669: if (Vflag) {
670: for (i = 0; args[i] != NULL; i++)
671: (void)printf("%s ", args[i]);
672: (void)printf("\n");
673: }
674:
675: currfn = crfn;
676:
677: (void)fflush(stdout);
678:
1.15 jwise 679: switch (vfork()) {
1.1 cgd 680: case -1:
681: warn("cannot fork");
682: terminate(-1);
683: /* NOTREACHED */
684: default:
685: /* parent */
686: break;
687: case 0:
688: /* child */
1.10 mrg 689:
690: /* setup the standard output if necessary */
691: if (fdout != -1) {
692: dup2(fdout, STDOUT_FILENO);
693: close(fdout);
694: }
1.19 wrstuden 695: (void)execvp(path, args);
1.1 cgd 696: warn("cannot exec %s", path);
1.15 jwise 697: _exit(1);
1.1 cgd 698: /* NOTREACHED */
699: }
700:
701: while ((rv = wait(&status)) == -1 && errno == EINTR) ;
702: if (rv == -1) {
703: warn("wait");
704: terminate(-1);
705: }
706: if (WIFSIGNALED(status)) {
707: signo = WTERMSIG(status);
1.25 ! tv 708: #if HAVE_DECL_SYS_SIGNAME
1.1 cgd 709: warnx("%s got SIG%s", path, sys_signame[signo]);
1.25 ! tv 710: #else
! 711: warnx("%s got signal %d", path, signo);
! 712: #endif
1.1 cgd 713: terminate(-1);
714: }
715: if (WEXITSTATUS(status) != 0)
716: terminate(-1);
717: currfn = NULL;
718: }
719:
720: static void
1.23 lukem 721: findlibs(char *const *liblst)
1.1 cgd 722: {
723: int i, k;
724: const char *lib, *path;
725: char *lfn;
726: size_t len;
727:
728: lfn = NULL;
729:
730: for (i = 0; (lib = liblst[i]) != NULL; i++) {
731: for (k = 0; (path = libsrchpath[k]) != NULL; k++) {
732: len = strlen(path) + strlen(lib);
733: lfn = xrealloc(lfn, len + sizeof ("/llib-l.ln"));
734: (void)sprintf(lfn, "%s/llib-l%s.ln", path, lib);
735: if (rdok(lfn))
736: break;
737: lfn = xrealloc(lfn, len + sizeof ("/lint/llib-l.ln"));
738: (void)sprintf(lfn, "%s/lint/llib-l%s.ln", path, lib);
739: if (rdok(lfn))
740: break;
741: }
742: if (path != NULL) {
1.3 jpo 743: appstrg(&l2libs, concat2("-l", lfn));
1.1 cgd 744: } else {
745: warnx("cannot find llib-l%s.ln", lib);
746: }
747: }
748:
749: free(lfn);
750: }
751:
752: static int
1.23 lukem 753: rdok(const char *path)
1.1 cgd 754: {
755: struct stat sbuf;
756:
757: if (stat(path, &sbuf) == -1)
758: return (0);
1.5 mycroft 759: if (!S_ISREG(sbuf.st_mode))
1.1 cgd 760: return (0);
761: if (access(path, R_OK) == -1)
762: return (0);
763: return (1);
764: }
765:
766: static void
1.23 lukem 767: lint2(void)
1.1 cgd 768: {
769: char *path, **args;
770:
771: args = xcalloc(1, sizeof (char *));
772:
1.17 garbled 773: if (!Bflag) {
1.24 thorpej 774: path = xmalloc(strlen(PATH_LIBEXEC) + sizeof ("/lint2") +
775: strlen(target_prefix));
776: (void)sprintf(path, "%s/%slint2", PATH_LIBEXEC,
777: target_prefix);
1.17 garbled 778: } else {
1.24 thorpej 779: /*
780: * XXX Unclear whether we should be using target_prefix
781: * XXX here. --thorpej@wasabisystems.com
782: */
1.17 garbled 783: path = xmalloc(strlen(libexec_path) + sizeof ("/lint2"));
784: (void)sprintf(path, "%s/lint2", libexec_path);
1.23 lukem 785: }
786:
1.3 jpo 787: appcstrg(&args, path);
1.1 cgd 788: applst(&args, l2flags);
789: applst(&args, l2libs);
790: applst(&args, p2in);
791:
1.10 mrg 792: runchild(path, args, p2out, -1);
1.1 cgd 793: free(path);
794: freelst(&args);
795: free(args);
796: }
797:
798: static void
1.23 lukem 799: cat(char *const *srcs, const char *dest)
1.1 cgd 800: {
801: int ifd, ofd, i;
802: char *src, *buf;
803: ssize_t rlen;
804:
805: if ((ofd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1) {
806: warn("cannot open %s", dest);
807: terminate(-1);
808: }
809:
810: buf = xmalloc(MBLKSIZ);
811:
812: for (i = 0; (src = srcs[i]) != NULL; i++) {
813: if ((ifd = open(src, O_RDONLY)) == -1) {
814: free(buf);
815: warn("cannot open %s", src);
816: terminate(-1);
817: }
818: do {
819: if ((rlen = read(ifd, buf, MBLKSIZ)) == -1) {
820: free(buf);
821: warn("read error on %s", src);
822: terminate(-1);
823: }
824: if (write(ofd, buf, (size_t)rlen) == -1) {
825: free(buf);
826: warn("write error on %s", dest);
827: terminate(-1);
828: }
829: } while (rlen == MBLKSIZ);
830: (void)close(ifd);
831: }
832: (void)close(ofd);
833: free(buf);
834: }
CVSweb <webmaster@jp.NetBSD.org>