1 /* $NetBSD: main.c,v 1.38 1997/09/28 03:31:07 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1988, 1989, 1990, 1993 5 * The Regents of the University of California. All rights reserved. 6 * Copyright (c) 1989 by Berkeley Softworks 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Adam de Boor. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 */ 40 41 #ifdef MAKE_BOOTSTRAP 42 static char rcsid[] = "$NetBSD: main.c,v 1.38 1997/09/28 03:31:07 lukem Exp $"; 43 #else 44 #include <sys/cdefs.h> 45 #ifndef lint 46 __COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\n\ 47 The Regents of the University of California. All rights reserved.\n"); 48 #endif /* not lint */ 49 50 #ifndef lint 51 #if 0 52 static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; 53 #else 54 __RCSID("$NetBSD: main.c,v 1.38 1997/09/28 03:31:07 lukem Exp $"); 55 #endif 56 #endif /* not lint */ 57 #endif 58 59 /*- 60 * main.c -- 61 * The main file for this entire program. Exit routines etc 62 * reside here. 63 * 64 * Utility functions defined in this file: 65 * Main_ParseArgLine Takes a line of arguments, breaks them and 66 * treats them as if they were given when first 67 * invoked. Used by the parse module to implement 68 * the .MFLAGS target. 69 * 70 * Error Print a tagged error message. The global 71 * MAKE variable must have been defined. This 72 * takes a format string and two optional 73 * arguments for it. 74 * 75 * Fatal Print an error message and exit. Also takes 76 * a format string and two arguments. 77 * 78 * Punt Aborts all jobs and exits with a message. Also 79 * takes a format string and two arguments. 80 * 81 * Finish Finish things up by printing the number of 82 * errors which occured, as passed to it, and 83 * exiting. 84 */ 85 86 #include <sys/types.h> 87 #include <sys/time.h> 88 #include <sys/param.h> 89 #include <sys/resource.h> 90 #include <sys/signal.h> 91 #include <sys/stat.h> 92 #ifndef MAKE_BOOTSTRAP 93 #include <sys/utsname.h> 94 #endif 95 #include <sys/wait.h> 96 #include <errno.h> 97 #include <fcntl.h> 98 #include <stdio.h> 99 #include <stdlib.h> 100 #ifdef __STDC__ 101 #include <stdarg.h> 102 #else 103 #include <varargs.h> 104 #endif 105 #include "make.h" 106 #include "hash.h" 107 #include "dir.h" 108 #include "job.h" 109 #include "pathnames.h" 110 111 #ifndef DEFMAXLOCAL 112 #define DEFMAXLOCAL DEFMAXJOBS 113 #endif /* DEFMAXLOCAL */ 114 115 #define MAKEFLAGS ".MAKEFLAGS" 116 117 Lst create; /* Targets to be made */ 118 time_t now; /* Time at start of make */ 119 GNode *DEFAULT; /* .DEFAULT node */ 120 Boolean allPrecious; /* .PRECIOUS given on line by itself */ 121 122 static Boolean noBuiltins; /* -r flag */ 123 static Lst makefiles; /* ordered list of makefiles to read */ 124 static Boolean printVars; /* print value of one or more vars */ 125 static Lst variables; /* list of variables to print */ 126 int maxJobs; /* -j argument */ 127 static int maxLocal; /* -L argument */ 128 Boolean compatMake; /* -B argument */ 129 Boolean debug; /* -d flag */ 130 Boolean noExecute; /* -n flag */ 131 Boolean keepgoing; /* -k flag */ 132 Boolean queryFlag; /* -q flag */ 133 Boolean touchFlag; /* -t flag */ 134 Boolean usePipes; /* !-P flag */ 135 Boolean ignoreErrors; /* -i flag */ 136 Boolean beSilent; /* -s flag */ 137 Boolean oldVars; /* variable substitution style */ 138 Boolean checkEnvFirst; /* -e flag */ 139 Boolean mkIncPath; /* -m flag */ 140 static Boolean jobsRunning; /* TRUE if the jobs might be running */ 141 142 static void MainParseArgs __P((int, char **)); 143 char * chdir_verify_path __P((char *, char *)); 144 static int ReadMakefile __P((ClientData, ClientData)); 145 static void usage __P((void)); 146 147 static char *curdir; /* startup directory */ 148 static char *objdir; /* where we chdir'ed to */ 149 150 /*- 151 * MainParseArgs -- 152 * Parse a given argument vector. Called from main() and from 153 * Main_ParseArgLine() when the .MAKEFLAGS target is used. 154 * 155 * XXX: Deal with command line overriding .MAKEFLAGS in makefile 156 * 157 * Results: 158 * None 159 * 160 * Side Effects: 161 * Various global and local flags will be set depending on the flags 162 * given 163 */ 164 static void 165 MainParseArgs(argc, argv) 166 int argc; 167 char **argv; 168 { 169 extern int optind; 170 extern char *optarg; 171 int c; 172 int forceJobs = 0; 173 174 optind = 1; /* since we're called more than once */ 175 #ifdef REMOTE 176 # define OPTFLAGS "BD:I:L:PSV:d:ef:ij:km:nqrst" 177 #else 178 # define OPTFLAGS "BD:I:PSV:d:ef:ij:km:nqrst" 179 #endif 180 rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) { 181 switch(c) { 182 case 'D': 183 Var_Set(optarg, "1", VAR_GLOBAL); 184 Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); 185 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 186 break; 187 case 'I': 188 Parse_AddIncludeDir(optarg); 189 Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); 190 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 191 break; 192 case 'V': 193 printVars = TRUE; 194 (void)Lst_AtEnd(variables, (ClientData)optarg); 195 Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); 196 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 197 break; 198 case 'B': 199 compatMake = TRUE; 200 break; 201 #ifdef REMOTE 202 case 'L': 203 maxLocal = atoi(optarg); 204 Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL); 205 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 206 break; 207 #endif 208 case 'P': 209 usePipes = FALSE; 210 Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL); 211 break; 212 case 'S': 213 keepgoing = FALSE; 214 Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); 215 break; 216 case 'd': { 217 char *modules = optarg; 218 219 for (; *modules; ++modules) 220 switch (*modules) { 221 case 'A': 222 debug = ~0; 223 break; 224 case 'a': 225 debug |= DEBUG_ARCH; 226 break; 227 case 'c': 228 debug |= DEBUG_COND; 229 break; 230 case 'd': 231 debug |= DEBUG_DIR; 232 break; 233 case 'f': 234 debug |= DEBUG_FOR; 235 break; 236 case 'g': 237 if (modules[1] == '1') { 238 debug |= DEBUG_GRAPH1; 239 ++modules; 240 } 241 else if (modules[1] == '2') { 242 debug |= DEBUG_GRAPH2; 243 ++modules; 244 } 245 break; 246 case 'j': 247 debug |= DEBUG_JOB; 248 break; 249 case 'm': 250 debug |= DEBUG_MAKE; 251 break; 252 case 's': 253 debug |= DEBUG_SUFF; 254 break; 255 case 't': 256 debug |= DEBUG_TARG; 257 break; 258 case 'v': 259 debug |= DEBUG_VAR; 260 break; 261 default: 262 (void)fprintf(stderr, 263 "make: illegal argument to d option -- %c\n", 264 *modules); 265 usage(); 266 } 267 Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); 268 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 269 break; 270 } 271 case 'e': 272 checkEnvFirst = TRUE; 273 Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); 274 break; 275 case 'f': 276 (void)Lst_AtEnd(makefiles, (ClientData)optarg); 277 break; 278 case 'i': 279 ignoreErrors = TRUE; 280 Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); 281 break; 282 case 'j': 283 forceJobs = TRUE; 284 maxJobs = atoi(optarg); 285 #ifndef REMOTE 286 maxLocal = maxJobs; 287 #endif 288 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); 289 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 290 break; 291 case 'k': 292 keepgoing = TRUE; 293 Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); 294 break; 295 case 'm': 296 mkIncPath = TRUE; 297 (void) Dir_AddDir(sysIncPath, optarg); 298 Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); 299 Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 300 break; 301 case 'n': 302 noExecute = TRUE; 303 Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); 304 break; 305 case 'q': 306 queryFlag = TRUE; 307 /* Kind of nonsensical, wot? */ 308 Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); 309 break; 310 case 'r': 311 noBuiltins = TRUE; 312 Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); 313 break; 314 case 's': 315 beSilent = TRUE; 316 Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); 317 break; 318 case 't': 319 touchFlag = TRUE; 320 Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); 321 break; 322 default: 323 case '?': 324 usage(); 325 } 326 } 327 328 /* 329 * Be compatible if user did not specify -j and did not explicitly 330 * turned compatibility on 331 */ 332 if (!compatMake && !forceJobs) 333 compatMake = TRUE; 334 335 oldVars = TRUE; 336 337 /* 338 * See if the rest of the arguments are variable assignments and 339 * perform them if so. Else take them to be targets and stuff them 340 * on the end of the "create" list. 341 */ 342 for (argv += optind, argc -= optind; *argv; ++argv, --argc) 343 if (Parse_IsVar(*argv)) 344 Parse_DoVar(*argv, VAR_CMD); 345 else { 346 if (!**argv) 347 Punt("illegal (null) argument."); 348 if (**argv == '-') { 349 if ((*argv)[1]) 350 optind = 0; /* -flag... */ 351 else 352 optind = 1; /* - */ 353 goto rearg; 354 } 355 (void)Lst_AtEnd(create, (ClientData)estrdup(*argv)); 356 } 357 } 358 359 /*- 360 * Main_ParseArgLine -- 361 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target 362 * is encountered and by main() when reading the .MAKEFLAGS envariable. 363 * Takes a line of arguments and breaks it into its 364 * component words and passes those words and the number of them to the 365 * MainParseArgs function. 366 * The line should have all its leading whitespace removed. 367 * 368 * Results: 369 * None 370 * 371 * Side Effects: 372 * Only those that come from the various arguments. 373 */ 374 void 375 Main_ParseArgLine(line) 376 char *line; /* Line to fracture */ 377 { 378 char **argv; /* Manufactured argument vector */ 379 int argc; /* Number of arguments in argv */ 380 381 if (line == NULL) 382 return; 383 for (; *line == ' '; ++line) 384 continue; 385 if (!*line) 386 return; 387 388 argv = brk_string(line, &argc, TRUE); 389 MainParseArgs(argc, argv); 390 } 391 392 char * 393 chdir_verify_path(path, obpath) 394 char *path; 395 char *obpath; 396 { 397 struct stat sb; 398 399 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { 400 if (chdir(path)) { 401 (void)fprintf(stderr, "make warning: %s: %s.\n", 402 path, strerror(errno)); 403 return 0; 404 } 405 else { 406 if (path[0] != '/') { 407 (void) snprintf(obpath, MAXPATHLEN, "%s/%s", 408 curdir, path); 409 return obpath; 410 } 411 else 412 return path; 413 } 414 } 415 416 return 0; 417 } 418 419 420 /*- 421 * main -- 422 * The main function, for obvious reasons. Initializes variables 423 * and a few modules, then parses the arguments give it in the 424 * environment and on the command line. Reads the system makefile 425 * followed by either Makefile, makefile or the file given by the 426 * -f argument. Sets the .MAKEFLAGS PMake variable based on all the 427 * flags it has received by then uses either the Make or the Compat 428 * module to create the initial list of targets. 429 * 430 * Results: 431 * If -q was given, exits -1 if anything was out-of-date. Else it exits 432 * 0. 433 * 434 * Side Effects: 435 * The program exits when done. Targets are created. etc. etc. etc. 436 */ 437 int 438 main(argc, argv) 439 int argc; 440 char **argv; 441 { 442 Lst targs; /* target nodes to create -- passed to Make_Init */ 443 Boolean outOfDate = TRUE; /* FALSE if all targets up to date */ 444 struct stat sb, sa; 445 char *p, *p1, *path, *pathp, *pwd; 446 char mdpath[MAXPATHLEN + 1]; 447 char obpath[MAXPATHLEN + 1]; 448 char cdpath[MAXPATHLEN + 1]; 449 char *machine = getenv("MACHINE"); 450 char *machine_arch = getenv("MACHINE_ARCH"); 451 Lst sysMkPath; /* Path of sys.mk */ 452 char *cp = NULL, *start; 453 /* avoid faults on read-only strings */ 454 static char syspath[] = _PATH_DEFSYSPATH; 455 456 #ifdef RLIMIT_NOFILE 457 /* 458 * get rid of resource limit on file descriptors 459 */ 460 { 461 struct rlimit rl; 462 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && 463 rl.rlim_cur != rl.rlim_max) { 464 rl.rlim_cur = rl.rlim_max; 465 (void) setrlimit(RLIMIT_NOFILE, &rl); 466 } 467 } 468 #endif 469 /* 470 * Find where we are and take care of PWD for the automounter... 471 * All this code is so that we know where we are when we start up 472 * on a different machine with pmake. 473 */ 474 curdir = cdpath; 475 if (getcwd(curdir, MAXPATHLEN) == NULL) { 476 (void)fprintf(stderr, "make: %s.\n", strerror(errno)); 477 exit(2); 478 } 479 480 if (stat(curdir, &sa) == -1) { 481 (void)fprintf(stderr, "make: %s: %s.\n", 482 curdir, strerror(errno)); 483 exit(2); 484 } 485 486 if ((pwd = getenv("PWD")) != NULL) { 487 if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino && 488 sa.st_dev == sb.st_dev) 489 (void) strcpy(curdir, pwd); 490 } 491 492 /* 493 * Get the name of this type of MACHINE from utsname 494 * so we can share an executable for similar machines. 495 * (i.e. m68k: amiga hp300, mac68k, sun3, ...) 496 * 497 * Note that both MACHINE and MACHINE_ARCH are decided at 498 * run-time. 499 */ 500 if (!machine) { 501 #ifndef MAKE_BOOTSTRAP 502 struct utsname utsname; 503 504 if (uname(&utsname) == -1) { 505 perror("make: uname"); 506 exit(2); 507 } 508 machine = utsname.machine; 509 #else 510 machine = MACHINE; 511 #endif 512 } 513 514 if (!machine_arch) { 515 #ifndef MACHINE_ARCH 516 machine_arch = "unknown"; /* XXX: no uname -p yet */ 517 #else 518 machine_arch = MACHINE_ARCH; 519 #endif 520 } 521 522 /* 523 * If the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory 524 * exists, change into it and build there. (If a .${MACHINE} suffix 525 * exists, use that directory instead). 526 * Otherwise check MAKEOBJDIRPREFIX`cwd` (or by default, 527 * _PATH_OBJDIRPREFIX`cwd`) and build there if it exists. 528 * If all fails, use the current directory to build. 529 * 530 * Once things are initted, 531 * have to add the original directory to the search path, 532 * and modify the paths for the Makefiles apropriately. The 533 * current directory is also placed as a variable for make scripts. 534 */ 535 if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) { 536 if (!(path = getenv("MAKEOBJDIR"))) { 537 path = _PATH_OBJDIR; 538 pathp = _PATH_OBJDIRPREFIX; 539 (void) snprintf(mdpath, MAXPATHLEN, "%s.%s", 540 path, machine); 541 if (!(objdir = chdir_verify_path(mdpath, obpath))) 542 if (!(objdir=chdir_verify_path(path, obpath))) { 543 (void) snprintf(mdpath, MAXPATHLEN, 544 "%s%s", pathp, curdir); 545 if (!(objdir=chdir_verify_path(mdpath, 546 obpath))) 547 objdir = curdir; 548 } 549 } 550 else if (!(objdir = chdir_verify_path(path, obpath))) 551 objdir = curdir; 552 } 553 else { 554 (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); 555 if (!(objdir = chdir_verify_path(mdpath, obpath))) 556 objdir = curdir; 557 } 558 559 setenv("PWD", objdir, 1); 560 561 create = Lst_Init(FALSE); 562 makefiles = Lst_Init(FALSE); 563 printVars = FALSE; 564 variables = Lst_Init(FALSE); 565 beSilent = FALSE; /* Print commands as executed */ 566 ignoreErrors = FALSE; /* Pay attention to non-zero returns */ 567 noExecute = FALSE; /* Execute all commands */ 568 keepgoing = FALSE; /* Stop on error */ 569 allPrecious = FALSE; /* Remove targets when interrupted */ 570 queryFlag = FALSE; /* This is not just a check-run */ 571 noBuiltins = FALSE; /* Read the built-in rules */ 572 touchFlag = FALSE; /* Actually update targets */ 573 usePipes = TRUE; /* Catch child output in pipes */ 574 debug = 0; /* No debug verbosity, please. */ 575 jobsRunning = FALSE; 576 577 maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ 578 #ifdef REMOTE 579 maxJobs = DEFMAXJOBS; /* Set default max concurrency */ 580 #else 581 maxJobs = maxLocal; 582 #endif 583 compatMake = FALSE; /* No compat mode */ 584 585 586 /* 587 * Initialize the parsing, directory and variable modules to prepare 588 * for the reading of inclusion paths and variable settings on the 589 * command line 590 */ 591 592 /* 593 * Initialize directory structures so -I flags can be processed 594 * correctly, if we have a different objdir, then let the directory 595 * know our curdir. 596 */ 597 Dir_Init(curdir != objdir ? curdir : NULL); 598 Parse_Init(); /* Need to initialize the paths of #include 599 * directories */ 600 Var_Init(); /* As well as the lists of variables for 601 * parsing arguments */ 602 str_init(); 603 Var_Set(".CURDIR", curdir, VAR_GLOBAL); 604 Var_Set(".OBJDIR", objdir, VAR_GLOBAL); 605 606 /* 607 * Initialize various variables. 608 * MAKE also gets this name, for compatibility 609 * .MAKEFLAGS gets set to the empty string just in case. 610 * MFLAGS also gets initialized empty, for compatibility. 611 */ 612 Var_Set("MAKE", argv[0], VAR_GLOBAL); 613 Var_Set(MAKEFLAGS, "", VAR_GLOBAL); 614 Var_Set("MFLAGS", "", VAR_GLOBAL); 615 Var_Set("MACHINE", machine, VAR_GLOBAL); 616 Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL); 617 618 /* 619 * First snag any flags out of the MAKE environment variable. 620 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's 621 * in a different format). 622 */ 623 #ifdef POSIX 624 Main_ParseArgLine(getenv("MAKEFLAGS")); 625 #else 626 Main_ParseArgLine(getenv("MAKE")); 627 #endif 628 629 MainParseArgs(argc, argv); 630 631 /* 632 * Initialize archive, target and suffix modules in preparation for 633 * parsing the makefile(s) 634 */ 635 Arch_Init(); 636 Targ_Init(); 637 Suff_Init(); 638 639 DEFAULT = NILGNODE; 640 (void)time(&now); 641 642 /* 643 * Set up the .TARGETS variable to contain the list of targets to be 644 * created. If none specified, make the variable empty -- the parser 645 * will fill the thing in with the default or .MAIN target. 646 */ 647 if (!Lst_IsEmpty(create)) { 648 LstNode ln; 649 650 for (ln = Lst_First(create); ln != NILLNODE; 651 ln = Lst_Succ(ln)) { 652 char *name = (char *)Lst_Datum(ln); 653 654 Var_Append(".TARGETS", name, VAR_GLOBAL); 655 } 656 } else 657 Var_Set(".TARGETS", "", VAR_GLOBAL); 658 659 660 /* 661 * If no user-supplied system path was given (through the -m option) 662 * add the directories from the DEFSYSPATH (more than one may be given 663 * as dir1:...:dirn) to the system include path. 664 */ 665 if (!mkIncPath) { 666 for (start = syspath; *start != '\0'; start = cp) { 667 for (cp = start; *cp != '\0' && *cp != ':'; cp++) 668 continue; 669 if (*cp == '\0') { 670 (void) Dir_AddDir(sysIncPath, start); 671 } else { 672 *cp++ = '\0'; 673 (void) Dir_AddDir(sysIncPath, start); 674 } 675 } 676 } 677 678 /* 679 * Read in the built-in rules first, followed by the specified 680 * makefile, if it was (makefile != (char *) NULL), or the default 681 * Makefile and makefile, in that order, if it wasn't. 682 */ 683 if (!noBuiltins) { 684 LstNode ln; 685 686 sysMkPath = Lst_Init (FALSE); 687 Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath); 688 if (Lst_IsEmpty(sysMkPath)) 689 Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); 690 ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile); 691 if (ln != NILLNODE) 692 Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 693 } 694 695 if (!Lst_IsEmpty(makefiles)) { 696 LstNode ln; 697 698 ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile); 699 if (ln != NILLNODE) 700 Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 701 } else if (!ReadMakefile("makefile", NULL)) 702 (void)ReadMakefile("Makefile", NULL); 703 704 (void)ReadMakefile(".depend", NULL); 705 706 Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL); 707 if (p1) 708 free(p1); 709 710 /* Install all the flags into the MAKE envariable. */ 711 if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p) 712 #ifdef POSIX 713 setenv("MAKEFLAGS", p, 1); 714 #else 715 setenv("MAKE", p, 1); 716 #endif 717 if (p1) 718 free(p1); 719 720 /* 721 * For compatibility, look at the directories in the VPATH variable 722 * and add them to the search path, if the variable is defined. The 723 * variable's value is in the same format as the PATH envariable, i.e. 724 * <directory>:<directory>:<directory>... 725 */ 726 if (Var_Exists("VPATH", VAR_CMD)) { 727 char *vpath, *path, *cp, savec; 728 /* 729 * GCC stores string constants in read-only memory, but 730 * Var_Subst will want to write this thing, so store it 731 * in an array 732 */ 733 static char VPATH[] = "${VPATH}"; 734 735 vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE); 736 path = vpath; 737 do { 738 /* skip to end of directory */ 739 for (cp = path; *cp != ':' && *cp != '\0'; cp++) 740 continue; 741 /* Save terminator character so know when to stop */ 742 savec = *cp; 743 *cp = '\0'; 744 /* Add directory to search path */ 745 (void) Dir_AddDir(dirSearchPath, path); 746 *cp = savec; 747 path = cp + 1; 748 } while (savec == ':'); 749 (void)free((Address)vpath); 750 } 751 752 /* 753 * Now that all search paths have been read for suffixes et al, it's 754 * time to add the default search path to their lists... 755 */ 756 Suff_DoPaths(); 757 758 /* print the initial graph, if the user requested it */ 759 if (DEBUG(GRAPH1)) 760 Targ_PrintGraph(1); 761 762 /* print the values of any variables requested by the user */ 763 if (printVars) { 764 LstNode ln; 765 766 for (ln = Lst_First(variables); ln != NILLNODE; 767 ln = Lst_Succ(ln)) { 768 char *value = Var_Value((char *)Lst_Datum(ln), 769 VAR_GLOBAL, &p1); 770 771 printf("%s\n", value ? value : ""); 772 if (p1) 773 free(p1); 774 } 775 } 776 777 /* 778 * Have now read the entire graph and need to make a list of targets 779 * to create. If none was given on the command line, we consult the 780 * parsing module to find the main target(s) to create. 781 */ 782 if (Lst_IsEmpty(create)) 783 targs = Parse_MainName(); 784 else 785 targs = Targ_FindList(create, TARG_CREATE); 786 787 if (!compatMake && !printVars) { 788 /* 789 * Initialize job module before traversing the graph, now that 790 * any .BEGIN and .END targets have been read. This is done 791 * only if the -q flag wasn't given (to prevent the .BEGIN from 792 * being executed should it exist). 793 */ 794 if (!queryFlag) { 795 if (maxLocal == -1) 796 maxLocal = maxJobs; 797 Job_Init(maxJobs, maxLocal); 798 jobsRunning = TRUE; 799 } 800 801 /* Traverse the graph, checking on all the targets */ 802 outOfDate = Make_Run(targs); 803 } else if (!printVars) { 804 /* 805 * Compat_Init will take care of creating all the targets as 806 * well as initializing the module. 807 */ 808 Compat_Run(targs); 809 } 810 811 Lst_Destroy(targs, NOFREE); 812 Lst_Destroy(variables, NOFREE); 813 Lst_Destroy(makefiles, NOFREE); 814 Lst_Destroy(create, (void (*) __P((ClientData))) free); 815 816 /* print the graph now it's been processed if the user requested it */ 817 if (DEBUG(GRAPH2)) 818 Targ_PrintGraph(2); 819 820 Suff_End(); 821 Targ_End(); 822 Arch_End(); 823 str_end(); 824 Var_End(); 825 Parse_End(); 826 Dir_End(); 827 828 if (queryFlag && outOfDate) 829 return(1); 830 else 831 return(0); 832 } 833 834 /*- 835 * ReadMakefile -- 836 * Open and parse the given makefile. 837 * 838 * Results: 839 * TRUE if ok. FALSE if couldn't open file. 840 * 841 * Side Effects: 842 * lots 843 */ 844 static Boolean 845 ReadMakefile(p, q) 846 ClientData p, q; 847 { 848 char *fname = p; /* makefile to read */ 849 extern Lst parseIncPath; 850 FILE *stream; 851 char *name, path[MAXPATHLEN + 1]; 852 853 if (!strcmp(fname, "-")) { 854 Parse_File("(stdin)", stdin); 855 Var_Set("MAKEFILE", "", VAR_GLOBAL); 856 } else { 857 if ((stream = fopen(fname, "r")) != NULL) 858 goto found; 859 /* if we've chdir'd, rebuild the path name */ 860 if (curdir != objdir && *fname != '/') { 861 (void)sprintf(path, "%s/%s", curdir, fname); 862 if ((stream = fopen(path, "r")) != NULL) { 863 fname = path; 864 goto found; 865 } 866 } 867 /* look in -I and system include directories. */ 868 name = Dir_FindFile(fname, parseIncPath); 869 if (!name) 870 name = Dir_FindFile(fname, sysIncPath); 871 if (!name || !(stream = fopen(name, "r"))) 872 return(FALSE); 873 fname = name; 874 /* 875 * set the MAKEFILE variable desired by System V fans -- the 876 * placement of the setting here means it gets set to the last 877 * makefile specified, as it is set by SysV make. 878 */ 879 found: Var_Set("MAKEFILE", fname, VAR_GLOBAL); 880 Parse_File(fname, stream); 881 (void)fclose(stream); 882 } 883 return(TRUE); 884 } 885 886 /*- 887 * Cmd_Exec -- 888 * Execute the command in cmd, and return the output of that command 889 * in a string. 890 * 891 * Results: 892 * A string containing the output of the command, or the empty string 893 * If err is not NULL, it contains the reason for the command failure 894 * 895 * Side Effects: 896 * The string must be freed by the caller. 897 */ 898 char * 899 Cmd_Exec(cmd, err) 900 char *cmd; 901 char **err; 902 { 903 char *args[4]; /* Args for invoking the shell */ 904 int fds[2]; /* Pipe streams */ 905 int cpid; /* Child PID */ 906 int pid; /* PID from wait() */ 907 char *res; /* result */ 908 int status; /* command exit status */ 909 Buffer buf; /* buffer to store the result */ 910 char *cp; 911 int cc; 912 913 914 *err = NULL; 915 916 /* 917 * Set up arguments for shell 918 */ 919 args[0] = "sh"; 920 args[1] = "-c"; 921 args[2] = cmd; 922 args[3] = NULL; 923 924 /* 925 * Open a pipe for fetching its output 926 */ 927 if (pipe(fds) == -1) { 928 *err = "Couldn't create pipe for \"%s\""; 929 goto bad; 930 } 931 932 /* 933 * Fork 934 */ 935 switch (cpid = vfork()) { 936 case 0: 937 /* 938 * Close input side of pipe 939 */ 940 (void) close(fds[0]); 941 942 /* 943 * Duplicate the output stream to the shell's output, then 944 * shut the extra thing down. Note we don't fetch the error 945 * stream...why not? Why? 946 */ 947 (void) dup2(fds[1], 1); 948 (void) close(fds[1]); 949 950 (void) execv("/bin/sh", args); 951 _exit(1); 952 /*NOTREACHED*/ 953 954 case -1: 955 *err = "Couldn't exec \"%s\""; 956 goto bad; 957 958 default: 959 /* 960 * No need for the writing half 961 */ 962 (void) close(fds[1]); 963 964 buf = Buf_Init (MAKE_BSIZE); 965 966 do { 967 char result[BUFSIZ]; 968 cc = read(fds[0], result, sizeof(result)); 969 if (cc > 0) 970 Buf_AddBytes(buf, cc, (Byte *) result); 971 } 972 while (cc > 0 || (cc == -1 && errno == EINTR)); 973 974 /* 975 * Close the input side of the pipe. 976 */ 977 (void) close(fds[0]); 978 979 /* 980 * Wait for the process to exit. 981 */ 982 while(((pid = wait(&status)) != cpid) && (pid >= 0)) 983 continue; 984 985 res = (char *)Buf_GetAll (buf, &cc); 986 Buf_Destroy (buf, FALSE); 987 988 if (cc == 0) 989 *err = "Couldn't read shell's output for \"%s\""; 990 991 if (status) 992 *err = "\"%s\" returned non-zero status"; 993 994 /* 995 * Null-terminate the result, convert newlines to spaces and 996 * install it in the variable. 997 */ 998 res[cc] = '\0'; 999 cp = &res[cc] - 1; 1000 1001 if (*cp == '\n') { 1002 /* 1003 * A final newline is just stripped 1004 */ 1005 *cp-- = '\0'; 1006 } 1007 while (cp >= res) { 1008 if (*cp == '\n') { 1009 *cp = ' '; 1010 } 1011 cp--; 1012 } 1013 break; 1014 } 1015 return res; 1016 bad: 1017 res = emalloc(1); 1018 *res = '\0'; 1019 return res; 1020 } 1021 1022 /*- 1023 * Error -- 1024 * Print an error message given its format. 1025 * 1026 * Results: 1027 * None. 1028 * 1029 * Side Effects: 1030 * The message is printed. 1031 */ 1032 /* VARARGS */ 1033 void 1034 #ifdef __STDC__ 1035 Error(char *fmt, ...) 1036 #else 1037 Error(va_alist) 1038 va_dcl 1039 #endif 1040 { 1041 va_list ap; 1042 #ifdef __STDC__ 1043 va_start(ap, fmt); 1044 #else 1045 char *fmt; 1046 1047 va_start(ap); 1048 fmt = va_arg(ap, char *); 1049 #endif 1050 (void)vfprintf(stderr, fmt, ap); 1051 va_end(ap); 1052 (void)fprintf(stderr, "\n"); 1053 (void)fflush(stderr); 1054 } 1055 1056 /*- 1057 * Fatal -- 1058 * Produce a Fatal error message. If jobs are running, waits for them 1059 * to finish. 1060 * 1061 * Results: 1062 * None 1063 * 1064 * Side Effects: 1065 * The program exits 1066 */ 1067 /* VARARGS */ 1068 void 1069 #ifdef __STDC__ 1070 Fatal(char *fmt, ...) 1071 #else 1072 Fatal(va_alist) 1073 va_dcl 1074 #endif 1075 { 1076 va_list ap; 1077 #ifdef __STDC__ 1078 va_start(ap, fmt); 1079 #else 1080 char *fmt; 1081 1082 va_start(ap); 1083 fmt = va_arg(ap, char *); 1084 #endif 1085 if (jobsRunning) 1086 Job_Wait(); 1087 1088 (void)vfprintf(stderr, fmt, ap); 1089 va_end(ap); 1090 (void)fprintf(stderr, "\n"); 1091 (void)fflush(stderr); 1092 1093 if (DEBUG(GRAPH2)) 1094 Targ_PrintGraph(2); 1095 exit(2); /* Not 1 so -q can distinguish error */ 1096 } 1097 1098 /* 1099 * Punt -- 1100 * Major exception once jobs are being created. Kills all jobs, prints 1101 * a message and exits. 1102 * 1103 * Results: 1104 * None 1105 * 1106 * Side Effects: 1107 * All children are killed indiscriminately and the program Lib_Exits 1108 */ 1109 /* VARARGS */ 1110 void 1111 #ifdef __STDC__ 1112 Punt(char *fmt, ...) 1113 #else 1114 Punt(va_alist) 1115 va_dcl 1116 #endif 1117 { 1118 va_list ap; 1119 #ifdef __STDC__ 1120 va_start(ap, fmt); 1121 #else 1122 char *fmt; 1123 1124 va_start(ap); 1125 fmt = va_arg(ap, char *); 1126 #endif 1127 1128 (void)fprintf(stderr, "make: "); 1129 (void)vfprintf(stderr, fmt, ap); 1130 va_end(ap); 1131 (void)fprintf(stderr, "\n"); 1132 (void)fflush(stderr); 1133 1134 DieHorribly(); 1135 } 1136 1137 /*- 1138 * DieHorribly -- 1139 * Exit without giving a message. 1140 * 1141 * Results: 1142 * None 1143 * 1144 * Side Effects: 1145 * A big one... 1146 */ 1147 void 1148 DieHorribly() 1149 { 1150 if (jobsRunning) 1151 Job_AbortAll(); 1152 if (DEBUG(GRAPH2)) 1153 Targ_PrintGraph(2); 1154 exit(2); /* Not 1, so -q can distinguish error */ 1155 } 1156 1157 /* 1158 * Finish -- 1159 * Called when aborting due to errors in child shell to signal 1160 * abnormal exit. 1161 * 1162 * Results: 1163 * None 1164 * 1165 * Side Effects: 1166 * The program exits 1167 */ 1168 void 1169 Finish(errors) 1170 int errors; /* number of errors encountered in Make_Make */ 1171 { 1172 Fatal("%d error%s", errors, errors == 1 ? "" : "s"); 1173 } 1174 1175 /* 1176 * emalloc -- 1177 * malloc, but die on error. 1178 */ 1179 void * 1180 emalloc(len) 1181 size_t len; 1182 { 1183 void *p; 1184 1185 if ((p = malloc(len)) == NULL) 1186 enomem(); 1187 return(p); 1188 } 1189 1190 /* 1191 * estrdup -- 1192 * strdup, but die on error. 1193 */ 1194 char * 1195 estrdup(str) 1196 const char *str; 1197 { 1198 char *p; 1199 1200 if ((p = strdup(str)) == NULL) 1201 enomem(); 1202 return(p); 1203 } 1204 1205 /* 1206 * erealloc -- 1207 * realloc, but die on error. 1208 */ 1209 void * 1210 erealloc(ptr, size) 1211 void *ptr; 1212 size_t size; 1213 { 1214 if ((ptr = realloc(ptr, size)) == NULL) 1215 enomem(); 1216 return(ptr); 1217 } 1218 1219 /* 1220 * enomem -- 1221 * die when out of memory. 1222 */ 1223 void 1224 enomem() 1225 { 1226 (void)fprintf(stderr, "make: %s.\n", strerror(errno)); 1227 exit(2); 1228 } 1229 1230 /* 1231 * enunlink -- 1232 * Remove a file carefully, avoiding directories. 1233 */ 1234 int 1235 eunlink(file) 1236 const char *file; 1237 { 1238 struct stat st; 1239 1240 if (lstat(file, &st) == -1) 1241 return -1; 1242 1243 if (S_ISDIR(st.st_mode)) { 1244 errno = EISDIR; 1245 return -1; 1246 } 1247 return unlink(file); 1248 } 1249 1250 /* 1251 * usage -- 1252 * exit with usage message 1253 */ 1254 static void 1255 usage() 1256 { 1257 (void)fprintf(stderr, 1258 "usage: make [-Beiknqrst] [-D variable] [-d flags] [-f makefile ]\n\ 1259 [-I directory] [-j max_jobs] [-m directory] [-V variable]\n\ 1260 [variable=value] [target ...]\n"); 1261 exit(2); 1262 } 1263 1264 1265 int 1266 PrintAddr(a, b) 1267 ClientData a; 1268 ClientData b; 1269 { 1270 printf("%lx ", (unsigned long) a); 1271 return b ? 0 : 0; 1272 } 1273