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