Annotation of src/usr.bin/make/main.c, Revision 1.117
1.117 ! dsl 1: /* $NetBSD: main.c,v 1.116 2005/08/09 21:36:42 christos Exp $ */
1.19 christos 2:
1.1 cgd 3: /*
1.31 christos 4: * Copyright (c) 1988, 1989, 1990, 1993
5: * The Regents of the University of California. All rights reserved.
1.91 agc 6: *
7: * This code is derived from software contributed to Berkeley by
8: * Adam de Boor.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: */
34:
35: /*
1.1 cgd 36: * Copyright (c) 1989 by Berkeley Softworks
37: * All rights reserved.
38: *
39: * This code is derived from software contributed to Berkeley by
40: * Adam de Boor.
41: *
42: * Redistribution and use in source and binary forms, with or without
43: * modification, are permitted provided that the following conditions
44: * are met:
45: * 1. Redistributions of source code must retain the above copyright
46: * notice, this list of conditions and the following disclaimer.
47: * 2. Redistributions in binary form must reproduce the above copyright
48: * notice, this list of conditions and the following disclaimer in the
49: * documentation and/or other materials provided with the distribution.
50: * 3. All advertising materials mentioning features or use of this software
51: * must display the following acknowledgement:
52: * This product includes software developed by the University of
53: * California, Berkeley and its contributors.
54: * 4. Neither the name of the University nor the names of its contributors
55: * may be used to endorse or promote products derived from this software
56: * without specific prior written permission.
57: *
58: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68: * SUCH DAMAGE.
69: */
70:
1.102 ross 71: #ifndef MAKE_NATIVE
1.117 ! dsl 72: static char rcsid[] = "$NetBSD: main.c,v 1.116 2005/08/09 21:36:42 christos Exp $";
1.38 lukem 73: #else
1.37 christos 74: #include <sys/cdefs.h>
1.1 cgd 75: #ifndef lint
1.37 christos 76: __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\n\
77: The Regents of the University of California. All rights reserved.\n");
1.1 cgd 78: #endif /* not lint */
79:
80: #ifndef lint
1.19 christos 81: #if 0
1.31 christos 82: static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
1.19 christos 83: #else
1.117 ! dsl 84: __RCSID("$NetBSD: main.c,v 1.116 2005/08/09 21:36:42 christos Exp $");
1.19 christos 85: #endif
1.1 cgd 86: #endif /* not lint */
1.38 lukem 87: #endif
1.1 cgd 88:
89: /*-
90: * main.c --
91: * The main file for this entire program. Exit routines etc
92: * reside here.
93: *
94: * Utility functions defined in this file:
95: * Main_ParseArgLine Takes a line of arguments, breaks them and
96: * treats them as if they were given when first
97: * invoked. Used by the parse module to implement
98: * the .MFLAGS target.
99: *
100: * Error Print a tagged error message. The global
101: * MAKE variable must have been defined. This
102: * takes a format string and two optional
103: * arguments for it.
104: *
105: * Fatal Print an error message and exit. Also takes
106: * a format string and two arguments.
107: *
108: * Punt Aborts all jobs and exits with a message. Also
109: * takes a format string and two arguments.
110: *
111: * Finish Finish things up by printing the number of
1.72 wiz 112: * errors which occurred, as passed to it, and
1.1 cgd 113: * exiting.
114: */
115:
1.13 cgd 116: #include <sys/types.h>
117: #include <sys/time.h>
1.1 cgd 118: #include <sys/param.h>
1.13 cgd 119: #include <sys/resource.h>
1.21 christos 120: #include <sys/signal.h>
1.1 cgd 121: #include <sys/stat.h>
1.102 ross 122: #ifdef MAKE_NATIVE
1.17 gwr 123: #include <sys/utsname.h>
1.31 christos 124: #endif
1.29 christos 125: #include <sys/wait.h>
1.85 wiz 126:
1.1 cgd 127: #include <errno.h>
128: #include <fcntl.h>
1.85 wiz 129: #include <stdarg.h>
1.1 cgd 130: #include <stdio.h>
1.32 christos 131: #include <stdlib.h>
1.42 kleink 132: #include <time.h>
1.85 wiz 133:
1.1 cgd 134: #include "make.h"
1.13 cgd 135: #include "hash.h"
136: #include "dir.h"
137: #include "job.h"
1.1 cgd 138: #include "pathnames.h"
1.58 sommerfe 139: #include "trace.h"
1.1 cgd 140:
1.66 christos 141: #ifdef USE_IOVEC
142: #include <sys/uio.h>
143: #endif
144:
1.1 cgd 145: #ifndef DEFMAXLOCAL
146: #define DEFMAXLOCAL DEFMAXJOBS
1.24 christos 147: #endif /* DEFMAXLOCAL */
1.1 cgd 148:
149: Lst create; /* Targets to be made */
150: time_t now; /* Time at start of make */
151: GNode *DEFAULT; /* .DEFAULT node */
152: Boolean allPrecious; /* .PRECIOUS given on line by itself */
153:
154: static Boolean noBuiltins; /* -r flag */
155: static Lst makefiles; /* ordered list of makefiles to read */
1.31 christos 156: static Boolean printVars; /* print value of one or more vars */
157: static Lst variables; /* list of variables to print */
1.21 christos 158: int maxJobs; /* -j argument */
1.1 cgd 159: static int maxLocal; /* -L argument */
1.13 cgd 160: Boolean compatMake; /* -B argument */
1.113 christos 161: int debug; /* -d argument */
1.1 cgd 162: Boolean noExecute; /* -n flag */
1.61 sommerfe 163: Boolean noRecursiveExecute; /* -N flag */
1.1 cgd 164: Boolean keepgoing; /* -k flag */
165: Boolean queryFlag; /* -q flag */
166: Boolean touchFlag; /* -t flag */
167: Boolean usePipes; /* !-P flag */
168: Boolean ignoreErrors; /* -i flag */
169: Boolean beSilent; /* -s flag */
170: Boolean oldVars; /* variable substitution style */
171: Boolean checkEnvFirst; /* -e flag */
1.63 christos 172: Boolean parseWarnFatal; /* -W flag */
1.58 sommerfe 173: Boolean jobServer; /* -J flag */
1.87 thorpej 174: Boolean varNoExportEnv; /* -X flag */
1.1 cgd 175: static Boolean jobsRunning; /* TRUE if the jobs might be running */
1.58 sommerfe 176: static const char * tracefile;
1.85 wiz 177: static char * Check_Cwd_av(int, char **, int);
178: static void MainParseArgs(int, char **);
179: static int ReadMakefile(ClientData, ClientData);
180: static void usage(void);
1.1 cgd 181:
1.74 tv 182: static char curdir[MAXPATHLEN + 1]; /* startup directory */
183: static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
1.63 christos 184: char *progname; /* the program name */
1.1 cgd 185:
1.58 sommerfe 186: Boolean forceJobs = FALSE;
187:
1.63 christos 188: extern Lst parseIncPath;
189:
1.1 cgd 190: /*-
191: * MainParseArgs --
192: * Parse a given argument vector. Called from main() and from
193: * Main_ParseArgLine() when the .MAKEFLAGS target is used.
194: *
195: * XXX: Deal with command line overriding .MAKEFLAGS in makefile
196: *
197: * Results:
198: * None
199: *
200: * Side Effects:
201: * Various global and local flags will be set depending on the flags
202: * given
203: */
204: static void
1.85 wiz 205: MainParseArgs(int argc, char **argv)
1.1 cgd 206: {
1.47 hubertf 207: char *p;
208: int c;
1.98 ross 209: int arginc;
210: char *argvalue;
211: const char *getopt_def;
212: char *optscan;
1.101 ross 213: Boolean inOption, dashDash = FALSE;
1.97 chuck 214: char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */
1.1 cgd 215:
1.21 christos 216: #ifdef REMOTE
1.87 thorpej 217: # define OPTFLAGS "BD:I:J:L:NPST:V:WXd:ef:ij:km:nqrst"
1.13 cgd 218: #else
1.87 thorpej 219: # define OPTFLAGS "BD:I:J:NPST:V:WXd:ef:ij:km:nqrst"
1.13 cgd 220: #endif
1.98 ross 221: #undef optarg
222: #define optarg argvalue
223: /* Can't actually use getopt(3) because rescanning is not portable */
224:
225: getopt_def = OPTFLAGS;
226: rearg:
227: inOption = FALSE;
1.108 lukem 228: optscan = NULL;
1.98 ross 229: while(argc > 1) {
230: char *getopt_spec;
231: if(!inOption)
232: optscan = argv[1];
233: c = *optscan++;
234: arginc = 0;
235: if(inOption) {
236: if(c == '\0') {
237: ++argv;
238: --argc;
239: inOption = FALSE;
240: continue;
241: }
242: } else {
1.101 ross 243: if (c != '-' || dashDash)
1.98 ross 244: break;
245: inOption = TRUE;
246: c = *optscan++;
247: }
248: /* '-' found at some earlier point */
249: getopt_spec = strchr(getopt_def, c);
250: if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') {
251: /* -<something> found, and <something> should have an arg */
252: inOption = FALSE;
253: arginc = 1;
254: argvalue = optscan;
255: if(*argvalue == '\0') {
1.100 enami 256: if (argc < 3) {
257: (void)fprintf(stderr,
258: "%s: option requires "
259: "an argument -- %c\n",
260: progname, c);
261: usage();
262: }
1.98 ross 263: argvalue = argv[2];
264: arginc = 2;
265: }
1.108 lukem 266: } else {
267: argvalue = NULL;
1.98 ross 268: }
1.1 cgd 269: switch(c) {
1.98 ross 270: case '\0':
271: arginc = 1;
272: inOption = FALSE;
273: break;
1.92 sjg 274: case 'B':
275: compatMake = TRUE;
276: Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
277: break;
1.1 cgd 278: case 'D':
1.71 sjg 279: Var_Set(optarg, "1", VAR_GLOBAL, 0);
1.1 cgd 280: Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
281: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
282: break;
283: case 'I':
284: Parse_AddIncludeDir(optarg);
285: Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
286: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
287: break;
1.58 sommerfe 288: case 'J':
289: if (sscanf(optarg, "%d,%d", &job_pipe[0], &job_pipe[1]) != 2) {
1.65 cgd 290: /* backslash to avoid trigraph ??) */
1.63 christos 291: (void)fprintf(stderr,
1.65 cgd 292: "%s: internal error -- J option malformed (%s?\?)\n",
1.63 christos 293: progname, optarg);
1.58 sommerfe 294: usage();
295: }
296: if ((fcntl(job_pipe[0], F_GETFD, 0) < 0) ||
297: (fcntl(job_pipe[1], F_GETFD, 0) < 0)) {
1.61 sommerfe 298: #if 0
1.58 sommerfe 299: (void)fprintf(stderr,
1.63 christos 300: "%s: warning -- J descriptors were closed!\n",
301: progname);
1.61 sommerfe 302: #endif
1.58 sommerfe 303: job_pipe[0] = -1;
304: job_pipe[1] = -1;
1.61 sommerfe 305: compatMake = TRUE;
1.58 sommerfe 306: } else {
307: Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
308: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
309: jobServer = TRUE;
310: }
311: break;
1.21 christos 312: #ifdef REMOTE
1.1 cgd 313: case 'L':
1.47 hubertf 314: maxLocal = strtol(optarg, &p, 0);
315: if (*p != '\0' || maxLocal < 1) {
1.112 christos 316: (void)fprintf(stderr, "%s: illegal argument to -L -- must be positive integer!\n",
1.63 christos 317: progname);
318: exit(1);
1.46 hubertf 319: }
1.1 cgd 320: Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
321: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
322: break;
1.21 christos 323: #endif
1.61 sommerfe 324: case 'N':
325: noExecute = TRUE;
326: noRecursiveExecute = TRUE;
327: Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL);
328: break;
1.1 cgd 329: case 'P':
330: usePipes = FALSE;
331: Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
332: break;
333: case 'S':
334: keepgoing = FALSE;
335: Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
336: break;
1.58 sommerfe 337: case 'T':
1.59 sommerfe 338: tracefile = estrdup(optarg);
1.58 sommerfe 339: Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL);
340: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
341: break;
1.92 sjg 342: case 'V':
343: printVars = TRUE;
344: (void)Lst_AtEnd(variables, (ClientData)optarg);
345: Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
346: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
347: break;
1.63 christos 348: case 'W':
349: parseWarnFatal = TRUE;
1.87 thorpej 350: break;
351: case 'X':
352: varNoExportEnv = TRUE;
353: Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL);
1.63 christos 354: break;
1.1 cgd 355: case 'd': {
356: char *modules = optarg;
357:
358: for (; *modules; ++modules)
359: switch (*modules) {
360: case 'A':
361: debug = ~0;
362: break;
363: case 'a':
364: debug |= DEBUG_ARCH;
365: break;
366: case 'c':
367: debug |= DEBUG_COND;
368: break;
369: case 'd':
370: debug |= DEBUG_DIR;
1.93 jmmv 371: break;
372: case 'e':
373: debug |= DEBUG_ERROR;
1.1 cgd 374: break;
1.13 cgd 375: case 'f':
376: debug |= DEBUG_FOR;
377: break;
1.1 cgd 378: case 'g':
379: if (modules[1] == '1') {
380: debug |= DEBUG_GRAPH1;
381: ++modules;
382: }
383: else if (modules[1] == '2') {
384: debug |= DEBUG_GRAPH2;
385: ++modules;
386: }
1.94 dsl 387: else if (modules[1] == '3') {
388: debug |= DEBUG_GRAPH3;
389: ++modules;
390: }
1.1 cgd 391: break;
392: case 'j':
393: debug |= DEBUG_JOB;
394: break;
395: case 'm':
396: debug |= DEBUG_MAKE;
397: break;
1.109 jmc 398: case 'n':
399: debug |= DEBUG_SCRIPT;
400: break;
1.1 cgd 401: case 's':
402: debug |= DEBUG_SUFF;
403: break;
404: case 't':
405: debug |= DEBUG_TARG;
406: break;
407: case 'v':
408: debug |= DEBUG_VAR;
409: break;
1.67 sjg 410: case 'x':
411: debug |= DEBUG_SHELL;
412: break;
1.1 cgd 413: default:
414: (void)fprintf(stderr,
1.63 christos 415: "%s: illegal argument to d option -- %c\n",
416: progname, *modules);
1.1 cgd 417: usage();
418: }
419: Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
420: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
421: break;
422: }
423: case 'e':
424: checkEnvFirst = TRUE;
425: Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
426: break;
427: case 'f':
428: (void)Lst_AtEnd(makefiles, (ClientData)optarg);
429: break;
430: case 'i':
431: ignoreErrors = TRUE;
432: Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
433: break;
434: case 'j':
1.22 christos 435: forceJobs = TRUE;
1.47 hubertf 436: maxJobs = strtol(optarg, &p, 0);
437: if (*p != '\0' || maxJobs < 1) {
1.112 christos 438: (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n",
1.63 christos 439: progname);
1.46 hubertf 440: exit(1);
441: }
1.21 christos 442: #ifndef REMOTE
443: maxLocal = maxJobs;
444: #endif
1.9 jtc 445: Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
1.1 cgd 446: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
447: break;
448: case 'k':
449: keepgoing = TRUE;
450: Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
451: break;
1.25 christos 452: case 'm':
1.97 chuck 453: /* look for magic parent directory search string */
454: if (strncmp(".../", optarg, 4) == 0) {
455: if (!Dir_FindHereOrAbove(curdir, optarg+4,
456: found_path, sizeof(found_path)))
457: break; /* nothing doing */
1.112 christos 458: (void)Dir_AddDir(sysIncPath, found_path);
1.97 chuck 459:
460: } else {
1.112 christos 461: (void)Dir_AddDir(sysIncPath, optarg);
1.97 chuck 462: }
1.25 christos 463: Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
464: Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
465: break;
1.1 cgd 466: case 'n':
467: noExecute = TRUE;
468: Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
469: break;
470: case 'q':
471: queryFlag = TRUE;
472: /* Kind of nonsensical, wot? */
473: Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
474: break;
475: case 'r':
476: noBuiltins = TRUE;
477: Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
478: break;
479: case 's':
480: beSilent = TRUE;
481: Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
482: break;
483: case 't':
484: touchFlag = TRUE;
485: Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
486: break;
1.101 ross 487: case '-':
488: dashDash = TRUE;
489: break;
1.1 cgd 490: default:
491: case '?':
492: usage();
493: }
1.98 ross 494: argv += arginc;
495: argc -= arginc;
1.1 cgd 496: }
497:
498: oldVars = TRUE;
499:
500: /*
501: * See if the rest of the arguments are variable assignments and
502: * perform them if so. Else take them to be targets and stuff them
503: * on the end of the "create" list.
504: */
1.98 ross 505: for (; argc > 1; ++argv, --argc)
506: if (Parse_IsVar(argv[1])) {
507: Parse_DoVar(argv[1], VAR_CMD);
1.67 sjg 508: } else {
1.98 ross 509: if (!*argv[1])
1.1 cgd 510: Punt("illegal (null) argument.");
1.101 ross 511: if (*argv[1] == '-' && !dashDash)
1.1 cgd 512: goto rearg;
1.98 ross 513: (void)Lst_AtEnd(create, (ClientData)estrdup(argv[1]));
1.1 cgd 514: }
515: }
516:
517: /*-
518: * Main_ParseArgLine --
519: * Used by the parse module when a .MFLAGS or .MAKEFLAGS target
520: * is encountered and by main() when reading the .MAKEFLAGS envariable.
521: * Takes a line of arguments and breaks it into its
522: * component words and passes those words and the number of them to the
523: * MainParseArgs function.
524: * The line should have all its leading whitespace removed.
525: *
1.85 wiz 526: * Input:
527: * line Line to fracture
528: *
1.1 cgd 529: * Results:
530: * None
531: *
532: * Side Effects:
533: * Only those that come from the various arguments.
534: */
535: void
1.85 wiz 536: Main_ParseArgLine(char *line)
1.1 cgd 537: {
538: char **argv; /* Manufactured argument vector */
539: int argc; /* Number of arguments in argv */
1.40 christos 540: char *args; /* Space used by the args */
541: char *buf, *p1;
542: char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1);
1.48 christos 543: size_t len;
1.1 cgd 544:
545: if (line == NULL)
546: return;
1.13 cgd 547: for (; *line == ' '; ++line)
548: continue;
1.1 cgd 549: if (!*line)
550: return;
551:
1.48 christos 552: buf = emalloc(len = strlen(line) + strlen(argv0) + 2);
553: (void)snprintf(buf, len, "%s %s", argv0, line);
1.40 christos 554: if (p1)
555: free(p1);
556:
1.41 christos 557: argv = brk_string(buf, &argc, TRUE, &args);
1.45 itohy 558: free(buf);
1.1 cgd 559: MainParseArgs(argc, argv);
1.40 christos 560:
561: free(args);
562: free(argv);
1.1 cgd 563: }
564:
1.74 tv 565: Boolean
1.85 wiz 566: Main_SetObjdir(const char *path)
1.31 christos 567: {
568: struct stat sb;
1.74 tv 569: char *p = NULL;
570: char buf[MAXPATHLEN + 1];
1.76 tv 571: Boolean rc = FALSE;
1.31 christos 572:
1.74 tv 573: /* expand variable substitutions */
1.51 sjg 574: if (strchr(path, '$') != 0) {
1.74 tv 575: snprintf(buf, MAXPATHLEN, "%s", path);
576: path = p = Var_Subst(NULL, buf, VAR_GLOBAL, 0);
1.51 sjg 577: }
1.74 tv 578:
579: if (path[0] != '/') {
580: snprintf(buf, MAXPATHLEN, "%s/%s", curdir, path);
581: path = buf;
582: }
583:
584: /* look for the directory and try to chdir there */
1.31 christos 585: if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
586: if (chdir(path)) {
587: (void)fprintf(stderr, "make warning: %s: %s.\n",
588: path, strerror(errno));
1.74 tv 589: } else {
590: strncpy(objdir, path, MAXPATHLEN);
591: Var_Set(".OBJDIR", objdir, VAR_GLOBAL, 0);
592: setenv("PWD", objdir, 1);
1.79 tv 593: Dir_InitDot();
1.74 tv 594: rc = TRUE;
1.31 christos 595: }
596: }
597:
1.74 tv 598: if (p)
599: free(p);
600: return rc;
1.31 christos 601: }
602:
603:
1.1 cgd 604: /*-
605: * main --
606: * The main function, for obvious reasons. Initializes variables
607: * and a few modules, then parses the arguments give it in the
608: * environment and on the command line. Reads the system makefile
609: * followed by either Makefile, makefile or the file given by the
610: * -f argument. Sets the .MAKEFLAGS PMake variable based on all the
611: * flags it has received by then uses either the Make or the Compat
612: * module to create the initial list of targets.
613: *
614: * Results:
615: * If -q was given, exits -1 if anything was out-of-date. Else it exits
616: * 0.
617: *
618: * Side Effects:
619: * The program exits when done. Targets are created. etc. etc. etc.
620: */
1.13 cgd 621: int
1.85 wiz 622: main(int argc, char **argv)
1.1 cgd 623: {
624: Lst targs; /* target nodes to create -- passed to Make_Init */
1.13 cgd 625: Boolean outOfDate = TRUE; /* FALSE if all targets up to date */
1.77 tv 626: struct stat sb, sa;
627: char *p1, *path, *pwd;
1.74 tv 628: char mdpath[MAXPATHLEN];
1.18 christos 629: char *machine = getenv("MACHINE");
1.89 christos 630: const char *machine_arch = getenv("MACHINE_ARCH");
1.55 sjg 631: char *syspath = getenv("MAKESYSPATH");
1.25 christos 632: Lst sysMkPath; /* Path of sys.mk */
633: char *cp = NULL, *start;
634: /* avoid faults on read-only strings */
1.55 sjg 635: static char defsyspath[] = _PATH_DEFSYSPATH;
1.97 chuck 636: char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */
1.107 sjg 637: struct timeval rightnow; /* to initialize random seed */
638:
639: /*
640: * Set the seed to produce a different random sequences
641: * on each program execution.
642: */
643: gettimeofday(&rightnow, NULL);
644: srandom(rightnow.tv_sec + rightnow.tv_usec);
1.55 sjg 645:
1.53 christos 646: if ((progname = strrchr(argv[0], '/')) != NULL)
647: progname++;
648: else
649: progname = argv[0];
1.21 christos 650: #ifdef RLIMIT_NOFILE
651: /*
652: * get rid of resource limit on file descriptors
653: */
654: {
655: struct rlimit rl;
656: if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
657: rl.rlim_cur != rl.rlim_max) {
658: rl.rlim_cur = rl.rlim_max;
1.112 christos 659: (void)setrlimit(RLIMIT_NOFILE, &rl);
1.21 christos 660: }
661: }
662: #endif
1.13 cgd 663: /*
664: * Find where we are and take care of PWD for the automounter...
665: * All this code is so that we know where we are when we start up
666: * on a different machine with pmake.
667: */
1.16 mycroft 668: if (getcwd(curdir, MAXPATHLEN) == NULL) {
1.63 christos 669: (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
1.13 cgd 670: exit(2);
671: }
672:
1.77 tv 673: if (stat(curdir, &sa) == -1) {
1.63 christos 674: (void)fprintf(stderr, "%s: %s: %s.\n",
675: progname, curdir, strerror(errno));
1.13 cgd 676: exit(2);
1.77 tv 677: }
678:
679: /*
680: * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
681: * since the value of curdir can very depending on how we got
682: * here. Ie sitting at a shell prompt (shell that provides $PWD)
683: * or via subdir.mk in which case its likely a shell which does
684: * not provide it.
685: * So, to stop it breaking this case only, we ignore PWD if
686: * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform.
687: */
688: if ((pwd = getenv("PWD")) != NULL && getenv("MAKEOBJDIRPREFIX") == NULL) {
689: const char *makeobjdir = getenv("MAKEOBJDIR");
690:
691: if (makeobjdir == NULL || !strchr(makeobjdir, '$')) {
692: if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
693: sa.st_dev == sb.st_dev)
1.112 christos 694: (void)strncpy(curdir, pwd, MAXPATHLEN);
1.77 tv 695: }
1.13 cgd 696: }
697:
1.17 gwr 698: /*
699: * Get the name of this type of MACHINE from utsname
700: * so we can share an executable for similar machines.
701: * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
702: *
1.33 christos 703: * Note that both MACHINE and MACHINE_ARCH are decided at
704: * run-time.
1.17 gwr 705: */
1.34 gwr 706: if (!machine) {
1.102 ross 707: #ifdef MAKE_NATIVE
1.31 christos 708: struct utsname utsname;
709:
1.23 christos 710: if (uname(&utsname) == -1) {
1.63 christos 711: (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
712: strerror(errno));
713: exit(2);
1.18 christos 714: }
715: machine = utsname.machine;
1.26 christos 716: #else
1.81 tv 717: #ifdef MAKE_MACHINE
1.80 thorpej 718: machine = MAKE_MACHINE;
1.81 tv 719: #else
720: machine = "unknown";
721: #endif
1.26 christos 722: #endif
1.17 gwr 723: }
1.1 cgd 724:
1.33 christos 725: if (!machine_arch) {
726: #ifndef MACHINE_ARCH
1.80 thorpej 727: #ifdef MAKE_MACHINE_ARCH
728: machine_arch = MAKE_MACHINE_ARCH;
1.43 wsanchez 729: #else
1.81 tv 730: machine_arch = "unknown";
1.43 wsanchez 731: #endif
1.33 christos 732: #else
733: machine_arch = MACHINE_ARCH;
734: #endif
735: }
736:
1.1 cgd 737: /*
1.51 sjg 738: * Just in case MAKEOBJDIR wants us to do something tricky.
739: */
740: Var_Init(); /* Initialize the lists of variables for
741: * parsing arguments */
1.71 sjg 742: Var_Set(".CURDIR", curdir, VAR_GLOBAL, 0);
743: Var_Set("MACHINE", machine, VAR_GLOBAL, 0);
744: Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL, 0);
1.67 sjg 745: #ifdef MAKE_VERSION
1.71 sjg 746: Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL, 0);
1.67 sjg 747: #endif
1.71 sjg 748: Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */
1.51 sjg 749:
750: /*
1.74 tv 751: * Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that,
752: * MAKEOBJDIR is set in the environment, try only that value
753: * and fall back to .CURDIR if it does not exist.
1.111 lukem 754: *
755: * Otherwise, try _PATH_OBJDIR.MACHINE, _PATH_OBJDIR, and
756: * finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none
757: * of these paths exist, just use .CURDIR.
1.74 tv 758: */
1.79 tv 759: Dir_Init(curdir);
1.112 christos 760: (void)Main_SetObjdir(curdir);
1.79 tv 761:
1.74 tv 762: if ((path = getenv("MAKEOBJDIRPREFIX")) != NULL) {
1.112 christos 763: (void)snprintf(mdpath, MAXPATHLEN, "%s%s", path, curdir);
764: (void)Main_SetObjdir(mdpath);
1.74 tv 765: } else if ((path = getenv("MAKEOBJDIR")) != NULL) {
1.112 christos 766: (void)Main_SetObjdir(path);
1.111 lukem 767: } else {
1.112 christos 768: (void)snprintf(mdpath, MAXPATHLEN, "%s.%s", _PATH_OBJDIR, machine);
1.111 lukem 769: if (!Main_SetObjdir(mdpath) && !Main_SetObjdir(_PATH_OBJDIR)) {
1.112 christos 770: (void)snprintf(mdpath, MAXPATHLEN, "%s%s",
1.111 lukem 771: _PATH_OBJDIRPREFIX, curdir);
1.112 christos 772: (void)Main_SetObjdir(mdpath);
1.111 lukem 773: }
1.4 cgd 774: }
1.13 cgd 775:
1.1 cgd 776: create = Lst_Init(FALSE);
777: makefiles = Lst_Init(FALSE);
1.31 christos 778: printVars = FALSE;
779: variables = Lst_Init(FALSE);
1.1 cgd 780: beSilent = FALSE; /* Print commands as executed */
781: ignoreErrors = FALSE; /* Pay attention to non-zero returns */
782: noExecute = FALSE; /* Execute all commands */
1.61 sommerfe 783: noRecursiveExecute = FALSE; /* Execute all .MAKE targets */
1.1 cgd 784: keepgoing = FALSE; /* Stop on error */
785: allPrecious = FALSE; /* Remove targets when interrupted */
786: queryFlag = FALSE; /* This is not just a check-run */
787: noBuiltins = FALSE; /* Read the built-in rules */
788: touchFlag = FALSE; /* Actually update targets */
789: usePipes = TRUE; /* Catch child output in pipes */
790: debug = 0; /* No debug verbosity, please. */
791: jobsRunning = FALSE;
792:
1.21 christos 793: maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */
794: #ifdef REMOTE
1.1 cgd 795: maxJobs = DEFMAXJOBS; /* Set default max concurrency */
1.13 cgd 796: #else
1.21 christos 797: maxJobs = maxLocal;
1.13 cgd 798: #endif
1.21 christos 799: compatMake = FALSE; /* No compat mode */
1.31 christos 800:
1.13 cgd 801:
1.1 cgd 802: /*
803: * Initialize the parsing, directory and variable modules to prepare
804: * for the reading of inclusion paths and variable settings on the
805: * command line
806: */
1.36 gwr 807:
808: /*
1.1 cgd 809: * Initialize various variables.
810: * MAKE also gets this name, for compatibility
811: * .MAKEFLAGS gets set to the empty string just in case.
812: * MFLAGS also gets initialized empty, for compatibility.
813: */
1.79 tv 814: Parse_Init();
1.71 sjg 815: Var_Set("MAKE", argv[0], VAR_GLOBAL, 0);
816: Var_Set(".MAKE", argv[0], VAR_GLOBAL, 0);
817: Var_Set(MAKEFLAGS, "", VAR_GLOBAL, 0);
818: Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL, 0);
819: Var_Set("MFLAGS", "", VAR_GLOBAL, 0);
1.78 tv 820: Var_Set(".ALLTARGETS", "", VAR_GLOBAL, 0);
1.1 cgd 821:
822: /*
823: * First snag any flags out of the MAKE environment variable.
824: * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
825: * in a different format).
826: */
827: #ifdef POSIX
828: Main_ParseArgLine(getenv("MAKEFLAGS"));
829: #else
830: Main_ParseArgLine(getenv("MAKE"));
831: #endif
1.31 christos 832:
1.1 cgd 833: MainParseArgs(argc, argv);
834:
835: /*
1.58 sommerfe 836: * Be compatible if user did not specify -j and did not explicitly
837: * turned compatibility on
838: */
839: if (!compatMake && !forceJobs) {
840: compatMake = TRUE;
841: }
842:
843: /*
1.1 cgd 844: * Initialize archive, target and suffix modules in preparation for
845: * parsing the makefile(s)
846: */
847: Arch_Init();
848: Targ_Init();
849: Suff_Init();
1.58 sommerfe 850: Trace_Init(tracefile);
1.1 cgd 851:
852: DEFAULT = NILGNODE;
853: (void)time(&now);
854:
1.58 sommerfe 855: Trace_Log(MAKESTART, NULL);
856:
1.1 cgd 857: /*
858: * Set up the .TARGETS variable to contain the list of targets to be
859: * created. If none specified, make the variable empty -- the parser
860: * will fill the thing in with the default or .MAIN target.
861: */
862: if (!Lst_IsEmpty(create)) {
863: LstNode ln;
864:
865: for (ln = Lst_First(create); ln != NILLNODE;
866: ln = Lst_Succ(ln)) {
867: char *name = (char *)Lst_Datum(ln);
868:
869: Var_Append(".TARGETS", name, VAR_GLOBAL);
870: }
871: } else
1.71 sjg 872: Var_Set(".TARGETS", "", VAR_GLOBAL, 0);
1.1 cgd 873:
1.25 christos 874:
1.1 cgd 875: /*
1.25 christos 876: * If no user-supplied system path was given (through the -m option)
877: * add the directories from the DEFSYSPATH (more than one may be given
878: * as dir1:...:dirn) to the system include path.
1.1 cgd 879: */
1.73 tv 880: if (syspath == NULL || *syspath == '\0')
881: syspath = defsyspath;
882: else
883: syspath = strdup(syspath);
884:
885: for (start = syspath; *start != '\0'; start = cp) {
886: for (cp = start; *cp != '\0' && *cp != ':'; cp++)
887: continue;
1.97 chuck 888: if (*cp == ':') {
889: *cp++ = '\0';
890: }
891: /* look for magic parent directory search string */
892: if (strncmp(".../", start, 4) != 0) {
1.112 christos 893: (void)Dir_AddDir(defIncPath, start);
1.73 tv 894: } else {
1.97 chuck 895: if (Dir_FindHereOrAbove(curdir, start+4,
896: found_path, sizeof(found_path))) {
1.112 christos 897: (void)Dir_AddDir(defIncPath, found_path);
1.97 chuck 898: }
1.25 christos 899: }
900: }
1.73 tv 901: if (syspath != defsyspath)
902: free(syspath);
1.25 christos 903:
904: /*
905: * Read in the built-in rules first, followed by the specified
1.115 christos 906: * makefile, if it was (makefile != NULL), or the default
1.99 fair 907: * makefile and Makefile, in that order, if it wasn't.
1.25 christos 908: */
909: if (!noBuiltins) {
910: LstNode ln;
911:
1.106 christos 912: sysMkPath = Lst_Init(FALSE);
1.73 tv 913: Dir_Expand(_PATH_DEFSYSMK,
914: Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath,
915: sysMkPath);
1.25 christos 916: if (Lst_IsEmpty(sysMkPath))
1.63 christos 917: Fatal("%s: no system rules (%s).", progname,
918: _PATH_DEFSYSMK);
1.25 christos 919: ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
920: if (ln != NILLNODE)
1.63 christos 921: Fatal("%s: cannot open %s.", progname,
922: (char *)Lst_Datum(ln));
1.25 christos 923: }
1.1 cgd 924:
925: if (!Lst_IsEmpty(makefiles)) {
926: LstNode ln;
927:
928: ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
929: if (ln != NILLNODE)
1.63 christos 930: Fatal("%s: cannot open %s.", progname,
931: (char *)Lst_Datum(ln));
1.89 christos 932: } else if (!ReadMakefile(UNCONST("makefile"), NULL))
933: (void)ReadMakefile(UNCONST("Makefile"), NULL);
1.1 cgd 934:
1.89 christos 935: (void)ReadMakefile(UNCONST(".depend"), NULL);
1.1 cgd 936:
1.14 jtc 937: Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
938: if (p1)
939: free(p1);
1.1 cgd 940:
1.58 sommerfe 941: if (!jobServer && !compatMake)
942: Job_ServerStart(maxJobs);
943: if (DEBUG(JOB))
944: printf("job_pipe %d %d, maxjobs %d maxlocal %d compat %d\n", job_pipe[0], job_pipe[1], maxJobs,
945: maxLocal, compatMake);
946:
1.73 tv 947: Main_ExportMAKEFLAGS(TRUE); /* initial export */
1.1 cgd 948:
1.54 sjg 949: Check_Cwd_av(0, NULL, 0); /* initialize it */
950:
951:
1.1 cgd 952: /*
953: * For compatibility, look at the directories in the VPATH variable
954: * and add them to the search path, if the variable is defined. The
955: * variable's value is in the same format as the PATH envariable, i.e.
956: * <directory>:<directory>:<directory>...
957: */
958: if (Var_Exists("VPATH", VAR_CMD)) {
1.82 reinoud 959: char *vpath, savec;
1.1 cgd 960: /*
961: * GCC stores string constants in read-only memory, but
962: * Var_Subst will want to write this thing, so store it
963: * in an array
964: */
965: static char VPATH[] = "${VPATH}";
966:
1.13 cgd 967: vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
1.1 cgd 968: path = vpath;
969: do {
970: /* skip to end of directory */
1.13 cgd 971: for (cp = path; *cp != ':' && *cp != '\0'; cp++)
972: continue;
1.1 cgd 973: /* Save terminator character so know when to stop */
974: savec = *cp;
975: *cp = '\0';
976: /* Add directory to search path */
1.112 christos 977: (void)Dir_AddDir(dirSearchPath, path);
1.1 cgd 978: *cp = savec;
979: path = cp + 1;
980: } while (savec == ':');
1.114 christos 981: free(vpath);
1.1 cgd 982: }
983:
984: /*
985: * Now that all search paths have been read for suffixes et al, it's
986: * time to add the default search path to their lists...
987: */
988: Suff_DoPaths();
1.50 mycroft 989:
990: /*
991: * Propagate attributes through :: dependency lists.
992: */
993: Targ_Propagate();
1.1 cgd 994:
995: /* print the initial graph, if the user requested it */
996: if (DEBUG(GRAPH1))
997: Targ_PrintGraph(1);
998:
1.31 christos 999: /* print the values of any variables requested by the user */
1000: if (printVars) {
1001: LstNode ln;
1002:
1003: for (ln = Lst_First(variables); ln != NILLNODE;
1004: ln = Lst_Succ(ln)) {
1.92 sjg 1005: char *var = (char *)Lst_Datum(ln);
1006: char *value;
1007:
1008: if (strchr(var, '$')) {
1009: value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0);
1010: } else {
1011: value = Var_Value(var, VAR_GLOBAL, &p1);
1012: }
1.31 christos 1013: printf("%s\n", value ? value : "");
1014: if (p1)
1015: free(p1);
1016: }
1017: }
1018:
1.1 cgd 1019: /*
1020: * Have now read the entire graph and need to make a list of targets
1021: * to create. If none was given on the command line, we consult the
1022: * parsing module to find the main target(s) to create.
1023: */
1024: if (Lst_IsEmpty(create))
1025: targs = Parse_MainName();
1026: else
1027: targs = Targ_FindList(create, TARG_CREATE);
1028:
1.31 christos 1029: if (!compatMake && !printVars) {
1.1 cgd 1030: /*
1031: * Initialize job module before traversing the graph, now that
1032: * any .BEGIN and .END targets have been read. This is done
1033: * only if the -q flag wasn't given (to prevent the .BEGIN from
1034: * being executed should it exist).
1035: */
1036: if (!queryFlag) {
1037: if (maxLocal == -1)
1038: maxLocal = maxJobs;
1039: Job_Init(maxJobs, maxLocal);
1040: jobsRunning = TRUE;
1041: }
1042:
1043: /* Traverse the graph, checking on all the targets */
1044: outOfDate = Make_Run(targs);
1.31 christos 1045: } else if (!printVars) {
1.1 cgd 1046: /*
1047: * Compat_Init will take care of creating all the targets as
1048: * well as initializing the module.
1049: */
1050: Compat_Run(targs);
1.31 christos 1051: }
1052:
1.49 mycroft 1053: #ifdef CLEANUP
1.14 jtc 1054: Lst_Destroy(targs, NOFREE);
1.31 christos 1055: Lst_Destroy(variables, NOFREE);
1.14 jtc 1056: Lst_Destroy(makefiles, NOFREE);
1.116 christos 1057: Lst_Destroy(create, (FreeProc *)free);
1.49 mycroft 1058: #endif
1.14 jtc 1059:
1.1 cgd 1060: /* print the graph now it's been processed if the user requested it */
1061: if (DEBUG(GRAPH2))
1062: Targ_PrintGraph(2);
1063:
1.58 sommerfe 1064: Trace_Log(MAKEEND, 0);
1065:
1.14 jtc 1066: Suff_End();
1067: Targ_End();
1068: Arch_End();
1069: Var_End();
1070: Parse_End();
1071: Dir_End();
1.40 christos 1072: Job_End();
1.58 sommerfe 1073: Trace_End();
1.14 jtc 1074:
1.1 cgd 1075: if (queryFlag && outOfDate)
1.13 cgd 1076: return(1);
1.1 cgd 1077: else
1.13 cgd 1078: return(0);
1.1 cgd 1079: }
1080:
1081: /*-
1082: * ReadMakefile --
1083: * Open and parse the given makefile.
1084: *
1085: * Results:
1086: * TRUE if ok. FALSE if couldn't open file.
1087: *
1088: * Side Effects:
1089: * lots
1090: */
1091: static Boolean
1.104 jmc 1092: ReadMakefile(ClientData p, ClientData q __unused)
1.1 cgd 1093: {
1.31 christos 1094: char *fname = p; /* makefile to read */
1.1 cgd 1095: FILE *stream;
1.48 christos 1096: size_t len = MAXPATHLEN;
1097: char *name, *path = emalloc(len);
1.67 sjg 1098: int setMAKEFILE;
1.1 cgd 1099:
1100: if (!strcmp(fname, "-")) {
1101: Parse_File("(stdin)", stdin);
1.71 sjg 1102: Var_Set("MAKEFILE", "", VAR_GLOBAL, 0);
1.1 cgd 1103: } else {
1.67 sjg 1104: setMAKEFILE = strcmp(fname, ".depend");
1105:
1.1 cgd 1106: /* if we've chdir'd, rebuild the path name */
1.74 tv 1107: if (strcmp(curdir, objdir) && *fname != '/') {
1.48 christos 1108: size_t plen = strlen(curdir) + strlen(fname) + 2;
1109: if (len < plen)
1110: path = erealloc(path, len = 2 * plen);
1111:
1112: (void)snprintf(path, len, "%s/%s", curdir, fname);
1.13 cgd 1113: if ((stream = fopen(path, "r")) != NULL) {
1.1 cgd 1114: fname = path;
1115: goto found;
1116: }
1.95 jmc 1117:
1118: /* If curdir failed, try objdir (ala .depend) */
1119: plen = strlen(objdir) + strlen(fname) + 2;
1120: if (len < plen)
1121: path = erealloc(path, len = 2 * plen);
1122: (void)snprintf(path, len, "%s/%s", objdir, fname);
1123: if ((stream = fopen(path, "r")) != NULL) {
1124: fname = path;
1125: goto found;
1126: }
1.62 sjg 1127: } else if ((stream = fopen(fname, "r")) != NULL)
1128: goto found;
1.1 cgd 1129: /* look in -I and system include directories. */
1130: name = Dir_FindFile(fname, parseIncPath);
1131: if (!name)
1.73 tv 1132: name = Dir_FindFile(fname,
1133: Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
1.48 christos 1134: if (!name || !(stream = fopen(name, "r"))) {
1135: free(path);
1.1 cgd 1136: return(FALSE);
1.48 christos 1137: }
1.1 cgd 1138: fname = name;
1139: /*
1140: * set the MAKEFILE variable desired by System V fans -- the
1141: * placement of the setting here means it gets set to the last
1142: * makefile specified, as it is set by SysV make.
1143: */
1.67 sjg 1144: found:
1145: if (setMAKEFILE)
1.71 sjg 1146: Var_Set("MAKEFILE", fname, VAR_GLOBAL, 0);
1.1 cgd 1147: Parse_File(fname, stream);
1148: (void)fclose(stream);
1149: }
1.48 christos 1150: free(path);
1.1 cgd 1151: return(TRUE);
1.54 sjg 1152: }
1153:
1154:
1155: /*
1156: * If MAKEOBJDIRPREFIX is in use, make ends up not in .CURDIR
1157: * in situations that would not arrise with ./obj (links or not).
1158: * This tends to break things like:
1159: *
1160: * build:
1161: * ${MAKE} includes
1162: *
1163: * This function spots when ${.MAKE:T} or ${.MAKE} is a command (as
1164: * opposed to an argument) in a command line and if so returns
1165: * ${.CURDIR} so caller can chdir() so that the assumptions made by
1166: * the Makefile hold true.
1167: *
1168: * If ${.MAKE} does not contain any '/', then ${.MAKE:T} is skipped.
1169: *
1170: * The chdir() only happens in the child process, and does nothing if
1171: * MAKEOBJDIRPREFIX and MAKEOBJDIR are not in the environment so it
1172: * should not break anything. Also if NOCHECKMAKECHDIR is set we
1173: * do nothing - to ensure historic semantics can be retained.
1174: */
1175: static int Check_Cwd_Off = 0;
1176:
1177: static char *
1.85 wiz 1178: Check_Cwd_av(int ac, char **av, int copy)
1.54 sjg 1179: {
1180: static char *make[4];
1.82 reinoud 1181: static char *cur_dir = NULL;
1.89 christos 1182: char **mp;
1183: char *cp;
1.54 sjg 1184: int is_cmd, next_cmd;
1185: int i;
1186: int n;
1187:
1188: if (Check_Cwd_Off)
1189: return NULL;
1190:
1191: if (make[0] == NULL) {
1192: if (Var_Exists("NOCHECKMAKECHDIR", VAR_GLOBAL)) {
1193: Check_Cwd_Off = 1;
1194: return NULL;
1195: }
1196:
1197: make[1] = Var_Value(".MAKE", VAR_GLOBAL, &cp);
1198: if ((make[0] = strrchr(make[1], '/')) == NULL) {
1199: make[0] = make[1];
1200: make[1] = NULL;
1201: } else
1202: ++make[0];
1203: make[2] = NULL;
1.82 reinoud 1204: cur_dir = Var_Value(".CURDIR", VAR_GLOBAL, &cp);
1.54 sjg 1205: }
1206: if (ac == 0 || av == NULL)
1207: return NULL; /* initialization only */
1208:
1209: if (getenv("MAKEOBJDIR") == NULL &&
1210: getenv("MAKEOBJDIRPREFIX") == NULL)
1211: return NULL;
1212:
1213:
1214: next_cmd = 1;
1215: for (i = 0; i < ac; ++i) {
1216: is_cmd = next_cmd;
1217:
1218: n = strlen(av[i]);
1219: cp = &(av[i])[n - 1];
1220: if (strspn(av[i], "|&;") == n) {
1221: next_cmd = 1;
1222: continue;
1223: } else if (*cp == ';' || *cp == '&' || *cp == '|' || *cp == ')') {
1224: next_cmd = 1;
1225: if (copy) {
1226: do {
1227: *cp-- = '\0';
1228: } while (*cp == ';' || *cp == '&' || *cp == '|' ||
1229: *cp == ')' || *cp == '}') ;
1230: } else {
1231: /*
1232: * XXX this should not happen.
1233: */
1234: fprintf(stderr, "WARNING: raw arg ends in shell meta '%s'\n",
1235: av[i]);
1236: }
1237: } else
1238: next_cmd = 0;
1239:
1240: cp = av[i];
1241: if (*cp == ';' || *cp == '&' || *cp == '|')
1242: is_cmd = 1;
1243:
1244: #ifdef check_cwd_debug
1245: fprintf(stderr, "av[%d] == %s '%s'",
1246: i, (is_cmd) ? "cmd" : "arg", av[i]);
1247: #endif
1248: if (is_cmd != 0) {
1.57 sjg 1249: if (*cp == '(' || *cp == '{' ||
1250: *cp == ';' || *cp == '&' || *cp == '|') {
1251: do {
1252: ++cp;
1253: } while (*cp == '(' || *cp == '{' ||
1254: *cp == ';' || *cp == '&' || *cp == '|');
1255: if (*cp == '\0') {
1256: next_cmd = 1;
1257: continue;
1258: }
1259: }
1.54 sjg 1260: if (strcmp(cp, "cd") == 0 || strcmp(cp, "chdir") == 0) {
1261: #ifdef check_cwd_debug
1262: fprintf(stderr, " == cd, done.\n");
1263: #endif
1264: return NULL;
1265: }
1266: for (mp = make; *mp != NULL; ++mp) {
1267: n = strlen(*mp);
1268: if (strcmp(cp, *mp) == 0) {
1269: #ifdef check_cwd_debug
1270: fprintf(stderr, " %s == '%s', chdir(%s)\n",
1.82 reinoud 1271: cp, *mp, cur_dir);
1.54 sjg 1272: #endif
1.82 reinoud 1273: return cur_dir;
1.54 sjg 1274: }
1275: }
1276: }
1277: #ifdef check_cwd_debug
1278: fprintf(stderr, "\n");
1279: #endif
1280: }
1281: return NULL;
1282: }
1283:
1284: char *
1.89 christos 1285: Check_Cwd_Cmd(const char *cmd)
1.54 sjg 1286: {
1.89 christos 1287: char *cp, *bp;
1288: char **av;
1.54 sjg 1289: int ac;
1290:
1291: if (Check_Cwd_Off)
1292: return NULL;
1293:
1294: if (cmd) {
1295: av = brk_string(cmd, &ac, TRUE, &bp);
1296: #ifdef check_cwd_debug
1297: fprintf(stderr, "splitting: '%s' -> %d words\n",
1298: cmd, ac);
1299: #endif
1300: } else {
1301: ac = 0;
1302: av = NULL;
1303: bp = NULL;
1304: }
1305: cp = Check_Cwd_av(ac, av, 1);
1306: if (bp) {
1307: free(av);
1308: free(bp);
1309: }
1310: return cp;
1311: }
1312:
1313: void
1.89 christos 1314: Check_Cwd(const char **argv)
1.54 sjg 1315: {
1316: char *cp;
1317: int ac;
1318:
1319: if (Check_Cwd_Off)
1320: return;
1321:
1322: for (ac = 0; argv[ac] != NULL; ++ac)
1323: /* NOTHING */;
1324: if (ac == 3 && *argv[1] == '-') {
1325: cp = Check_Cwd_Cmd(argv[2]);
1326: } else {
1.89 christos 1327: cp = Check_Cwd_av(ac, UNCONST(argv), 0);
1.54 sjg 1328: }
1329: if (cp) {
1330: chdir(cp);
1331: }
1.29 christos 1332: }
1333:
1334: /*-
1335: * Cmd_Exec --
1336: * Execute the command in cmd, and return the output of that command
1337: * in a string.
1338: *
1339: * Results:
1340: * A string containing the output of the command, or the empty string
1341: * If err is not NULL, it contains the reason for the command failure
1342: *
1343: * Side Effects:
1344: * The string must be freed by the caller.
1345: */
1346: char *
1.89 christos 1347: Cmd_Exec(const char *cmd, const char **err)
1.29 christos 1348: {
1.89 christos 1349: const char *args[4]; /* Args for invoking the shell */
1.29 christos 1350: int fds[2]; /* Pipe streams */
1351: int cpid; /* Child PID */
1352: int pid; /* PID from wait() */
1353: char *res; /* result */
1354: int status; /* command exit status */
1355: Buffer buf; /* buffer to store the result */
1356: char *cp;
1357: int cc;
1358:
1359:
1360: *err = NULL;
1361:
1.90 sjg 1362: if (!shellName)
1363: Shell_Init();
1.29 christos 1364: /*
1365: * Set up arguments for shell
1366: */
1.90 sjg 1367: args[0] = shellName;
1.29 christos 1368: args[1] = "-c";
1369: args[2] = cmd;
1370: args[3] = NULL;
1371:
1372: /*
1373: * Open a pipe for fetching its output
1374: */
1375: if (pipe(fds) == -1) {
1376: *err = "Couldn't create pipe for \"%s\"";
1377: goto bad;
1378: }
1379:
1380: /*
1381: * Fork
1382: */
1383: switch (cpid = vfork()) {
1384: case 0:
1385: /*
1386: * Close input side of pipe
1387: */
1.112 christos 1388: (void)close(fds[0]);
1.29 christos 1389:
1390: /*
1391: * Duplicate the output stream to the shell's output, then
1392: * shut the extra thing down. Note we don't fetch the error
1393: * stream...why not? Why?
1394: */
1.112 christos 1395: (void)dup2(fds[1], 1);
1396: (void)close(fds[1]);
1.31 christos 1397:
1.112 christos 1398: (void)execv(shellPath, UNCONST(args));
1.29 christos 1399: _exit(1);
1400: /*NOTREACHED*/
1401:
1402: case -1:
1403: *err = "Couldn't exec \"%s\"";
1404: goto bad;
1405:
1406: default:
1407: /*
1408: * No need for the writing half
1409: */
1.112 christos 1410: (void)close(fds[1]);
1.31 christos 1411:
1.106 christos 1412: buf = Buf_Init(MAKE_BSIZE);
1.29 christos 1413:
1414: do {
1415: char result[BUFSIZ];
1416: cc = read(fds[0], result, sizeof(result));
1.31 christos 1417: if (cc > 0)
1.115 christos 1418: Buf_AddBytes(buf, cc, (Byte *)result);
1.29 christos 1419: }
1420: while (cc > 0 || (cc == -1 && errno == EINTR));
1421:
1422: /*
1423: * Close the input side of the pipe.
1424: */
1.112 christos 1425: (void)close(fds[0]);
1.29 christos 1426:
1427: /*
1428: * Wait for the process to exit.
1429: */
1430: while(((pid = wait(&status)) != cpid) && (pid >= 0))
1431: continue;
1432:
1.112 christos 1433: res = (char *)Buf_GetAll(buf, &cc);
1.106 christos 1434: Buf_Destroy(buf, FALSE);
1.29 christos 1435:
1.31 christos 1436: if (cc == 0)
1.29 christos 1437: *err = "Couldn't read shell's output for \"%s\"";
1438:
1439: if (status)
1440: *err = "\"%s\" returned non-zero status";
1441:
1442: /*
1443: * Null-terminate the result, convert newlines to spaces and
1444: * install it in the variable.
1445: */
1446: res[cc] = '\0';
1.44 itohy 1447: cp = &res[cc];
1.29 christos 1448:
1.44 itohy 1449: if (cc > 0 && *--cp == '\n') {
1.29 christos 1450: /*
1451: * A final newline is just stripped
1452: */
1453: *cp-- = '\0';
1454: }
1455: while (cp >= res) {
1456: if (*cp == '\n') {
1457: *cp = ' ';
1458: }
1459: cp--;
1460: }
1461: break;
1462: }
1463: return res;
1464: bad:
1465: res = emalloc(1);
1466: *res = '\0';
1467: return res;
1.1 cgd 1468: }
1469:
1470: /*-
1471: * Error --
1472: * Print an error message given its format.
1473: *
1474: * Results:
1475: * None.
1476: *
1477: * Side Effects:
1478: * The message is printed.
1479: */
1480: /* VARARGS */
1481: void
1.89 christos 1482: Error(const char *fmt, ...)
1.1 cgd 1483: {
1484: va_list ap;
1.85 wiz 1485:
1.13 cgd 1486: va_start(ap, fmt);
1.53 christos 1487: fprintf(stderr, "%s: ", progname);
1.1 cgd 1488: (void)vfprintf(stderr, fmt, ap);
1489: va_end(ap);
1490: (void)fprintf(stderr, "\n");
1491: (void)fflush(stderr);
1492: }
1493:
1494: /*-
1495: * Fatal --
1496: * Produce a Fatal error message. If jobs are running, waits for them
1497: * to finish.
1498: *
1499: * Results:
1500: * None
1501: *
1502: * Side Effects:
1503: * The program exits
1504: */
1505: /* VARARGS */
1506: void
1.89 christos 1507: Fatal(const char *fmt, ...)
1.1 cgd 1508: {
1509: va_list ap;
1.85 wiz 1510:
1.13 cgd 1511: va_start(ap, fmt);
1.1 cgd 1512: if (jobsRunning)
1513: Job_Wait();
1514:
1515: (void)vfprintf(stderr, fmt, ap);
1516: va_end(ap);
1517: (void)fprintf(stderr, "\n");
1518: (void)fflush(stderr);
1519:
1.67 sjg 1520: PrintOnError(NULL);
1521:
1.94 dsl 1522: if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
1.1 cgd 1523: Targ_PrintGraph(2);
1.58 sommerfe 1524: Trace_Log(MAKEERROR, 0);
1.1 cgd 1525: exit(2); /* Not 1 so -q can distinguish error */
1526: }
1527:
1528: /*
1529: * Punt --
1530: * Major exception once jobs are being created. Kills all jobs, prints
1531: * a message and exits.
1532: *
1533: * Results:
1.31 christos 1534: * None
1.1 cgd 1535: *
1536: * Side Effects:
1537: * All children are killed indiscriminately and the program Lib_Exits
1538: */
1539: /* VARARGS */
1540: void
1.89 christos 1541: Punt(const char *fmt, ...)
1.1 cgd 1542: {
1543: va_list ap;
1.85 wiz 1544:
1.13 cgd 1545: va_start(ap, fmt);
1.63 christos 1546: (void)fprintf(stderr, "%s: ", progname);
1.1 cgd 1547: (void)vfprintf(stderr, fmt, ap);
1548: va_end(ap);
1549: (void)fprintf(stderr, "\n");
1550: (void)fflush(stderr);
1551:
1.67 sjg 1552: PrintOnError(NULL);
1553:
1.1 cgd 1554: DieHorribly();
1555: }
1556:
1557: /*-
1558: * DieHorribly --
1559: * Exit without giving a message.
1560: *
1561: * Results:
1562: * None
1563: *
1564: * Side Effects:
1565: * A big one...
1566: */
1567: void
1.85 wiz 1568: DieHorribly(void)
1.1 cgd 1569: {
1570: if (jobsRunning)
1571: Job_AbortAll();
1572: if (DEBUG(GRAPH2))
1573: Targ_PrintGraph(2);
1.58 sommerfe 1574: Trace_Log(MAKEERROR, 0);
1.1 cgd 1575: exit(2); /* Not 1, so -q can distinguish error */
1576: }
1577:
1578: /*
1579: * Finish --
1580: * Called when aborting due to errors in child shell to signal
1.31 christos 1581: * abnormal exit.
1.1 cgd 1582: *
1583: * Results:
1.31 christos 1584: * None
1.1 cgd 1585: *
1586: * Side Effects:
1587: * The program exits
1588: */
1589: void
1.85 wiz 1590: Finish(int errors)
1591: /* number of errors encountered in Make_Make */
1.1 cgd 1592: {
1593: Fatal("%d error%s", errors, errors == 1 ? "" : "s");
1594: }
1595:
1596: /*
1597: * emalloc --
1598: * malloc, but die on error.
1599: */
1.28 christos 1600: void *
1.85 wiz 1601: emalloc(size_t len)
1.1 cgd 1602: {
1.28 christos 1603: void *p;
1.1 cgd 1604:
1.28 christos 1605: if ((p = malloc(len)) == NULL)
1.30 christos 1606: enomem();
1607: return(p);
1608: }
1609:
1610: /*
1.31 christos 1611: * estrdup --
1.30 christos 1612: * strdup, but die on error.
1613: */
1614: char *
1.85 wiz 1615: estrdup(const char *str)
1.30 christos 1616: {
1617: char *p;
1618:
1619: if ((p = strdup(str)) == NULL)
1.27 jtc 1620: enomem();
1621: return(p);
1622: }
1623:
1624: /*
1625: * erealloc --
1626: * realloc, but die on error.
1627: */
1.28 christos 1628: void *
1.85 wiz 1629: erealloc(void *ptr, size_t size)
1.27 jtc 1630: {
1.28 christos 1631: if ((ptr = realloc(ptr, size)) == NULL)
1.1 cgd 1632: enomem();
1.28 christos 1633: return(ptr);
1.1 cgd 1634: }
1635:
1636: /*
1637: * enomem --
1638: * die when out of memory.
1639: */
1.13 cgd 1640: void
1.85 wiz 1641: enomem(void)
1.1 cgd 1642: {
1.63 christos 1643: (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
1.1 cgd 1644: exit(2);
1.21 christos 1645: }
1646:
1647: /*
1648: * enunlink --
1649: * Remove a file carefully, avoiding directories.
1650: */
1651: int
1.85 wiz 1652: eunlink(const char *file)
1.21 christos 1653: {
1654: struct stat st;
1655:
1656: if (lstat(file, &st) == -1)
1657: return -1;
1658:
1659: if (S_ISDIR(st.st_mode)) {
1660: errno = EISDIR;
1661: return -1;
1662: }
1663: return unlink(file);
1.1 cgd 1664: }
1665:
1666: /*
1.66 christos 1667: * execError --
1668: * Print why exec failed, avoiding stdio.
1669: */
1670: void
1.85 wiz 1671: execError(const char *af, const char *av)
1.66 christos 1672: {
1673: #ifdef USE_IOVEC
1674: int i = 0;
1.83 pk 1675: struct iovec iov[8];
1.66 christos 1676: #define IOADD(s) \
1.89 christos 1677: (void)(iov[i].iov_base = UNCONST(s), \
1.66 christos 1678: iov[i].iov_len = strlen(iov[i].iov_base), \
1679: i++)
1680: #else
1.112 christos 1681: #define IOADD(void)write(2, s, strlen(s))
1.66 christos 1682: #endif
1683:
1684: IOADD(progname);
1.83 pk 1685: IOADD(": ");
1.89 christos 1686: IOADD(af);
1.83 pk 1687: IOADD("(");
1.89 christos 1688: IOADD(av);
1.83 pk 1689: IOADD(") failed (");
1.66 christos 1690: IOADD(strerror(errno));
1691: IOADD(")\n");
1692:
1693: #ifdef USE_IOVEC
1.83 pk 1694: (void)writev(2, iov, 8);
1.66 christos 1695: #endif
1696: }
1697:
1698: /*
1.1 cgd 1699: * usage --
1700: * exit with usage message
1701: */
1.13 cgd 1702: static void
1.85 wiz 1703: usage(void)
1.1 cgd 1704: {
1705: (void)fprintf(stderr,
1.105 wiz 1706: "usage: %s [-BeikNnqrstWX] [-D variable] [-d flags] [-f makefile]\n\
1707: [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n\
1708: [-V variable] [variable=value] [target ...]\n", progname);
1.1 cgd 1709: exit(2);
1.14 jtc 1710: }
1711:
1712:
1713: int
1.85 wiz 1714: PrintAddr(ClientData a, ClientData b)
1.14 jtc 1715: {
1716: printf("%lx ", (unsigned long) a);
1717: return b ? 0 : 0;
1.67 sjg 1718: }
1719:
1720:
1721:
1722: void
1.89 christos 1723: PrintOnError(const char *s)
1.67 sjg 1724: {
1725: char tmp[64];
1726:
1727: if (s)
1728: printf("%s", s);
1729:
1730: printf("\n%s: stopped in %s\n", progname, curdir);
1731: strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
1732: sizeof(tmp) - 1);
1733: s = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
1734: if (s && *s)
1735: printf("%s", s);
1.68 sjg 1736: }
1737:
1738: void
1.85 wiz 1739: Main_ExportMAKEFLAGS(Boolean first)
1.68 sjg 1740: {
1741: static int once = 1;
1742: char tmp[64];
1743: char *s;
1744:
1745: if (once != first)
1746: return;
1747: once = 0;
1748:
1.70 sjg 1749: strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
1750: sizeof(tmp));
1751: s = Var_Subst(NULL, tmp, VAR_CMD, 0);
1.68 sjg 1752: if (s && *s) {
1753: #ifdef POSIX
1754: setenv("MAKEFLAGS", s, 1);
1755: #else
1756: setenv("MAKE", s, 1);
1757: #endif
1758: }
1.1 cgd 1759: }
CVSweb <webmaster@jp.NetBSD.org>