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