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