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