1 /* $NetBSD: main.c,v 1.512 2021/01/10 23:59:53 rillig Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 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 /* 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 71 /* 72 * The main file for this entire program. Exit routines etc. reside here. 73 * 74 * Utility functions defined in this file: 75 * 76 * Main_ParseArgLine Parse and process command line arguments from 77 * a single string. Used to implement the 78 * special targets .MFLAGS and .MAKEFLAGS. 79 * 80 * Error Print a tagged error message. 81 * 82 * Fatal Print an error message and exit. 83 * 84 * Punt Abort all jobs and exit with a message. 85 * 86 * Finish Finish things up by printing the number of 87 * errors which occurred, and exit. 88 */ 89 90 #include <sys/types.h> 91 #include <sys/time.h> 92 #include <sys/param.h> 93 #include <sys/resource.h> 94 #include <sys/stat.h> 95 #if defined(MAKE_NATIVE) && defined(HAVE_SYSCTL) 96 #include <sys/sysctl.h> 97 #endif 98 #include <sys/utsname.h> 99 #include "wait.h" 100 101 #include <errno.h> 102 #include <signal.h> 103 #include <stdarg.h> 104 #include <time.h> 105 106 #include "make.h" 107 #include "dir.h" 108 #include "job.h" 109 #include "pathnames.h" 110 #include "trace.h" 111 112 /* "@(#)main.c 8.3 (Berkeley) 3/19/94" */ 113 MAKE_RCSID("$NetBSD: main.c,v 1.512 2021/01/10 23:59:53 rillig Exp $"); 114 #if defined(MAKE_NATIVE) && !defined(lint) 115 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993 " 116 "The Regents of the University of California. " 117 "All rights reserved."); 118 #endif 119 120 #ifndef __arraycount 121 # define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) 122 #endif 123 124 CmdOpts opts; 125 time_t now; /* Time at start of make */ 126 GNode *defaultNode; /* .DEFAULT node */ 127 Boolean allPrecious; /* .PRECIOUS given on line by itself */ 128 Boolean deleteOnError; /* .DELETE_ON_ERROR: set */ 129 130 static int maxJobTokens; /* -j argument */ 131 Boolean enterFlagObj; /* -w and objdir != srcdir */ 132 133 static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */ 134 Boolean doing_depend; /* Set while reading .depend */ 135 static Boolean jobsRunning; /* TRUE if the jobs might be running */ 136 static const char *tracefile; 137 static int ReadMakefile(const char *); 138 static void purge_relative_cached_realpaths(void); 139 140 static Boolean ignorePWD; /* if we use -C, PWD is meaningless */ 141 static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */ 142 char curdir[MAXPATHLEN + 1]; /* Startup directory */ 143 const char *progname; 144 char *makeDependfile; 145 pid_t myPid; 146 int makelevel; 147 148 Boolean forceJobs = FALSE; 149 static int main_errors = 0; 150 static HashTable cached_realpaths; 151 152 /* 153 * For compatibility with the POSIX version of MAKEFLAGS that includes 154 * all the options without '-', convert 'flags' to '-f -l -a -g -s'. 155 */ 156 static char * 157 explode(const char *flags) 158 { 159 size_t len; 160 char *nf, *st; 161 const char *f; 162 163 if (flags == NULL) 164 return NULL; 165 166 for (f = flags; *f != '\0'; f++) 167 if (!ch_isalpha(*f)) 168 break; 169 170 if (*f != '\0') 171 return bmake_strdup(flags); 172 173 len = strlen(flags); 174 st = nf = bmake_malloc(len * 3 + 1); 175 while (*flags != '\0') { 176 *nf++ = '-'; 177 *nf++ = *flags++; 178 *nf++ = ' '; 179 } 180 *nf = '\0'; 181 return st; 182 } 183 184 /* 185 * usage -- 186 * exit with usage message 187 */ 188 MAKE_ATTR_DEAD static void 189 usage(void) 190 { 191 size_t prognameLen = strcspn(progname, "["); 192 193 (void)fprintf(stderr, 194 "usage: %.*s [-BeikNnqrSstWwX]\n" 195 " [-C directory] [-D variable] [-d flags] [-f makefile]\n" 196 " [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n" 197 " [-V variable] [-v variable] [variable=value] [target ...]\n", 198 (int)prognameLen, progname); 199 exit(2); 200 } 201 202 static void 203 parse_debug_option_F(const char *modules) 204 { 205 const char *mode; 206 size_t len; 207 char *fname; 208 209 if (opts.debug_file != stdout && opts.debug_file != stderr) 210 fclose(opts.debug_file); 211 212 if (*modules == '+') { 213 modules++; 214 mode = "a"; 215 } else 216 mode = "w"; 217 218 if (strcmp(modules, "stdout") == 0) { 219 opts.debug_file = stdout; 220 return; 221 } 222 if (strcmp(modules, "stderr") == 0) { 223 opts.debug_file = stderr; 224 return; 225 } 226 227 len = strlen(modules); 228 fname = bmake_malloc(len + 20); 229 memcpy(fname, modules, len + 1); 230 231 /* Let the filename be modified by the pid */ 232 if (strcmp(fname + len - 3, ".%d") == 0) 233 snprintf(fname + len - 2, 20, "%d", getpid()); 234 235 opts.debug_file = fopen(fname, mode); 236 if (opts.debug_file == NULL) { 237 fprintf(stderr, "Cannot open debug file %s\n", 238 fname); 239 usage(); 240 } 241 free(fname); 242 } 243 244 static void 245 parse_debug_options(const char *argvalue) 246 { 247 const char *modules; 248 DebugFlags debug = opts.debug; 249 250 for (modules = argvalue; *modules != '\0'; ++modules) { 251 switch (*modules) { 252 case '0': /* undocumented, only intended for tests */ 253 debug = DEBUG_NONE; 254 break; 255 case 'A': 256 debug = DEBUG_ALL; 257 break; 258 case 'a': 259 debug |= DEBUG_ARCH; 260 break; 261 case 'C': 262 debug |= DEBUG_CWD; 263 break; 264 case 'c': 265 debug |= DEBUG_COND; 266 break; 267 case 'd': 268 debug |= DEBUG_DIR; 269 break; 270 case 'e': 271 debug |= DEBUG_ERROR; 272 break; 273 case 'f': 274 debug |= DEBUG_FOR; 275 break; 276 case 'g': 277 if (modules[1] == '1') { 278 debug |= DEBUG_GRAPH1; 279 modules++; 280 } else if (modules[1] == '2') { 281 debug |= DEBUG_GRAPH2; 282 modules++; 283 } else if (modules[1] == '3') { 284 debug |= DEBUG_GRAPH3; 285 modules++; 286 } 287 break; 288 case 'h': 289 debug |= DEBUG_HASH; 290 break; 291 case 'j': 292 debug |= DEBUG_JOB; 293 break; 294 case 'L': 295 opts.strict = TRUE; 296 break; 297 case 'l': 298 debug |= DEBUG_LOUD; 299 break; 300 case 'M': 301 debug |= DEBUG_META; 302 break; 303 case 'm': 304 debug |= DEBUG_MAKE; 305 break; 306 case 'n': 307 debug |= DEBUG_SCRIPT; 308 break; 309 case 'p': 310 debug |= DEBUG_PARSE; 311 break; 312 case 's': 313 debug |= DEBUG_SUFF; 314 break; 315 case 't': 316 debug |= DEBUG_TARG; 317 break; 318 case 'V': 319 opts.debugVflag = TRUE; 320 break; 321 case 'v': 322 debug |= DEBUG_VAR; 323 break; 324 case 'x': 325 debug |= DEBUG_SHELL; 326 break; 327 case 'F': 328 parse_debug_option_F(modules + 1); 329 goto debug_setbuf; 330 default: 331 (void)fprintf(stderr, 332 "%s: illegal argument to d option -- %c\n", 333 progname, *modules); 334 usage(); 335 } 336 } 337 338 debug_setbuf: 339 opts.debug = debug; 340 341 /* 342 * Make the debug_file unbuffered, and make 343 * stdout line buffered (unless debugfile == stdout). 344 */ 345 setvbuf(opts.debug_file, NULL, _IONBF, 0); 346 if (opts.debug_file != stdout) { 347 setvbuf(stdout, NULL, _IOLBF, 0); 348 } 349 } 350 351 /* 352 * does path contain any relative components 353 */ 354 static Boolean 355 is_relpath(const char *path) 356 { 357 const char *cp; 358 359 if (path[0] != '/') 360 return TRUE; 361 cp = path; 362 while ((cp = strstr(cp, "/.")) != NULL) { 363 cp += 2; 364 if (*cp == '.') 365 cp++; 366 if (cp[0] == '/' || cp[0] == '\0') 367 return TRUE; 368 } 369 return FALSE; 370 } 371 372 static void 373 MainParseArgChdir(const char *argvalue) 374 { 375 struct stat sa, sb; 376 377 if (chdir(argvalue) == -1) { 378 (void)fprintf(stderr, "%s: chdir %s: %s\n", 379 progname, argvalue, strerror(errno)); 380 exit(2); /* Not 1 so -q can distinguish error */ 381 } 382 if (getcwd(curdir, MAXPATHLEN) == NULL) { 383 (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno)); 384 exit(2); 385 } 386 if (!is_relpath(argvalue) && 387 stat(argvalue, &sa) != -1 && 388 stat(curdir, &sb) != -1 && 389 sa.st_ino == sb.st_ino && 390 sa.st_dev == sb.st_dev) 391 strncpy(curdir, argvalue, MAXPATHLEN); 392 ignorePWD = TRUE; 393 } 394 395 static void 396 MainParseArgJobsInternal(const char *argvalue) 397 { 398 char end; 399 if (sscanf(argvalue, "%d,%d%c", &jp_0, &jp_1, &end) != 2) { 400 (void)fprintf(stderr, 401 "%s: internal error -- J option malformed (%s)\n", 402 progname, argvalue); 403 usage(); 404 } 405 if ((fcntl(jp_0, F_GETFD, 0) < 0) || 406 (fcntl(jp_1, F_GETFD, 0) < 0)) { 407 #if 0 408 (void)fprintf(stderr, 409 "%s: ###### warning -- J descriptors were closed!\n", 410 progname); 411 exit(2); 412 #endif 413 jp_0 = -1; 414 jp_1 = -1; 415 opts.compatMake = TRUE; 416 } else { 417 Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL); 418 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 419 } 420 } 421 422 static void 423 MainParseArgJobs(const char *argvalue) 424 { 425 char *p; 426 427 forceJobs = TRUE; 428 opts.maxJobs = (int)strtol(argvalue, &p, 0); 429 if (*p != '\0' || opts.maxJobs < 1) { 430 (void)fprintf(stderr, 431 "%s: illegal argument to -j -- must be positive integer!\n", 432 progname); 433 exit(2); /* Not 1 so -q can distinguish error */ 434 } 435 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); 436 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 437 Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL); 438 maxJobTokens = opts.maxJobs; 439 } 440 441 static void 442 MainParseArgSysInc(const char *argvalue) 443 { 444 /* look for magic parent directory search string */ 445 if (strncmp(".../", argvalue, 4) == 0) { 446 char *found_path = Dir_FindHereOrAbove(curdir, argvalue + 4); 447 if (found_path == NULL) 448 return; 449 (void)Dir_AddDir(sysIncPath, found_path); 450 free(found_path); 451 } else { 452 (void)Dir_AddDir(sysIncPath, argvalue); 453 } 454 Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); 455 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 456 } 457 458 static Boolean 459 MainParseArg(char c, const char *argvalue) 460 { 461 switch (c) { 462 case '\0': 463 break; 464 case 'B': 465 opts.compatMake = TRUE; 466 Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL); 467 Var_Set(MAKE_MODE, "compat", VAR_GLOBAL); 468 break; 469 case 'C': 470 MainParseArgChdir(argvalue); 471 break; 472 case 'D': 473 if (argvalue[0] == '\0') return FALSE; 474 Var_Set(argvalue, "1", VAR_GLOBAL); 475 Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); 476 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 477 break; 478 case 'I': 479 Parse_AddIncludeDir(argvalue); 480 Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); 481 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 482 break; 483 case 'J': 484 MainParseArgJobsInternal(argvalue); 485 break; 486 case 'N': 487 opts.noExecute = TRUE; 488 opts.noRecursiveExecute = TRUE; 489 Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL); 490 break; 491 case 'S': 492 opts.keepgoing = FALSE; 493 Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); 494 break; 495 case 'T': 496 tracefile = bmake_strdup(argvalue); 497 Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL); 498 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 499 break; 500 case 'V': 501 case 'v': 502 opts.printVars = c == 'v' ? PVM_EXPANDED : PVM_UNEXPANDED; 503 Lst_Append(&opts.variables, bmake_strdup(argvalue)); 504 /* XXX: Why always -V? */ 505 Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); 506 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 507 break; 508 case 'W': 509 opts.parseWarnFatal = TRUE; 510 /* XXX: why no Var_Append? */ 511 break; 512 case 'X': 513 opts.varNoExportEnv = TRUE; 514 Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL); 515 break; 516 case 'd': 517 /* If '-d-opts' don't pass to children */ 518 if (argvalue[0] == '-') 519 argvalue++; 520 else { 521 Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); 522 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 523 } 524 parse_debug_options(argvalue); 525 break; 526 case 'e': 527 opts.checkEnvFirst = TRUE; 528 Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); 529 break; 530 case 'f': 531 Lst_Append(&opts.makefiles, bmake_strdup(argvalue)); 532 break; 533 case 'i': 534 opts.ignoreErrors = TRUE; 535 Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); 536 break; 537 case 'j': 538 MainParseArgJobs(argvalue); 539 break; 540 case 'k': 541 opts.keepgoing = TRUE; 542 Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); 543 break; 544 case 'm': 545 MainParseArgSysInc(argvalue); 546 /* XXX: why no Var_Append? */ 547 break; 548 case 'n': 549 opts.noExecute = TRUE; 550 Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); 551 break; 552 case 'q': 553 opts.queryFlag = TRUE; 554 /* Kind of nonsensical, wot? */ 555 Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); 556 break; 557 case 'r': 558 opts.noBuiltins = TRUE; 559 Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); 560 break; 561 case 's': 562 opts.beSilent = TRUE; 563 Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); 564 break; 565 case 't': 566 opts.touchFlag = TRUE; 567 Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); 568 break; 569 case 'w': 570 opts.enterFlag = TRUE; 571 Var_Append(MAKEFLAGS, "-w", VAR_GLOBAL); 572 break; 573 default: 574 case '?': 575 usage(); 576 } 577 return TRUE; 578 } 579 580 /* 581 * Parse the given arguments. Called from main() and from 582 * Main_ParseArgLine() when the .MAKEFLAGS target is used. 583 * 584 * The arguments must be treated as read-only and will be freed after the 585 * call. 586 * 587 * XXX: Deal with command line overriding .MAKEFLAGS in makefile 588 */ 589 static void 590 MainParseArgs(int argc, char **argv) 591 { 592 char c; 593 int arginc; 594 char *argvalue; 595 char *optscan; 596 Boolean inOption, dashDash = FALSE; 597 598 const char *optspecs = "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrstv:w"; 599 /* Can't actually use getopt(3) because rescanning is not portable */ 600 601 rearg: 602 inOption = FALSE; 603 optscan = NULL; 604 while (argc > 1) { 605 const char *optspec; 606 if (!inOption) 607 optscan = argv[1]; 608 c = *optscan++; 609 arginc = 0; 610 if (inOption) { 611 if (c == '\0') { 612 argv++; 613 argc--; 614 inOption = FALSE; 615 continue; 616 } 617 } else { 618 if (c != '-' || dashDash) 619 break; 620 inOption = TRUE; 621 c = *optscan++; 622 } 623 /* '-' found at some earlier point */ 624 optspec = strchr(optspecs, c); 625 if (c != '\0' && optspec != NULL && optspec[1] == ':') { 626 /* -<something> found, and <something> should have an arg */ 627 inOption = FALSE; 628 arginc = 1; 629 argvalue = optscan; 630 if (*argvalue == '\0') { 631 if (argc < 3) 632 goto noarg; 633 argvalue = argv[2]; 634 arginc = 2; 635 } 636 } else { 637 argvalue = NULL; 638 } 639 switch (c) { 640 case '\0': 641 arginc = 1; 642 inOption = FALSE; 643 break; 644 case '-': 645 dashDash = TRUE; 646 break; 647 default: 648 if (!MainParseArg(c, argvalue)) 649 goto noarg; 650 } 651 argv += arginc; 652 argc -= arginc; 653 } 654 655 /* 656 * See if the rest of the arguments are variable assignments and 657 * perform them if so. Else take them to be targets and stuff them 658 * on the end of the "create" list. 659 */ 660 for (; argc > 1; ++argv, --argc) { 661 VarAssign var; 662 if (Parse_IsVar(argv[1], &var)) { 663 Parse_DoVar(&var, VAR_CMDLINE); 664 } else { 665 if (argv[1][0] == '\0') 666 Punt("illegal (null) argument."); 667 if (argv[1][0] == '-' && !dashDash) 668 goto rearg; 669 Lst_Append(&opts.create, bmake_strdup(argv[1])); 670 } 671 } 672 673 return; 674 noarg: 675 (void)fprintf(stderr, "%s: option requires an argument -- %c\n", 676 progname, c); 677 usage(); 678 } 679 680 /* 681 * Break a line of arguments into words and parse them. 682 * 683 * Used when a .MFLAGS or .MAKEFLAGS target is encountered during parsing and 684 * by main() when reading the MAKEFLAGS environment variable. 685 */ 686 void 687 Main_ParseArgLine(const char *line) 688 { 689 Words words; 690 char *buf; 691 692 if (line == NULL) 693 return; 694 /* XXX: don't use line as an iterator variable */ 695 for (; *line == ' '; ++line) 696 continue; 697 if (line[0] == '\0') 698 return; 699 700 #ifndef POSIX 701 { 702 /* 703 * $MAKE may simply be naming the make(1) binary 704 */ 705 char *cp; 706 707 if (!(cp = strrchr(line, '/'))) 708 cp = line; 709 if ((cp = strstr(cp, "make")) && 710 strcmp(cp, "make") == 0) 711 return; 712 } 713 #endif 714 { 715 FStr argv0 = Var_Value(".MAKE", VAR_GLOBAL); 716 buf = str_concat3(argv0.str, " ", line); 717 FStr_Done(&argv0); 718 } 719 720 words = Str_Words(buf, TRUE); 721 if (words.words == NULL) { 722 Error("Unterminated quoted string [%s]", buf); 723 free(buf); 724 return; 725 } 726 free(buf); 727 MainParseArgs((int)words.len, words.words); 728 729 Words_Free(words); 730 } 731 732 Boolean 733 Main_SetObjdir(Boolean writable, const char *fmt, ...) 734 { 735 struct stat sb; 736 char *path; 737 char buf[MAXPATHLEN + 1]; 738 char buf2[MAXPATHLEN + 1]; 739 Boolean rc = FALSE; 740 va_list ap; 741 742 va_start(ap, fmt); 743 vsnprintf(path = buf, MAXPATHLEN, fmt, ap); 744 va_end(ap); 745 746 if (path[0] != '/') { 747 snprintf(buf2, MAXPATHLEN, "%s/%s", curdir, path); 748 path = buf2; 749 } 750 751 /* look for the directory and try to chdir there */ 752 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { 753 if ((writable && access(path, W_OK) != 0) || 754 (chdir(path) != 0)) { 755 (void)fprintf(stderr, "%s warning: %s: %s.\n", 756 progname, path, strerror(errno)); 757 } else { 758 snprintf(objdir, sizeof objdir, "%s", path); 759 Var_Set(".OBJDIR", objdir, VAR_GLOBAL); 760 setenv("PWD", objdir, 1); 761 Dir_InitDot(); 762 purge_relative_cached_realpaths(); 763 rc = TRUE; 764 if (opts.enterFlag && strcmp(objdir, curdir) != 0) 765 enterFlagObj = TRUE; 766 } 767 } 768 769 return rc; 770 } 771 772 static Boolean 773 SetVarObjdir(Boolean writable, const char *var, const char *suffix) 774 { 775 FStr path = Var_Value(var, VAR_CMDLINE); 776 FStr xpath; 777 778 if (path.str == NULL || path.str[0] == '\0') { 779 FStr_Done(&path); 780 return FALSE; 781 } 782 783 /* expand variable substitutions */ 784 xpath = FStr_InitRefer(path.str); 785 if (strchr(path.str, '$') != 0) { 786 char *expanded; 787 (void)Var_Subst(path.str, VAR_GLOBAL, VARE_WANTRES, &expanded); 788 /* TODO: handle errors */ 789 xpath = FStr_InitOwn(expanded); 790 } 791 792 (void)Main_SetObjdir(writable, "%s%s", xpath.str, suffix); 793 794 FStr_Done(&xpath); 795 FStr_Done(&path); 796 return TRUE; 797 } 798 799 /* 800 * Splits str into words, adding them to the list. 801 * The string must be kept alive as long as the list. 802 */ 803 int 804 str2Lst_Append(StringList *lp, char *str) 805 { 806 char *cp; 807 int n; 808 809 const char *sep = " \t"; 810 811 for (n = 0, cp = strtok(str, sep); cp != NULL; cp = strtok(NULL, sep)) { 812 Lst_Append(lp, cp); 813 n++; 814 } 815 return n; 816 } 817 818 #ifdef SIGINFO 819 /*ARGSUSED*/ 820 static void 821 siginfo(int signo MAKE_ATTR_UNUSED) 822 { 823 char dir[MAXPATHLEN]; 824 char str[2 * MAXPATHLEN]; 825 int len; 826 if (getcwd(dir, sizeof dir) == NULL) 827 return; 828 len = snprintf(str, sizeof str, "%s: Working in: %s\n", progname, dir); 829 if (len > 0) 830 (void)write(STDERR_FILENO, str, (size_t)len); 831 } 832 #endif 833 834 /* Allow makefiles some control over the mode we run in. */ 835 static void 836 MakeMode(void) 837 { 838 FStr mode = FStr_InitRefer(NULL); 839 840 if (mode.str == NULL) { 841 char *expanded; 842 (void)Var_Subst("${" MAKE_MODE ":tl}", 843 VAR_GLOBAL, VARE_WANTRES, &expanded); 844 /* TODO: handle errors */ 845 mode = FStr_InitOwn(expanded); 846 } 847 848 if (mode.str[0] != '\0') { 849 if (strstr(mode.str, "compat") != NULL) { 850 opts.compatMake = TRUE; 851 forceJobs = FALSE; 852 } 853 #if USE_META 854 if (strstr(mode.str, "meta") != NULL) 855 meta_mode_init(mode.str); 856 #endif 857 } 858 859 FStr_Done(&mode); 860 } 861 862 static void 863 PrintVar(const char *varname, Boolean expandVars) 864 { 865 if (strchr(varname, '$') != NULL) { 866 char *evalue; 867 (void)Var_Subst(varname, VAR_GLOBAL, VARE_WANTRES, &evalue); 868 /* TODO: handle errors */ 869 printf("%s\n", evalue); 870 bmake_free(evalue); 871 872 } else if (expandVars) { 873 char *expr = str_concat3("${", varname, "}"); 874 char *evalue; 875 (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &evalue); 876 /* TODO: handle errors */ 877 free(expr); 878 printf("%s\n", evalue); 879 bmake_free(evalue); 880 881 } else { 882 FStr value = Var_Value(varname, VAR_GLOBAL); 883 printf("%s\n", value.str != NULL ? value.str : ""); 884 FStr_Done(&value); 885 } 886 } 887 888 /* 889 * Return a Boolean based on a variable. 890 * 891 * If the knob is not set, return the fallback. 892 * If set, anything that looks or smells like "No", "False", "Off", "0", etc. 893 * is FALSE, otherwise TRUE. 894 */ 895 Boolean 896 GetBooleanVar(const char *varname, Boolean fallback) 897 { 898 char *expr = str_concat3("${", varname, ":U}"); 899 char *value; 900 Boolean res; 901 902 (void)Var_Subst(expr, VAR_GLOBAL, VARE_WANTRES, &value); 903 /* TODO: handle errors */ 904 res = ParseBoolean(value, fallback); 905 free(value); 906 free(expr); 907 return res; 908 } 909 910 static void 911 doPrintVars(void) 912 { 913 StringListNode *ln; 914 Boolean expandVars; 915 916 if (opts.printVars == PVM_EXPANDED) 917 expandVars = TRUE; 918 else if (opts.debugVflag) 919 expandVars = FALSE; 920 else 921 expandVars = GetBooleanVar(".MAKE.EXPAND_VARIABLES", FALSE); 922 923 for (ln = opts.variables.first; ln != NULL; ln = ln->next) { 924 const char *varname = ln->datum; 925 PrintVar(varname, expandVars); 926 } 927 } 928 929 static Boolean 930 runTargets(void) 931 { 932 GNodeList targs = LST_INIT; /* target nodes to create */ 933 Boolean outOfDate; /* FALSE if all targets up to date */ 934 935 /* 936 * Have now read the entire graph and need to make a list of 937 * targets to create. If none was given on the command line, 938 * we consult the parsing module to find the main target(s) 939 * to create. 940 */ 941 if (Lst_IsEmpty(&opts.create)) 942 Parse_MainName(&targs); 943 else 944 Targ_FindList(&targs, &opts.create); 945 946 if (!opts.compatMake) { 947 /* 948 * Initialize job module before traversing the graph 949 * now that any .BEGIN and .END targets have been read. 950 * This is done only if the -q flag wasn't given 951 * (to prevent the .BEGIN from being executed should 952 * it exist). 953 */ 954 if (!opts.queryFlag) { 955 Job_Init(); 956 jobsRunning = TRUE; 957 } 958 959 /* Traverse the graph, checking on all the targets */ 960 outOfDate = Make_Run(&targs); 961 } else { 962 /* 963 * Compat_Init will take care of creating all the 964 * targets as well as initializing the module. 965 */ 966 Compat_Run(&targs); 967 outOfDate = FALSE; 968 } 969 Lst_Done(&targs); /* Don't free the nodes. */ 970 return outOfDate; 971 } 972 973 /* 974 * Set up the .TARGETS variable to contain the list of targets to be 975 * created. If none specified, make the variable empty -- the parser 976 * will fill the thing in with the default or .MAIN target. 977 */ 978 static void 979 InitVarTargets(void) 980 { 981 StringListNode *ln; 982 983 if (Lst_IsEmpty(&opts.create)) { 984 Var_Set(".TARGETS", "", VAR_GLOBAL); 985 return; 986 } 987 988 for (ln = opts.create.first; ln != NULL; ln = ln->next) { 989 char *name = ln->datum; 990 Var_Append(".TARGETS", name, VAR_GLOBAL); 991 } 992 } 993 994 static void 995 InitRandom(void) 996 { 997 struct timeval tv; 998 999 gettimeofday(&tv, NULL); 1000 srandom((unsigned int)(tv.tv_sec + tv.tv_usec)); 1001 } 1002 1003 static const char * 1004 InitVarMachine(const struct utsname *utsname) 1005 { 1006 #ifdef FORCE_MACHINE 1007 return FORCE_MACHINE; 1008 #else 1009 const char *machine = getenv("MACHINE"); 1010 1011 if (machine != NULL) 1012 return machine; 1013 1014 #if defined(MAKE_NATIVE) 1015 return utsname->machine; 1016 #elif defined(MAKE_MACHINE) 1017 return MAKE_MACHINE; 1018 #else 1019 return "unknown"; 1020 #endif 1021 #endif 1022 } 1023 1024 static const char * 1025 InitVarMachineArch(void) 1026 { 1027 #ifdef FORCE_MACHINE_ARCH 1028 return FORCE_MACHINE_ARCH; 1029 #else 1030 const char *env = getenv("MACHINE_ARCH"); 1031 if (env != NULL) 1032 return env; 1033 1034 #if defined(MAKE_NATIVE) && defined(CTL_HW) 1035 { 1036 struct utsname utsname; 1037 static char machine_arch_buf[sizeof utsname.machine]; 1038 const int mib[2] = { CTL_HW, HW_MACHINE_ARCH }; 1039 size_t len = sizeof machine_arch_buf; 1040 1041 if (sysctl(mib, (unsigned int)__arraycount(mib), 1042 machine_arch_buf, &len, NULL, 0) < 0) { 1043 (void)fprintf(stderr, "%s: sysctl failed (%s).\n", 1044 progname, strerror(errno)); 1045 exit(2); 1046 } 1047 1048 return machine_arch_buf; 1049 } 1050 #elif defined(MACHINE_ARCH) 1051 return MACHINE_ARCH; 1052 #elif defined(MAKE_MACHINE_ARCH) 1053 return MAKE_MACHINE_ARCH; 1054 #else 1055 return "unknown"; 1056 #endif 1057 #endif 1058 } 1059 1060 #ifndef NO_PWD_OVERRIDE 1061 /* 1062 * All this code is so that we know where we are when we start up 1063 * on a different machine with pmake. 1064 * 1065 * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX 1066 * since the value of curdir can vary depending on how we got 1067 * here. Ie sitting at a shell prompt (shell that provides $PWD) 1068 * or via subdir.mk in which case its likely a shell which does 1069 * not provide it. 1070 * 1071 * So, to stop it breaking this case only, we ignore PWD if 1072 * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a variable expression. 1073 */ 1074 static void 1075 HandlePWD(const struct stat *curdir_st) 1076 { 1077 char *pwd; 1078 FStr prefix, makeobjdir; 1079 struct stat pwd_st; 1080 1081 if (ignorePWD || (pwd = getenv("PWD")) == NULL) 1082 return; 1083 1084 prefix = Var_Value("MAKEOBJDIRPREFIX", VAR_CMDLINE); 1085 if (prefix.str != NULL) { 1086 FStr_Done(&prefix); 1087 return; 1088 } 1089 1090 makeobjdir = Var_Value("MAKEOBJDIR", VAR_CMDLINE); 1091 if (makeobjdir.str != NULL && strchr(makeobjdir.str, '$') != NULL) 1092 goto ignore_pwd; 1093 1094 if (stat(pwd, &pwd_st) == 0 && 1095 curdir_st->st_ino == pwd_st.st_ino && 1096 curdir_st->st_dev == pwd_st.st_dev) 1097 (void)strncpy(curdir, pwd, MAXPATHLEN); 1098 1099 ignore_pwd: 1100 FStr_Done(&makeobjdir); 1101 } 1102 #endif 1103 1104 /* 1105 * Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that, 1106 * MAKEOBJDIR is set in the environment, try only that value 1107 * and fall back to .CURDIR if it does not exist. 1108 * 1109 * Otherwise, try _PATH_OBJDIR.MACHINE-MACHINE_ARCH, _PATH_OBJDIR.MACHINE, 1110 * and * finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none 1111 * of these paths exist, just use .CURDIR. 1112 */ 1113 static void 1114 InitObjdir(const char *machine, const char *machine_arch) 1115 { 1116 Boolean writable; 1117 1118 Dir_InitCur(curdir); 1119 writable = GetBooleanVar("MAKE_OBJDIR_CHECK_WRITABLE", TRUE); 1120 (void)Main_SetObjdir(FALSE, "%s", curdir); 1121 1122 if (!SetVarObjdir(writable, "MAKEOBJDIRPREFIX", curdir) && 1123 !SetVarObjdir(writable, "MAKEOBJDIR", "") && 1124 !Main_SetObjdir(writable, "%s.%s-%s", _PATH_OBJDIR, machine, machine_arch) && 1125 !Main_SetObjdir(writable, "%s.%s", _PATH_OBJDIR, machine) && 1126 !Main_SetObjdir(writable, "%s", _PATH_OBJDIR)) 1127 (void)Main_SetObjdir(writable, "%s%s", _PATH_OBJDIRPREFIX, curdir); 1128 } 1129 1130 /* get rid of resource limit on file descriptors */ 1131 static void 1132 UnlimitFiles(void) 1133 { 1134 #if defined(MAKE_NATIVE) || (defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)) 1135 struct rlimit rl; 1136 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && 1137 rl.rlim_cur != rl.rlim_max) { 1138 rl.rlim_cur = rl.rlim_max; 1139 (void)setrlimit(RLIMIT_NOFILE, &rl); 1140 } 1141 #endif 1142 } 1143 1144 static void 1145 CmdOpts_Init(void) 1146 { 1147 opts.compatMake = FALSE; 1148 opts.debug = DEBUG_NONE; 1149 /* opts.debug_file has been initialized earlier */ 1150 opts.strict = FALSE; 1151 opts.debugVflag = FALSE; 1152 opts.checkEnvFirst = FALSE; 1153 Lst_Init(&opts.makefiles); 1154 opts.ignoreErrors = FALSE; /* Pay attention to non-zero returns */ 1155 opts.maxJobs = 1; 1156 opts.keepgoing = FALSE; /* Stop on error */ 1157 opts.noRecursiveExecute = FALSE; /* Execute all .MAKE targets */ 1158 opts.noExecute = FALSE; /* Execute all commands */ 1159 opts.queryFlag = FALSE; 1160 opts.noBuiltins = FALSE; /* Read the built-in rules */ 1161 opts.beSilent = FALSE; /* Print commands as executed */ 1162 opts.touchFlag = FALSE; 1163 opts.printVars = PVM_NONE; 1164 Lst_Init(&opts.variables); 1165 opts.parseWarnFatal = FALSE; 1166 opts.enterFlag = FALSE; 1167 opts.varNoExportEnv = FALSE; 1168 Lst_Init(&opts.create); 1169 } 1170 1171 /* 1172 * Initialize MAKE and .MAKE to the path of the executable, so that it can be 1173 * found by execvp(3) and the shells, even after a chdir. 1174 * 1175 * If it's a relative path and contains a '/', resolve it to an absolute path. 1176 * Otherwise keep it as is, assuming it will be found in the PATH. 1177 */ 1178 static void 1179 InitVarMake(const char *argv0) 1180 { 1181 const char *make = argv0; 1182 1183 if (argv0[0] != '/' && strchr(argv0, '/') != NULL) { 1184 char pathbuf[MAXPATHLEN]; 1185 const char *abspath = cached_realpath(argv0, pathbuf); 1186 struct stat st; 1187 if (abspath != NULL && abspath[0] == '/' && 1188 stat(make, &st) == 0) 1189 make = abspath; 1190 } 1191 1192 Var_Set("MAKE", make, VAR_GLOBAL); 1193 Var_Set(".MAKE", make, VAR_GLOBAL); 1194 } 1195 1196 /* 1197 * Add the directories from the colon-separated syspath to defSysIncPath. 1198 * After returning, the contents of syspath is unspecified. 1199 */ 1200 static void 1201 InitDefSysIncPath(char *syspath) 1202 { 1203 static char defsyspath[] = _PATH_DEFSYSPATH; 1204 char *start, *cp; 1205 1206 /* 1207 * If no user-supplied system path was given (through the -m option) 1208 * add the directories from the DEFSYSPATH (more than one may be given 1209 * as dir1:...:dirn) to the system include path. 1210 */ 1211 if (syspath == NULL || syspath[0] == '\0') 1212 syspath = defsyspath; 1213 else 1214 syspath = bmake_strdup(syspath); 1215 1216 for (start = syspath; *start != '\0'; start = cp) { 1217 for (cp = start; *cp != '\0' && *cp != ':'; cp++) 1218 continue; 1219 if (*cp == ':') 1220 *cp++ = '\0'; 1221 1222 /* look for magic parent directory search string */ 1223 if (strncmp(start, ".../", 4) == 0) { 1224 char *dir = Dir_FindHereOrAbove(curdir, start + 4); 1225 if (dir != NULL) { 1226 (void)Dir_AddDir(defSysIncPath, dir); 1227 free(dir); 1228 } 1229 } else { 1230 (void)Dir_AddDir(defSysIncPath, start); 1231 } 1232 } 1233 1234 if (syspath != defsyspath) 1235 free(syspath); 1236 } 1237 1238 static void 1239 ReadBuiltinRules(void) 1240 { 1241 StringListNode *ln; 1242 StringList sysMkPath = LST_INIT; 1243 1244 Dir_Expand(_PATH_DEFSYSMK, 1245 Lst_IsEmpty(sysIncPath) ? defSysIncPath : sysIncPath, 1246 &sysMkPath); 1247 if (Lst_IsEmpty(&sysMkPath)) 1248 Fatal("%s: no system rules (%s).", progname, _PATH_DEFSYSMK); 1249 1250 for (ln = sysMkPath.first; ln != NULL; ln = ln->next) 1251 if (ReadMakefile(ln->datum) == 0) 1252 break; 1253 1254 if (ln == NULL) 1255 Fatal("%s: cannot open %s.", 1256 progname, (const char *)sysMkPath.first->datum); 1257 1258 /* Free the list but not the actual filenames since these may still 1259 * be used in GNodes. */ 1260 Lst_Done(&sysMkPath); 1261 } 1262 1263 static void 1264 InitMaxJobs(void) 1265 { 1266 char *value; 1267 int n; 1268 1269 if (forceJobs || opts.compatMake || 1270 !Var_Exists(".MAKE.JOBS", VAR_GLOBAL)) 1271 return; 1272 1273 (void)Var_Subst("${.MAKE.JOBS}", VAR_GLOBAL, VARE_WANTRES, &value); 1274 /* TODO: handle errors */ 1275 n = (int)strtol(value, NULL, 0); 1276 if (n < 1) { 1277 (void)fprintf(stderr, 1278 "%s: illegal value for .MAKE.JOBS " 1279 "-- must be positive integer!\n", 1280 progname); 1281 exit(2); /* Not 1 so -q can distinguish error */ 1282 } 1283 1284 if (n != opts.maxJobs) { 1285 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); 1286 Var_Append(MAKEFLAGS, value, VAR_GLOBAL); 1287 } 1288 1289 opts.maxJobs = n; 1290 maxJobTokens = opts.maxJobs; 1291 forceJobs = TRUE; 1292 free(value); 1293 } 1294 1295 /* 1296 * For compatibility, look at the directories in the VPATH variable 1297 * and add them to the search path, if the variable is defined. The 1298 * variable's value is in the same format as the PATH environment 1299 * variable, i.e. <directory>:<directory>:<directory>... 1300 */ 1301 static void 1302 InitVpath(void) 1303 { 1304 char *vpath, savec, *path; 1305 if (!Var_Exists("VPATH", VAR_CMDLINE)) 1306 return; 1307 1308 (void)Var_Subst("${VPATH}", VAR_CMDLINE, VARE_WANTRES, &vpath); 1309 /* TODO: handle errors */ 1310 path = vpath; 1311 do { 1312 char *cp; 1313 /* skip to end of directory */ 1314 for (cp = path; *cp != ':' && *cp != '\0'; cp++) 1315 continue; 1316 /* Save terminator character so know when to stop */ 1317 savec = *cp; 1318 *cp = '\0'; 1319 /* Add directory to search path */ 1320 (void)Dir_AddDir(&dirSearchPath, path); 1321 *cp = savec; 1322 path = cp + 1; 1323 } while (savec == ':'); 1324 free(vpath); 1325 } 1326 1327 static void 1328 ReadAllMakefiles(StringList *makefiles) 1329 { 1330 StringListNode *ln; 1331 1332 for (ln = makefiles->first; ln != NULL; ln = ln->next) { 1333 const char *fname = ln->datum; 1334 if (ReadMakefile(fname) != 0) 1335 Fatal("%s: cannot open %s.", progname, fname); 1336 } 1337 } 1338 1339 static void 1340 ReadFirstDefaultMakefile(void) 1341 { 1342 StringListNode *ln; 1343 char *prefs; 1344 1345 (void)Var_Subst("${" MAKE_MAKEFILE_PREFERENCE "}", 1346 VAR_CMDLINE, VARE_WANTRES, &prefs); 1347 /* TODO: handle errors */ 1348 1349 /* XXX: This should use a local list instead of opts.makefiles 1350 * since these makefiles do not come from the command line. They 1351 * also have different semantics in that only the first file that 1352 * is found is processed. See ReadAllMakefiles. */ 1353 (void)str2Lst_Append(&opts.makefiles, prefs); 1354 1355 for (ln = opts.makefiles.first; ln != NULL; ln = ln->next) 1356 if (ReadMakefile(ln->datum) == 0) 1357 break; 1358 1359 free(prefs); 1360 } 1361 1362 /* 1363 * Initialize variables such as MAKE, MACHINE, .MAKEFLAGS. 1364 * Initialize a few modules. 1365 * Parse the arguments from MAKEFLAGS and the command line. 1366 */ 1367 static void 1368 main_Init(int argc, char **argv) 1369 { 1370 struct stat sa; 1371 const char *machine; 1372 const char *machine_arch; 1373 char *syspath = getenv("MAKESYSPATH"); 1374 struct utsname utsname; 1375 1376 /* default to writing debug to stderr */ 1377 opts.debug_file = stderr; 1378 1379 HashTable_Init(&cached_realpaths); 1380 1381 #ifdef SIGINFO 1382 (void)bmake_signal(SIGINFO, siginfo); 1383 #endif 1384 1385 InitRandom(); 1386 1387 progname = str_basename(argv[0]); 1388 1389 UnlimitFiles(); 1390 1391 if (uname(&utsname) == -1) { 1392 (void)fprintf(stderr, "%s: uname failed (%s).\n", progname, 1393 strerror(errno)); 1394 exit(2); 1395 } 1396 1397 /* 1398 * Get the name of this type of MACHINE from utsname 1399 * so we can share an executable for similar machines. 1400 * (i.e. m68k: amiga hp300, mac68k, sun3, ...) 1401 * 1402 * Note that both MACHINE and MACHINE_ARCH are decided at 1403 * run-time. 1404 */ 1405 machine = InitVarMachine(&utsname); 1406 machine_arch = InitVarMachineArch(); 1407 1408 myPid = getpid(); /* remember this for vFork() */ 1409 1410 /* 1411 * Just in case MAKEOBJDIR wants us to do something tricky. 1412 */ 1413 Targ_Init(); 1414 Var_Init(); 1415 Var_Set(".MAKE.OS", utsname.sysname, VAR_GLOBAL); 1416 Var_Set("MACHINE", machine, VAR_GLOBAL); 1417 Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL); 1418 #ifdef MAKE_VERSION 1419 Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL); 1420 #endif 1421 Var_Set(".newline", "\n", VAR_GLOBAL); /* handy for :@ loops */ 1422 /* 1423 * This is the traditional preference for makefiles. 1424 */ 1425 #ifndef MAKEFILE_PREFERENCE_LIST 1426 # define MAKEFILE_PREFERENCE_LIST "makefile Makefile" 1427 #endif 1428 Var_Set(MAKE_MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST, VAR_GLOBAL); 1429 Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL); 1430 1431 CmdOpts_Init(); 1432 allPrecious = FALSE; /* Remove targets when interrupted */ 1433 deleteOnError = FALSE; /* Historical default behavior */ 1434 jobsRunning = FALSE; 1435 1436 maxJobTokens = opts.maxJobs; 1437 ignorePWD = FALSE; 1438 1439 /* 1440 * Initialize the parsing, directory and variable modules to prepare 1441 * for the reading of inclusion paths and variable settings on the 1442 * command line 1443 */ 1444 1445 /* 1446 * Initialize various variables. 1447 * MAKE also gets this name, for compatibility 1448 * .MAKEFLAGS gets set to the empty string just in case. 1449 * MFLAGS also gets initialized empty, for compatibility. 1450 */ 1451 Parse_Init(); 1452 InitVarMake(argv[0]); 1453 Var_Set(MAKEFLAGS, "", VAR_GLOBAL); 1454 Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL); 1455 Var_Set("MFLAGS", "", VAR_GLOBAL); 1456 Var_Set(".ALLTARGETS", "", VAR_GLOBAL); 1457 /* some makefiles need to know this */ 1458 Var_Set(MAKE_LEVEL ".ENV", MAKE_LEVEL_ENV, VAR_CMDLINE); 1459 1460 /* Set some other useful variables. */ 1461 { 1462 char tmp[64], *ep = getenv(MAKE_LEVEL_ENV); 1463 1464 makelevel = ep != NULL && ep[0] != '\0' ? atoi(ep) : 0; 1465 if (makelevel < 0) 1466 makelevel = 0; 1467 snprintf(tmp, sizeof tmp, "%d", makelevel); 1468 Var_Set(MAKE_LEVEL, tmp, VAR_GLOBAL); 1469 snprintf(tmp, sizeof tmp, "%u", myPid); 1470 Var_Set(".MAKE.PID", tmp, VAR_GLOBAL); 1471 snprintf(tmp, sizeof tmp, "%u", getppid()); 1472 Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL); 1473 snprintf(tmp, sizeof tmp, "%u", getuid()); 1474 Var_Set(".MAKE.UID", tmp, VAR_GLOBAL); 1475 snprintf(tmp, sizeof tmp, "%u", getgid()); 1476 Var_Set(".MAKE.GID", tmp, VAR_GLOBAL); 1477 } 1478 if (makelevel > 0) { 1479 char pn[1024]; 1480 snprintf(pn, sizeof pn, "%s[%d]", progname, makelevel); 1481 progname = bmake_strdup(pn); 1482 } 1483 1484 #ifdef USE_META 1485 meta_init(); 1486 #endif 1487 Dir_Init(); 1488 1489 /* 1490 * First snag any flags out of the MAKE environment variable. 1491 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's 1492 * in a different format). 1493 */ 1494 #ifdef POSIX 1495 { 1496 char *p1 = explode(getenv("MAKEFLAGS")); 1497 Main_ParseArgLine(p1); 1498 free(p1); 1499 } 1500 #else 1501 Main_ParseArgLine(getenv("MAKE")); 1502 #endif 1503 1504 /* 1505 * Find where we are (now). 1506 * We take care of PWD for the automounter below... 1507 */ 1508 if (getcwd(curdir, MAXPATHLEN) == NULL) { 1509 (void)fprintf(stderr, "%s: getcwd: %s.\n", 1510 progname, strerror(errno)); 1511 exit(2); 1512 } 1513 1514 MainParseArgs(argc, argv); 1515 1516 if (opts.enterFlag) 1517 printf("%s: Entering directory `%s'\n", progname, curdir); 1518 1519 /* 1520 * Verify that cwd is sane. 1521 */ 1522 if (stat(curdir, &sa) == -1) { 1523 (void)fprintf(stderr, "%s: %s: %s.\n", 1524 progname, curdir, strerror(errno)); 1525 exit(2); 1526 } 1527 1528 #ifndef NO_PWD_OVERRIDE 1529 HandlePWD(&sa); 1530 #endif 1531 Var_Set(".CURDIR", curdir, VAR_GLOBAL); 1532 1533 InitObjdir(machine, machine_arch); 1534 1535 /* 1536 * Initialize archive, target and suffix modules in preparation for 1537 * parsing the makefile(s) 1538 */ 1539 Arch_Init(); 1540 Suff_Init(); 1541 Trace_Init(tracefile); 1542 1543 defaultNode = NULL; 1544 (void)time(&now); 1545 1546 Trace_Log(MAKESTART, NULL); 1547 1548 InitVarTargets(); 1549 1550 InitDefSysIncPath(syspath); 1551 } 1552 1553 /* 1554 * Read the system makefile followed by either makefile, Makefile or the 1555 * files given by the -f option. Exit on parse errors. 1556 */ 1557 static void 1558 main_ReadFiles(void) 1559 { 1560 1561 if (!opts.noBuiltins) 1562 ReadBuiltinRules(); 1563 1564 if (!Lst_IsEmpty(&opts.makefiles)) 1565 ReadAllMakefiles(&opts.makefiles); 1566 else 1567 ReadFirstDefaultMakefile(); 1568 } 1569 1570 /* Compute the dependency graph. */ 1571 static void 1572 main_PrepareMaking(void) 1573 { 1574 /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */ 1575 if (!opts.noBuiltins || opts.printVars == PVM_NONE) { 1576 (void)Var_Subst("${.MAKE.DEPENDFILE}", 1577 VAR_CMDLINE, VARE_WANTRES, &makeDependfile); 1578 if (makeDependfile[0] != '\0') { 1579 /* TODO: handle errors */ 1580 doing_depend = TRUE; 1581 (void)ReadMakefile(makeDependfile); 1582 doing_depend = FALSE; 1583 } 1584 } 1585 1586 if (enterFlagObj) 1587 printf("%s: Entering directory `%s'\n", progname, objdir); 1588 1589 MakeMode(); 1590 1591 { 1592 FStr makeflags = Var_Value(MAKEFLAGS, VAR_GLOBAL); 1593 Var_Append("MFLAGS", makeflags.str, VAR_GLOBAL); 1594 FStr_Done(&makeflags); 1595 } 1596 1597 InitMaxJobs(); 1598 1599 /* 1600 * Be compatible if the user did not specify -j and did not explicitly 1601 * turn compatibility on. 1602 */ 1603 if (!opts.compatMake && !forceJobs) 1604 opts.compatMake = TRUE; 1605 1606 if (!opts.compatMake) 1607 Job_ServerStart(maxJobTokens, jp_0, jp_1); 1608 DEBUG5(JOB, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n", 1609 jp_0, jp_1, opts.maxJobs, maxJobTokens, opts.compatMake ? 1 : 0); 1610 1611 if (opts.printVars == PVM_NONE) 1612 Main_ExportMAKEFLAGS(TRUE); /* initial export */ 1613 1614 InitVpath(); 1615 1616 /* 1617 * Now that all search paths have been read for suffixes et al, it's 1618 * time to add the default search path to their lists... 1619 */ 1620 Suff_DoPaths(); 1621 1622 /* 1623 * Propagate attributes through :: dependency lists. 1624 */ 1625 Targ_Propagate(); 1626 1627 /* print the initial graph, if the user requested it */ 1628 if (DEBUG(GRAPH1)) 1629 Targ_PrintGraph(1); 1630 } 1631 1632 /* 1633 * Make the targets. 1634 * If the -v or -V options are given, print variables instead. 1635 * Return whether any of the targets is out-of-date. 1636 */ 1637 static Boolean 1638 main_Run(void) 1639 { 1640 if (opts.printVars != PVM_NONE) { 1641 /* print the values of any variables requested by the user */ 1642 doPrintVars(); 1643 return FALSE; 1644 } else { 1645 return runTargets(); 1646 } 1647 } 1648 1649 /* Clean up after making the targets. */ 1650 static void 1651 main_CleanUp(void) 1652 { 1653 #ifdef CLEANUP 1654 Lst_DoneCall(&opts.variables, free); 1655 /* 1656 * Don't free the actual strings from opts.makefiles, they may be 1657 * used in GNodes. 1658 */ 1659 Lst_Done(&opts.makefiles); 1660 Lst_DoneCall(&opts.create, free); 1661 #endif 1662 1663 /* print the graph now it's been processed if the user requested it */ 1664 if (DEBUG(GRAPH2)) 1665 Targ_PrintGraph(2); 1666 1667 Trace_Log(MAKEEND, NULL); 1668 1669 if (enterFlagObj) 1670 printf("%s: Leaving directory `%s'\n", progname, objdir); 1671 if (opts.enterFlag) 1672 printf("%s: Leaving directory `%s'\n", progname, curdir); 1673 1674 #ifdef USE_META 1675 meta_finish(); 1676 #endif 1677 Suff_End(); 1678 Targ_End(); 1679 Arch_End(); 1680 Var_End(); 1681 Parse_End(); 1682 Dir_End(); 1683 Job_End(); 1684 Trace_End(); 1685 } 1686 1687 /* Determine the exit code. */ 1688 static int 1689 main_Exit(Boolean outOfDate) 1690 { 1691 if (opts.strict && (main_errors > 0 || Parse_GetFatals() > 0)) 1692 return 2; /* Not 1 so -q can distinguish error */ 1693 return outOfDate ? 1 : 0; 1694 } 1695 1696 int 1697 main(int argc, char **argv) 1698 { 1699 Boolean outOfDate; 1700 1701 main_Init(argc, argv); 1702 main_ReadFiles(); 1703 main_PrepareMaking(); 1704 outOfDate = main_Run(); 1705 main_CleanUp(); 1706 return main_Exit(outOfDate); 1707 } 1708 1709 /* 1710 * Open and parse the given makefile, with all its side effects. 1711 * 1712 * Results: 1713 * 0 if ok. -1 if couldn't open file. 1714 */ 1715 static int 1716 ReadMakefile(const char *fname) 1717 { 1718 int fd; 1719 char *name, *path = NULL; 1720 1721 if (strcmp(fname, "-") == 0) { 1722 Parse_File(NULL /*stdin*/, -1); 1723 Var_Set("MAKEFILE", "", VAR_INTERNAL); 1724 } else { 1725 /* if we've chdir'd, rebuild the path name */ 1726 if (strcmp(curdir, objdir) != 0 && *fname != '/') { 1727 path = str_concat3(curdir, "/", fname); 1728 fd = open(path, O_RDONLY); 1729 if (fd != -1) { 1730 fname = path; 1731 goto found; 1732 } 1733 free(path); 1734 1735 /* If curdir failed, try objdir (ala .depend) */ 1736 path = str_concat3(objdir, "/", fname); 1737 fd = open(path, O_RDONLY); 1738 if (fd != -1) { 1739 fname = path; 1740 goto found; 1741 } 1742 } else { 1743 fd = open(fname, O_RDONLY); 1744 if (fd != -1) 1745 goto found; 1746 } 1747 /* look in -I and system include directories. */ 1748 name = Dir_FindFile(fname, parseIncPath); 1749 if (name == NULL) { 1750 SearchPath *sysInc = Lst_IsEmpty(sysIncPath) 1751 ? defSysIncPath : sysIncPath; 1752 name = Dir_FindFile(fname, sysInc); 1753 } 1754 if (name == NULL || (fd = open(name, O_RDONLY)) == -1) { 1755 free(name); 1756 free(path); 1757 return -1; 1758 } 1759 fname = name; 1760 /* 1761 * set the MAKEFILE variable desired by System V fans -- the 1762 * placement of the setting here means it gets set to the last 1763 * makefile specified, as it is set by SysV make. 1764 */ 1765 found: 1766 if (!doing_depend) 1767 Var_Set("MAKEFILE", fname, VAR_INTERNAL); 1768 Parse_File(fname, fd); 1769 } 1770 free(path); 1771 return 0; 1772 } 1773 1774 /*- 1775 * Cmd_Exec -- 1776 * Execute the command in cmd, and return the output of that command 1777 * in a string. In the output, newlines are replaced with spaces. 1778 * 1779 * Results: 1780 * A string containing the output of the command, or the empty string. 1781 * *errfmt returns a format string describing the command failure, 1782 * if any, using a single %s conversion specification. 1783 * 1784 * Side Effects: 1785 * The string must be freed by the caller. 1786 */ 1787 char * 1788 Cmd_Exec(const char *cmd, const char **errfmt) 1789 { 1790 const char *args[4]; /* Args for invoking the shell */ 1791 int pipefds[2]; 1792 int cpid; /* Child PID */ 1793 int pid; /* PID from wait() */ 1794 int status; /* command exit status */ 1795 Buffer buf; /* buffer to store the result */ 1796 ssize_t bytes_read; 1797 char *res; /* result */ 1798 size_t res_len; 1799 char *cp; 1800 int savederr; /* saved errno */ 1801 1802 *errfmt = NULL; 1803 1804 if (shellName == NULL) 1805 Shell_Init(); 1806 /* 1807 * Set up arguments for shell 1808 */ 1809 args[0] = shellName; 1810 args[1] = "-c"; 1811 args[2] = cmd; 1812 args[3] = NULL; 1813 1814 /* 1815 * Open a pipe for fetching its output 1816 */ 1817 if (pipe(pipefds) == -1) { 1818 *errfmt = "Couldn't create pipe for \"%s\""; 1819 goto bad; 1820 } 1821 1822 Var_ReexportVars(); 1823 1824 /* 1825 * Fork 1826 */ 1827 switch (cpid = vFork()) { 1828 case 0: 1829 (void)close(pipefds[0]); /* Close input side of pipe */ 1830 1831 /* 1832 * Duplicate the output stream to the shell's output, then 1833 * shut the extra thing down. Note we don't fetch the error 1834 * stream...why not? Why? 1835 */ 1836 (void)dup2(pipefds[1], 1); 1837 (void)close(pipefds[1]); 1838 1839 (void)execv(shellPath, UNCONST(args)); 1840 _exit(1); 1841 /*NOTREACHED*/ 1842 1843 case -1: 1844 *errfmt = "Couldn't exec \"%s\""; 1845 goto bad; 1846 1847 default: 1848 (void)close(pipefds[1]); /* No need for the writing half */ 1849 1850 savederr = 0; 1851 Buf_Init(&buf); 1852 1853 do { 1854 char result[BUFSIZ]; 1855 bytes_read = read(pipefds[0], result, sizeof result); 1856 if (bytes_read > 0) 1857 Buf_AddBytes(&buf, result, (size_t)bytes_read); 1858 } while (bytes_read > 0 || 1859 (bytes_read == -1 && errno == EINTR)); 1860 if (bytes_read == -1) 1861 savederr = errno; 1862 1863 (void)close(pipefds[0]); /* Close the input side of the pipe. */ 1864 1865 /* Wait for the process to exit. */ 1866 while ((pid = waitpid(cpid, &status, 0)) != cpid && pid >= 0) 1867 JobReapChild(pid, status, FALSE); 1868 1869 res_len = Buf_Len(&buf); 1870 res = Buf_Destroy(&buf, FALSE); 1871 1872 if (savederr != 0) 1873 *errfmt = "Couldn't read shell's output for \"%s\""; 1874 1875 if (WIFSIGNALED(status)) 1876 *errfmt = "\"%s\" exited on a signal"; 1877 else if (WEXITSTATUS(status) != 0) 1878 *errfmt = "\"%s\" returned non-zero status"; 1879 1880 /* Convert newlines to spaces. A final newline is just stripped */ 1881 if (res_len > 0 && res[res_len - 1] == '\n') 1882 res[res_len - 1] = '\0'; 1883 for (cp = res; *cp != '\0'; cp++) 1884 if (*cp == '\n') 1885 *cp = ' '; 1886 break; 1887 } 1888 return res; 1889 bad: 1890 return bmake_strdup(""); 1891 } 1892 1893 /* 1894 * Print a printf-style error message. 1895 * 1896 * In default mode, this error message has no consequences, in particular it 1897 * does not affect the exit status. Only in lint mode (-dL) it does. 1898 */ 1899 void 1900 Error(const char *fmt, ...) 1901 { 1902 va_list ap; 1903 FILE *err_file; 1904 1905 err_file = opts.debug_file; 1906 if (err_file == stdout) 1907 err_file = stderr; 1908 (void)fflush(stdout); 1909 for (;;) { 1910 va_start(ap, fmt); 1911 fprintf(err_file, "%s: ", progname); 1912 (void)vfprintf(err_file, fmt, ap); 1913 va_end(ap); 1914 (void)fprintf(err_file, "\n"); 1915 (void)fflush(err_file); 1916 if (err_file == stderr) 1917 break; 1918 err_file = stderr; 1919 } 1920 main_errors++; 1921 } 1922 1923 /* 1924 * Wait for any running jobs to finish, then produce an error message, 1925 * finally exit immediately. 1926 * 1927 * Exiting immediately differs from Parse_Error, which exits only after the 1928 * current top-level makefile has been parsed completely. 1929 */ 1930 void 1931 Fatal(const char *fmt, ...) 1932 { 1933 va_list ap; 1934 1935 if (jobsRunning) 1936 Job_Wait(); 1937 1938 (void)fflush(stdout); 1939 va_start(ap, fmt); 1940 (void)vfprintf(stderr, fmt, ap); 1941 va_end(ap); 1942 (void)fprintf(stderr, "\n"); 1943 (void)fflush(stderr); 1944 1945 PrintOnError(NULL, NULL); 1946 1947 if (DEBUG(GRAPH2) || DEBUG(GRAPH3)) 1948 Targ_PrintGraph(2); 1949 Trace_Log(MAKEERROR, NULL); 1950 exit(2); /* Not 1 so -q can distinguish error */ 1951 } 1952 1953 /* 1954 * Major exception once jobs are being created. 1955 * Kills all jobs, prints a message and exits. 1956 */ 1957 void 1958 Punt(const char *fmt, ...) 1959 { 1960 va_list ap; 1961 1962 va_start(ap, fmt); 1963 (void)fflush(stdout); 1964 (void)fprintf(stderr, "%s: ", progname); 1965 (void)vfprintf(stderr, fmt, ap); 1966 va_end(ap); 1967 (void)fprintf(stderr, "\n"); 1968 (void)fflush(stderr); 1969 1970 PrintOnError(NULL, NULL); 1971 1972 DieHorribly(); 1973 } 1974 1975 /* Exit without giving a message. */ 1976 void 1977 DieHorribly(void) 1978 { 1979 if (jobsRunning) 1980 Job_AbortAll(); 1981 if (DEBUG(GRAPH2)) 1982 Targ_PrintGraph(2); 1983 Trace_Log(MAKEERROR, NULL); 1984 exit(2); /* Not 1 so -q can distinguish error */ 1985 } 1986 1987 /* 1988 * Called when aborting due to errors in child shell to signal abnormal exit. 1989 * The program exits. 1990 * Errors is the number of errors encountered in Make_Make. 1991 */ 1992 void 1993 Finish(int errs) 1994 { 1995 if (shouldDieQuietly(NULL, -1)) 1996 exit(2); 1997 Fatal("%d error%s", errs, errs == 1 ? "" : "s"); 1998 } 1999 2000 /* 2001 * eunlink -- 2002 * Remove a file carefully, avoiding directories. 2003 */ 2004 int 2005 eunlink(const char *file) 2006 { 2007 struct stat st; 2008 2009 if (lstat(file, &st) == -1) 2010 return -1; 2011 2012 if (S_ISDIR(st.st_mode)) { 2013 errno = EISDIR; 2014 return -1; 2015 } 2016 return unlink(file); 2017 } 2018 2019 static void 2020 write_all(int fd, const void *data, size_t n) 2021 { 2022 const char *mem = data; 2023 2024 while (n > 0) { 2025 ssize_t written = write(fd, mem, n); 2026 if (written == -1 && errno == EAGAIN) 2027 continue; 2028 if (written == -1) 2029 break; 2030 mem += written; 2031 n -= (size_t)written; 2032 } 2033 } 2034 2035 /* 2036 * execDie -- 2037 * Print why exec failed, avoiding stdio. 2038 */ 2039 void MAKE_ATTR_DEAD 2040 execDie(const char *af, const char *av) 2041 { 2042 Buffer buf; 2043 2044 Buf_Init(&buf); 2045 Buf_AddStr(&buf, progname); 2046 Buf_AddStr(&buf, ": "); 2047 Buf_AddStr(&buf, af); 2048 Buf_AddStr(&buf, "("); 2049 Buf_AddStr(&buf, av); 2050 Buf_AddStr(&buf, ") failed ("); 2051 Buf_AddStr(&buf, strerror(errno)); 2052 Buf_AddStr(&buf, ")\n"); 2053 2054 write_all(STDERR_FILENO, Buf_GetAll(&buf, NULL), Buf_Len(&buf)); 2055 2056 Buf_Destroy(&buf, TRUE); 2057 _exit(1); 2058 } 2059 2060 /* purge any relative paths */ 2061 static void 2062 purge_relative_cached_realpaths(void) 2063 { 2064 HashEntry *he, *nhe; 2065 HashIter hi; 2066 2067 HashIter_Init(&hi, &cached_realpaths); 2068 he = HashIter_Next(&hi); 2069 while (he != NULL) { 2070 nhe = HashIter_Next(&hi); 2071 if (he->key[0] != '/') { 2072 DEBUG1(DIR, "cached_realpath: purging %s\n", he->key); 2073 HashTable_DeleteEntry(&cached_realpaths, he); 2074 /* XXX: What about the allocated he->value? Either 2075 * free them or document why they cannot be freed. */ 2076 } 2077 he = nhe; 2078 } 2079 } 2080 2081 char * 2082 cached_realpath(const char *pathname, char *resolved) 2083 { 2084 const char *rp; 2085 2086 if (pathname == NULL || pathname[0] == '\0') 2087 return NULL; 2088 2089 rp = HashTable_FindValue(&cached_realpaths, pathname); 2090 if (rp != NULL) { 2091 /* a hit */ 2092 strncpy(resolved, rp, MAXPATHLEN); 2093 resolved[MAXPATHLEN - 1] = '\0'; 2094 return resolved; 2095 } 2096 2097 rp = realpath(pathname, resolved); 2098 if (rp != NULL) { 2099 HashTable_Set(&cached_realpaths, pathname, bmake_strdup(rp)); 2100 DEBUG2(DIR, "cached_realpath: %s -> %s\n", pathname, rp); 2101 return resolved; 2102 } 2103 2104 /* should we negative-cache? */ 2105 return NULL; 2106 } 2107 2108 /* 2109 * Return true if we should die without noise. 2110 * For example our failing child was a sub-make or failure happened elsewhere. 2111 */ 2112 Boolean 2113 shouldDieQuietly(GNode *gn, int bf) 2114 { 2115 static int quietly = -1; 2116 2117 if (quietly < 0) { 2118 if (DEBUG(JOB) || !GetBooleanVar(".MAKE.DIE_QUIETLY", TRUE)) 2119 quietly = 0; 2120 else if (bf >= 0) 2121 quietly = bf; 2122 else 2123 quietly = (gn != NULL && (gn->type & OP_MAKE)) ? 1 : 0; 2124 } 2125 return quietly; 2126 } 2127 2128 static void 2129 SetErrorVars(GNode *gn) 2130 { 2131 StringListNode *ln; 2132 2133 /* 2134 * We can print this even if there is no .ERROR target. 2135 */ 2136 Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL); 2137 Var_Delete(".ERROR_CMD", VAR_GLOBAL); 2138 2139 for (ln = gn->commands.first; ln != NULL; ln = ln->next) { 2140 const char *cmd = ln->datum; 2141 2142 if (cmd == NULL) 2143 break; 2144 Var_Append(".ERROR_CMD", cmd, VAR_GLOBAL); 2145 } 2146 } 2147 2148 /* 2149 * Print some helpful information in case of an error. 2150 * The caller should exit soon after calling this function. 2151 */ 2152 void 2153 PrintOnError(GNode *gn, const char *msg) 2154 { 2155 static GNode *errorNode = NULL; 2156 2157 if (DEBUG(HASH)) { 2158 Targ_Stats(); 2159 Var_Stats(); 2160 } 2161 2162 if (errorNode != NULL) 2163 return; /* we've been here! */ 2164 2165 if (msg != NULL) 2166 printf("%s", msg); 2167 printf("\n%s: stopped in %s\n", progname, curdir); 2168 2169 /* we generally want to keep quiet if a sub-make died */ 2170 if (shouldDieQuietly(gn, -1)) 2171 return; 2172 2173 if (gn != NULL) 2174 SetErrorVars(gn); 2175 2176 { 2177 char *errorVarsValues; 2178 (void)Var_Subst("${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}", 2179 VAR_GLOBAL, VARE_WANTRES, &errorVarsValues); 2180 /* TODO: handle errors */ 2181 printf("%s", errorVarsValues); 2182 free(errorVarsValues); 2183 } 2184 2185 fflush(stdout); 2186 2187 /* 2188 * Finally, see if there is a .ERROR target, and run it if so. 2189 */ 2190 errorNode = Targ_FindNode(".ERROR"); 2191 if (errorNode != NULL) { 2192 errorNode->type |= OP_SPECIAL; 2193 Compat_Make(errorNode, errorNode); 2194 } 2195 } 2196 2197 void 2198 Main_ExportMAKEFLAGS(Boolean first) 2199 { 2200 static Boolean once = TRUE; 2201 const char *expr; 2202 char *s; 2203 2204 if (once != first) 2205 return; 2206 once = FALSE; 2207 2208 expr = "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}"; 2209 (void)Var_Subst(expr, VAR_CMDLINE, VARE_WANTRES, &s); 2210 /* TODO: handle errors */ 2211 if (s[0] != '\0') { 2212 #ifdef POSIX 2213 setenv("MAKEFLAGS", s, 1); 2214 #else 2215 setenv("MAKE", s, 1); 2216 #endif 2217 } 2218 } 2219 2220 char * 2221 getTmpdir(void) 2222 { 2223 static char *tmpdir = NULL; 2224 struct stat st; 2225 2226 if (tmpdir != NULL) 2227 return tmpdir; 2228 2229 /* Honor $TMPDIR but only if it is valid. Ensure it ends with '/'. */ 2230 (void)Var_Subst("${TMPDIR:tA:U" _PATH_TMP "}/", 2231 VAR_GLOBAL, VARE_WANTRES, &tmpdir); 2232 /* TODO: handle errors */ 2233 2234 if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) { 2235 free(tmpdir); 2236 tmpdir = bmake_strdup(_PATH_TMP); 2237 } 2238 return tmpdir; 2239 } 2240 2241 /* 2242 * Create and open a temp file using "pattern". 2243 * If out_fname is provided, set it to a copy of the filename created. 2244 * Otherwise unlink the file once open. 2245 */ 2246 int 2247 mkTempFile(const char *pattern, char **out_fname) 2248 { 2249 static char *tmpdir = NULL; 2250 char tfile[MAXPATHLEN]; 2251 int fd; 2252 2253 if (pattern == NULL) 2254 pattern = TMPPAT; 2255 if (tmpdir == NULL) 2256 tmpdir = getTmpdir(); 2257 if (pattern[0] == '/') { 2258 snprintf(tfile, sizeof tfile, "%s", pattern); 2259 } else { 2260 snprintf(tfile, sizeof tfile, "%s%s", tmpdir, pattern); 2261 } 2262 if ((fd = mkstemp(tfile)) < 0) 2263 Punt("Could not create temporary file %s: %s", tfile, 2264 strerror(errno)); 2265 if (out_fname != NULL) { 2266 *out_fname = bmake_strdup(tfile); 2267 } else { 2268 unlink(tfile); /* we just want the descriptor */ 2269 } 2270 return fd; 2271 } 2272 2273 /* 2274 * Convert a string representation of a boolean into a boolean value. 2275 * Anything that looks like "No", "False", "Off", "0" etc. is FALSE, 2276 * the empty string is the fallback, everything else is TRUE. 2277 */ 2278 Boolean 2279 ParseBoolean(const char *s, Boolean fallback) 2280 { 2281 char ch = ch_tolower(s[0]); 2282 if (ch == '\0') 2283 return fallback; 2284 if (ch == '0' || ch == 'f' || ch == 'n') 2285 return FALSE; 2286 if (ch == 'o') 2287 return ch_tolower(s[1]) != 'f'; 2288 return TRUE; 2289 } 2290