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