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