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