main.c revision 107964
11590Srgrimes/* 21590Srgrimes * Copyright (c) 1988, 1989, 1990, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * Copyright (c) 1989 by Berkeley Softworks 51590Srgrimes * All rights reserved. 61590Srgrimes * 71590Srgrimes * This code is derived from software contributed to Berkeley by 81590Srgrimes * Adam de Boor. 91590Srgrimes * 101590Srgrimes * Redistribution and use in source and binary forms, with or without 111590Srgrimes * modification, are permitted provided that the following conditions 121590Srgrimes * are met: 131590Srgrimes * 1. Redistributions of source code must retain the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer. 151590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 161590Srgrimes * notice, this list of conditions and the following disclaimer in the 171590Srgrimes * documentation and/or other materials provided with the distribution. 181590Srgrimes * 3. All advertising materials mentioning features or use of this software 191590Srgrimes * must display the following acknowledgement: 201590Srgrimes * This product includes software developed by the University of 211590Srgrimes * California, Berkeley and its contributors. 221590Srgrimes * 4. Neither the name of the University nor the names of its contributors 231590Srgrimes * may be used to endorse or promote products derived from this software 241590Srgrimes * without specific prior written permission. 251590Srgrimes * 261590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 271590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 281590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 291590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 301590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 311590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 321590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 331590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 341590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 351590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 361590Srgrimes * SUCH DAMAGE. 3762833Swsanchez * 3862833Swsanchez * @(#)main.c 8.3 (Berkeley) 3/19/94 391590Srgrimes */ 401590Srgrimes 411590Srgrimes#ifndef lint 4294595Sobrien#if 0 4394589Sobrienstatic char copyright[] = 4494589Sobrien"@(#) Copyright (c) 1988, 1989, 1990, 1993\n\ 4594589Sobrien The Regents of the University of California. All rights reserved.\n"; 4694595Sobrien#endif 471590Srgrimes#endif /* not lint */ 4894589Sobrien#include <sys/cdefs.h> 4994587Sobrien__FBSDID("$FreeBSD: head/usr.bin/make/main.c 107964 2002-12-17 04:26:22Z seanc $"); 501590Srgrimes 511590Srgrimes/*- 521590Srgrimes * main.c -- 531590Srgrimes * The main file for this entire program. Exit routines etc 541590Srgrimes * reside here. 551590Srgrimes * 561590Srgrimes * Utility functions defined in this file: 571590Srgrimes * Main_ParseArgLine Takes a line of arguments, breaks them and 581590Srgrimes * treats them as if they were given when first 591590Srgrimes * invoked. Used by the parse module to implement 601590Srgrimes * the .MFLAGS target. 611590Srgrimes */ 621590Srgrimes 631590Srgrimes#include <sys/types.h> 641590Srgrimes#include <sys/time.h> 651590Srgrimes#include <sys/param.h> 661590Srgrimes#include <sys/resource.h> 671590Srgrimes#include <sys/signal.h> 681590Srgrimes#include <sys/stat.h> 6939006Skato#if defined(__i386__) 7039006Skato#include <sys/sysctl.h> 7139006Skato#endif 7218730Ssteve#ifndef MACHINE 735814Sjkh#include <sys/utsname.h> 7418730Ssteve#endif 7518730Ssteve#include <sys/wait.h> 7627644Scharnier#include <err.h> 7729957Simp#include <stdlib.h> 781590Srgrimes#include <errno.h> 791590Srgrimes#include <fcntl.h> 801590Srgrimes#include <stdio.h> 8149331Shoek#include <sysexits.h> 821590Srgrimes#include <stdarg.h> 8363955Simp#include <unistd.h> 841590Srgrimes#include "make.h" 851590Srgrimes#include "hash.h" 861590Srgrimes#include "dir.h" 871590Srgrimes#include "job.h" 881590Srgrimes#include "pathnames.h" 891590Srgrimes 90104395Sjmallett#define WANT_ENV_MKLVL 1 91104395Sjmallett 921590Srgrimes#ifndef DEFMAXLOCAL 931590Srgrimes#define DEFMAXLOCAL DEFMAXJOBS 9418730Ssteve#endif /* DEFMAXLOCAL */ 951590Srgrimes 961590Srgrimes#define MAKEFLAGS ".MAKEFLAGS" 971590Srgrimes 981590SrgrimesLst create; /* Targets to be made */ 991590Srgrimestime_t now; /* Time at start of make */ 1001590SrgrimesGNode *DEFAULT; /* .DEFAULT node */ 1011590SrgrimesBoolean allPrecious; /* .PRECIOUS given on line by itself */ 1021590Srgrimes 1031590Srgrimesstatic Boolean noBuiltins; /* -r flag */ 1041590Srgrimesstatic Lst makefiles; /* ordered list of makefiles to read */ 10566365Speterstatic Boolean expandVars; /* fully expand printed variables */ 10617193Sbdestatic Lst variables; /* list of variables to print */ 10718730Ssteveint maxJobs; /* -j argument */ 10828228Sfsmpstatic Boolean forceJobs; /* -j argument given */ 1091590Srgrimesstatic int maxLocal; /* -L argument */ 1101590SrgrimesBoolean compatMake; /* -B argument */ 1111590SrgrimesBoolean debug; /* -d flag */ 1121590SrgrimesBoolean noExecute; /* -n flag */ 1131590SrgrimesBoolean keepgoing; /* -k flag */ 1141590SrgrimesBoolean queryFlag; /* -q flag */ 1151590SrgrimesBoolean touchFlag; /* -t flag */ 1161590SrgrimesBoolean usePipes; /* !-P flag */ 1171590SrgrimesBoolean ignoreErrors; /* -i flag */ 1181590SrgrimesBoolean beSilent; /* -s flag */ 11941151SdgBoolean beVerbose; /* -v flag */ 1201590SrgrimesBoolean oldVars; /* variable substitution style */ 1211590SrgrimesBoolean checkEnvFirst; /* -e flag */ 12249332ShoekLst envFirstVars; /* (-E) vars to override from env */ 123104818SjmallettBoolean jobsRunning; /* TRUE if the jobs might be running */ 1241590Srgrimes 12592921Simpstatic void MainParseArgs(int, char **); 12692921Simpchar * chdir_verify_path(char *, char *); 12792921Simpstatic int ReadMakefile(void *, void *); 12892921Simpstatic void usage(void); 1291590Srgrimes 1301590Srgrimesstatic char *curdir; /* startup directory */ 1311590Srgrimesstatic char *objdir; /* where we chdir'ed to */ 1321590Srgrimes 1331590Srgrimes/*- 1341590Srgrimes * MainParseArgs -- 1351590Srgrimes * Parse a given argument vector. Called from main() and from 1361590Srgrimes * Main_ParseArgLine() when the .MAKEFLAGS target is used. 1371590Srgrimes * 1381590Srgrimes * XXX: Deal with command line overriding .MAKEFLAGS in makefile 1391590Srgrimes * 1401590Srgrimes * Results: 1411590Srgrimes * None 1421590Srgrimes * 1431590Srgrimes * Side Effects: 1441590Srgrimes * Various global and local flags will be set depending on the flags 1451590Srgrimes * given 1461590Srgrimes */ 1471590Srgrimesstatic void 148104696SjmallettMainParseArgs(int argc, char **argv) 1491590Srgrimes{ 15036942Speter char *p; 1515814Sjkh int c; 1521590Srgrimes 1531590Srgrimes optind = 1; /* since we're called more than once */ 15418730Ssteve#ifdef REMOTE 155102393Sjmallett# define OPTFLAGS "BC:D:E:I:L:PSV:Xd:ef:ij:km:nqrstv" 1561590Srgrimes#else 157102393Sjmallett# define OPTFLAGS "BC:D:E:I:PSV:Xd:ef:ij:km:nqrstv" 1581590Srgrimes#endif 15924360Simprearg: while((c = getopt(argc, argv, OPTFLAGS)) != -1) { 1601590Srgrimes switch(c) { 161102393Sjmallett case 'C': 162107964Sseanc if (chdir(optarg) == -1) 163107964Sseanc err(1, "chdir %s", optarg); 164102393Sjmallett break; 1651590Srgrimes case 'D': 1661590Srgrimes Var_Set(optarg, "1", VAR_GLOBAL); 1671590Srgrimes Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); 1681590Srgrimes Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 1691590Srgrimes break; 1701590Srgrimes case 'I': 1711590Srgrimes Parse_AddIncludeDir(optarg); 1721590Srgrimes Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); 1731590Srgrimes Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 1741590Srgrimes break; 17517193Sbde case 'V': 17669531Swill (void)Lst_AtEnd(variables, (void *)optarg); 17717193Sbde Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); 17817193Sbde Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 17917193Sbde break; 18066365Speter case 'X': 18166365Speter expandVars = FALSE; 18266365Speter break; 1831590Srgrimes case 'B': 1841590Srgrimes compatMake = TRUE; 18528746Sfsmp Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL); 1861590Srgrimes break; 18718730Ssteve#ifdef REMOTE 18849331Shoek case 'L': { 18949331Shoek char *endptr; 19049331Shoek 19149331Shoek maxLocal = strtol(optarg, &endptr, 10); 19249331Shoek if (maxLocal < 0 || *endptr != '\0') { 19349938Shoek warnx("illegal number, -L argument -- %s", 19449938Shoek optarg); 19549938Shoek usage(); 19649331Shoek } 1971590Srgrimes Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL); 1981590Srgrimes Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 1991590Srgrimes break; 20049331Shoek } 20118730Ssteve#endif 2021590Srgrimes case 'P': 2031590Srgrimes usePipes = FALSE; 2041590Srgrimes Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL); 2051590Srgrimes break; 2061590Srgrimes case 'S': 2071590Srgrimes keepgoing = FALSE; 2081590Srgrimes Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); 2091590Srgrimes break; 2101590Srgrimes case 'd': { 2111590Srgrimes char *modules = optarg; 2121590Srgrimes 2131590Srgrimes for (; *modules; ++modules) 2141590Srgrimes switch (*modules) { 2151590Srgrimes case 'A': 2161590Srgrimes debug = ~0; 2171590Srgrimes break; 2181590Srgrimes case 'a': 2191590Srgrimes debug |= DEBUG_ARCH; 2201590Srgrimes break; 2211590Srgrimes case 'c': 2221590Srgrimes debug |= DEBUG_COND; 2231590Srgrimes break; 2241590Srgrimes case 'd': 2251590Srgrimes debug |= DEBUG_DIR; 2261590Srgrimes break; 2271590Srgrimes case 'f': 2281590Srgrimes debug |= DEBUG_FOR; 2291590Srgrimes break; 2301590Srgrimes case 'g': 2311590Srgrimes if (modules[1] == '1') { 2321590Srgrimes debug |= DEBUG_GRAPH1; 2331590Srgrimes ++modules; 2341590Srgrimes } 2351590Srgrimes else if (modules[1] == '2') { 2361590Srgrimes debug |= DEBUG_GRAPH2; 2371590Srgrimes ++modules; 2381590Srgrimes } 2391590Srgrimes break; 2401590Srgrimes case 'j': 2411590Srgrimes debug |= DEBUG_JOB; 2421590Srgrimes break; 24360569Swill case 'l': 24460569Swill debug |= DEBUG_LOUD; 24560569Swill break; 2461590Srgrimes case 'm': 2471590Srgrimes debug |= DEBUG_MAKE; 2481590Srgrimes break; 2491590Srgrimes case 's': 2501590Srgrimes debug |= DEBUG_SUFF; 2511590Srgrimes break; 2521590Srgrimes case 't': 2531590Srgrimes debug |= DEBUG_TARG; 2541590Srgrimes break; 2551590Srgrimes case 'v': 2561590Srgrimes debug |= DEBUG_VAR; 2571590Srgrimes break; 2581590Srgrimes default: 25927644Scharnier warnx("illegal argument to d option -- %c", *modules); 2601590Srgrimes usage(); 2611590Srgrimes } 2621590Srgrimes Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); 2631590Srgrimes Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 2641590Srgrimes break; 2651590Srgrimes } 26649332Shoek case 'E': 26794506Scharnier p = emalloc(strlen(optarg) + 1); 26849332Shoek (void)strcpy(p, optarg); 26969531Swill (void)Lst_AtEnd(envFirstVars, (void *)p); 27049332Shoek Var_Append(MAKEFLAGS, "-E", VAR_GLOBAL); 27149332Shoek Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 27249332Shoek break; 2731590Srgrimes case 'e': 2741590Srgrimes checkEnvFirst = TRUE; 2751590Srgrimes Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); 2761590Srgrimes break; 2771590Srgrimes case 'f': 27869531Swill (void)Lst_AtEnd(makefiles, (void *)optarg); 2791590Srgrimes break; 2801590Srgrimes case 'i': 2811590Srgrimes ignoreErrors = TRUE; 2821590Srgrimes Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); 2831590Srgrimes break; 28449331Shoek case 'j': { 28549331Shoek char *endptr; 28649331Shoek 28718730Ssteve forceJobs = TRUE; 28849331Shoek maxJobs = strtol(optarg, &endptr, 10); 28949331Shoek if (maxJobs <= 0 || *endptr != '\0') { 29049938Shoek warnx("illegal number, -j argument -- %s", 29149938Shoek optarg); 29249938Shoek usage(); 29349331Shoek } 29418730Ssteve#ifndef REMOTE 29518730Ssteve maxLocal = maxJobs; 29618730Ssteve#endif 2971590Srgrimes Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); 2981590Srgrimes Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 2991590Srgrimes break; 30049331Shoek } 3011590Srgrimes case 'k': 3021590Srgrimes keepgoing = TRUE; 3031590Srgrimes Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); 3041590Srgrimes break; 30518730Ssteve case 'm': 30618730Ssteve Dir_AddDir(sysIncPath, optarg); 30718730Ssteve Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); 30818730Ssteve Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL); 30918730Ssteve break; 3101590Srgrimes case 'n': 3111590Srgrimes noExecute = TRUE; 3121590Srgrimes Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); 3131590Srgrimes break; 3141590Srgrimes case 'q': 3151590Srgrimes queryFlag = TRUE; 3161590Srgrimes /* Kind of nonsensical, wot? */ 3171590Srgrimes Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); 3181590Srgrimes break; 3191590Srgrimes case 'r': 3201590Srgrimes noBuiltins = TRUE; 3211590Srgrimes Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); 3221590Srgrimes break; 3231590Srgrimes case 's': 3241590Srgrimes beSilent = TRUE; 3251590Srgrimes Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); 3261590Srgrimes break; 3271590Srgrimes case 't': 3281590Srgrimes touchFlag = TRUE; 3291590Srgrimes Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); 3301590Srgrimes break; 33141151Sdg case 'v': 33241151Sdg beVerbose = TRUE; 33341151Sdg Var_Append(MAKEFLAGS, "-v", VAR_GLOBAL); 33441151Sdg break; 3351590Srgrimes default: 3361590Srgrimes case '?': 3371590Srgrimes usage(); 3381590Srgrimes } 3391590Srgrimes } 3401590Srgrimes 3411590Srgrimes oldVars = TRUE; 3421590Srgrimes 3431590Srgrimes /* 3441590Srgrimes * See if the rest of the arguments are variable assignments and 3451590Srgrimes * perform them if so. Else take them to be targets and stuff them 3461590Srgrimes * on the end of the "create" list. 3471590Srgrimes */ 3481590Srgrimes for (argv += optind, argc -= optind; *argv; ++argv, --argc) 3491590Srgrimes if (Parse_IsVar(*argv)) 3501590Srgrimes Parse_DoVar(*argv, VAR_CMD); 3511590Srgrimes else { 3521590Srgrimes if (!**argv) 3531590Srgrimes Punt("illegal (null) argument."); 3541590Srgrimes if (**argv == '-') { 3551590Srgrimes if ((*argv)[1]) 3561590Srgrimes optind = 0; /* -flag... */ 3571590Srgrimes else 3581590Srgrimes optind = 1; /* - */ 3591590Srgrimes goto rearg; 3601590Srgrimes } 36169531Swill (void)Lst_AtEnd(create, (void *)estrdup(*argv)); 3621590Srgrimes } 3631590Srgrimes} 3641590Srgrimes 3651590Srgrimes/*- 3661590Srgrimes * Main_ParseArgLine -- 3671590Srgrimes * Used by the parse module when a .MFLAGS or .MAKEFLAGS target 3681590Srgrimes * is encountered and by main() when reading the .MAKEFLAGS envariable. 3691590Srgrimes * Takes a line of arguments and breaks it into its 3701590Srgrimes * component words and passes those words and the number of them to the 3711590Srgrimes * MainParseArgs function. 3721590Srgrimes * The line should have all its leading whitespace removed. 3731590Srgrimes * 3741590Srgrimes * Results: 3751590Srgrimes * None 3761590Srgrimes * 3771590Srgrimes * Side Effects: 3781590Srgrimes * Only those that come from the various arguments. 3791590Srgrimes */ 3801590Srgrimesvoid 381104696SjmallettMain_ParseArgLine(char *line) 3821590Srgrimes{ 3831590Srgrimes char **argv; /* Manufactured argument vector */ 3841590Srgrimes int argc; /* Number of arguments in argv */ 3851590Srgrimes 3861590Srgrimes if (line == NULL) 3871590Srgrimes return; 3881590Srgrimes for (; *line == ' '; ++line) 3891590Srgrimes continue; 3901590Srgrimes if (!*line) 3911590Srgrimes return; 3921590Srgrimes 3935814Sjkh argv = brk_string(line, &argc, TRUE); 3941590Srgrimes MainParseArgs(argc, argv); 3951590Srgrimes} 3961590Srgrimes 39718339Sswallacechar * 398104696Sjmallettchdir_verify_path(char *path, char *obpath) 39918339Sswallace{ 40018339Sswallace struct stat sb; 40118339Sswallace 40218339Sswallace if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { 40375973Sru if (chdir(path) == -1 || getcwd(obpath, MAXPATHLEN) == NULL) { 40427644Scharnier warn("warning: %s", path); 40518339Sswallace return 0; 40618339Sswallace } 40775973Sru return obpath; 40818339Sswallace } 40918339Sswallace 41018339Sswallace return 0; 41118339Sswallace} 41218339Sswallace 41318339Sswallace 4141590Srgrimes/*- 4151590Srgrimes * main -- 4161590Srgrimes * The main function, for obvious reasons. Initializes variables 4171590Srgrimes * and a few modules, then parses the arguments give it in the 4181590Srgrimes * environment and on the command line. Reads the system makefile 4191590Srgrimes * followed by either Makefile, makefile or the file given by the 4201590Srgrimes * -f argument. Sets the .MAKEFLAGS PMake variable based on all the 4211590Srgrimes * flags it has received by then uses either the Make or the Compat 4221590Srgrimes * module to create the initial list of targets. 4231590Srgrimes * 4241590Srgrimes * Results: 4251590Srgrimes * If -q was given, exits -1 if anything was out-of-date. Else it exits 4261590Srgrimes * 0. 4271590Srgrimes * 4281590Srgrimes * Side Effects: 4291590Srgrimes * The program exits when done. Targets are created. etc. etc. etc. 4301590Srgrimes */ 4311590Srgrimesint 432104696Sjmallettmain(int argc, char **argv) 4331590Srgrimes{ 4341590Srgrimes Lst targs; /* target nodes to create -- passed to Make_Init */ 4351590Srgrimes Boolean outOfDate = TRUE; /* FALSE if all targets up to date */ 43640500Sobrien struct stat sa; 43740500Sobrien char *p, *p1, *path, *pathp; 438104395Sjmallett#ifdef WANT_ENV_MKLVL 439104395Sjmallett#define MKLVL_MAXVAL 500 440104395Sjmallett#define MKLVL_ENVVAR "__MKLVL__" 441104395Sjmallett int iMkLvl = 0; 442104395Sjmallett char *szMkLvl = getenv(MKLVL_ENVVAR); 443104395Sjmallett#endif /* WANT_ENV_MKLVL */ 44473262Simp char mdpath[MAXPATHLEN]; 44573262Simp char obpath[MAXPATHLEN]; 44673262Simp char cdpath[MAXPATHLEN]; 4475814Sjkh char *machine = getenv("MACHINE"); 44844362Simp char *machine_arch = getenv("MACHINE_ARCH"); 44972679Skris char *machine_cpu = getenv("MACHINE_CPU"); 45018730Ssteve Lst sysMkPath; /* Path of sys.mk */ 45118730Ssteve char *cp = NULL, *start; 45218730Ssteve /* avoid faults on read-only strings */ 45318730Ssteve static char syspath[] = _PATH_DEFSYSPATH; 4541590Srgrimes 455104395Sjmallett#ifdef WANT_ENV_MKLVL 456104395Sjmallett if ((iMkLvl = szMkLvl ? atoi(szMkLvl) : 0) < 0) { 457104395Sjmallett iMkLvl = 0; 458104395Sjmallett } 459104395Sjmallett if (iMkLvl++ > MKLVL_MAXVAL) { 460104395Sjmallett errc(2, EAGAIN, 461104395Sjmallett "Max recursion level (%d) exceeded.", MKLVL_MAXVAL); 462104395Sjmallett } 463104395Sjmallett bzero(szMkLvl = emalloc(32), 32); 464104395Sjmallett sprintf(szMkLvl, "%d", iMkLvl); 465104395Sjmallett setenv(MKLVL_ENVVAR, szMkLvl, 1); 466104395Sjmallett#endif /* WANT_ENV_MKLVL */ 467104395Sjmallett 46864739Sgreen#if DEFSHELL == 2 46964739Sgreen /* 47064739Sgreen * Turn off ENV to make ksh happier. 47164739Sgreen */ 47264739Sgreen unsetenv("ENV"); 47364739Sgreen#endif 47464739Sgreen 47518730Ssteve#ifdef RLIMIT_NOFILE 4761590Srgrimes /* 47718730Ssteve * get rid of resource limit on file descriptors 47818730Ssteve */ 47918730Ssteve { 48018730Ssteve struct rlimit rl; 48118730Ssteve if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && 48218730Ssteve rl.rlim_cur != rl.rlim_max) { 48318730Ssteve rl.rlim_cur = rl.rlim_max; 48418730Ssteve (void) setrlimit(RLIMIT_NOFILE, &rl); 48518730Ssteve } 48618730Ssteve } 48718730Ssteve#endif 48818730Ssteve /* 48975974Sru * Find where we are... 4901590Srgrimes * All this code is so that we know where we are when we start up 4911590Srgrimes * on a different machine with pmake. 4921590Srgrimes */ 4931590Srgrimes curdir = cdpath; 49427644Scharnier if (getcwd(curdir, MAXPATHLEN) == NULL) 49527644Scharnier err(2, NULL); 4961590Srgrimes 49727644Scharnier if (stat(curdir, &sa) == -1) 49827644Scharnier err(2, "%s", curdir); 4991590Srgrimes 50053631Smarcel#if defined(__i386__) && defined(__FreeBSD_version) && \ 50153631Smarcel __FreeBSD_version > 300003 5025814Sjkh /* 50339006Skato * PC-98 kernel sets the `i386' string to the utsname.machine and 50439006Skato * it cannot be distinguished from IBM-PC by uname(3). Therefore, 50539006Skato * we check machine.ispc98 and adjust the machine variable before 50639006Skato * using usname(3) below. 50753631Smarcel * NOTE: machdep.ispc98 was defined on 1998/8/31. At that time, 50853631Smarcel * __FreeBSD_version was defined as 300003. So, this check can 50953631Smarcel * safely be done with any kernel with version > 300003. 51039006Skato */ 51139006Skato if (!machine) { 51239006Skato int ispc98; 51339006Skato size_t len; 51439006Skato 51539006Skato len = sizeof(ispc98); 51639006Skato if (!sysctlbyname("machdep.ispc98", &ispc98, &len, NULL, 0)) { 51739006Skato if (ispc98) 51839006Skato machine = "pc98"; 51939006Skato } 52039006Skato } 52139006Skato#endif 52239006Skato 52339006Skato /* 5245814Sjkh * Get the name of this type of MACHINE from utsname 5255814Sjkh * so we can share an executable for similar machines. 5265814Sjkh * (i.e. m68k: amiga hp300, mac68k, sun3, ...) 5275814Sjkh * 5285814Sjkh * Note that while MACHINE is decided at run-time, 5295814Sjkh * MACHINE_ARCH is always known at compile time. 5305814Sjkh */ 53118864Ssteve if (!machine) { 53218339Sswallace#ifndef MACHINE 53318730Ssteve struct utsname utsname; 53418730Ssteve 53594506Scharnier if (uname(&utsname) == -1) 53694506Scharnier err(2, "uname"); 5375814Sjkh machine = utsname.machine; 53818339Sswallace#else 53918339Sswallace machine = MACHINE; 54018339Sswallace#endif 5415814Sjkh } 5421590Srgrimes 54344362Simp if (!machine_arch) { 54444362Simp#ifndef MACHINE_ARCH 54544362Simp machine_arch = "unknown"; 54644362Simp#else 54744362Simp machine_arch = MACHINE_ARCH; 54844362Simp#endif 54944362Simp } 55044362Simp 5511590Srgrimes /* 55272679Skris * Set machine_cpu to the minumum supported CPU revision based 55372679Skris * on the target architecture, if not already set. 55472679Skris */ 55572679Skris if (!machine_cpu) { 55672679Skris if (!strcmp(machine_arch, "i386")) 55772679Skris machine_cpu = "i386"; 55872679Skris else if (!strcmp(machine_arch, "alpha")) 55972679Skris machine_cpu = "ev4"; 56072679Skris else 56172679Skris machine_cpu = "unknown"; 56272679Skris } 56372679Skris 56472679Skris /* 56518759Ssteve * The object directory location is determined using the 56618759Ssteve * following order of preference: 56718759Ssteve * 56818759Ssteve * 1. MAKEOBJDIRPREFIX`cwd` 56918759Ssteve * 2. MAKEOBJDIR 57018759Ssteve * 3. _PATH_OBJDIR.${MACHINE} 57118759Ssteve * 4. _PATH_OBJDIR 57249938Shoek * 5. _PATH_OBJDIRPREFIX`cwd` 57318759Ssteve * 57449938Shoek * If one of the first two fails, use the current directory. 57549938Shoek * If the remaining three all fail, use the current directory. 57618339Sswallace * 57718339Sswallace * Once things are initted, 57818339Sswallace * have to add the original directory to the search path, 5791590Srgrimes * and modify the paths for the Makefiles apropriately. The 5801590Srgrimes * current directory is also placed as a variable for make scripts. 5811590Srgrimes */ 58218339Sswallace if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) { 58318339Sswallace if (!(path = getenv("MAKEOBJDIR"))) { 58418339Sswallace path = _PATH_OBJDIR; 58518339Sswallace pathp = _PATH_OBJDIRPREFIX; 58618339Sswallace (void) snprintf(mdpath, MAXPATHLEN, "%s.%s", 58718339Sswallace path, machine); 58818339Sswallace if (!(objdir = chdir_verify_path(mdpath, obpath))) 58918339Sswallace if (!(objdir=chdir_verify_path(path, obpath))) { 59018339Sswallace (void) snprintf(mdpath, MAXPATHLEN, 59118339Sswallace "%s%s", pathp, curdir); 59218339Sswallace if (!(objdir=chdir_verify_path(mdpath, 59318339Sswallace obpath))) 59418339Sswallace objdir = curdir; 59518339Sswallace } 59618339Sswallace } 59718339Sswallace else if (!(objdir = chdir_verify_path(path, obpath))) 5981590Srgrimes objdir = curdir; 5991590Srgrimes } 60018339Sswallace else { 60118339Sswallace (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); 60218339Sswallace if (!(objdir = chdir_verify_path(mdpath, obpath))) 60318339Sswallace objdir = curdir; 60418339Sswallace } 6051590Srgrimes 6061590Srgrimes create = Lst_Init(FALSE); 6071590Srgrimes makefiles = Lst_Init(FALSE); 60849332Shoek envFirstVars = Lst_Init(FALSE); 60966365Speter expandVars = TRUE; 61017193Sbde variables = Lst_Init(FALSE); 6111590Srgrimes beSilent = FALSE; /* Print commands as executed */ 6121590Srgrimes ignoreErrors = FALSE; /* Pay attention to non-zero returns */ 6131590Srgrimes noExecute = FALSE; /* Execute all commands */ 6141590Srgrimes keepgoing = FALSE; /* Stop on error */ 6151590Srgrimes allPrecious = FALSE; /* Remove targets when interrupted */ 6161590Srgrimes queryFlag = FALSE; /* This is not just a check-run */ 6171590Srgrimes noBuiltins = FALSE; /* Read the built-in rules */ 6181590Srgrimes touchFlag = FALSE; /* Actually update targets */ 6191590Srgrimes usePipes = TRUE; /* Catch child output in pipes */ 6201590Srgrimes debug = 0; /* No debug verbosity, please. */ 6211590Srgrimes jobsRunning = FALSE; 6221590Srgrimes 62318730Ssteve maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ 62418730Ssteve#ifdef REMOTE 6251590Srgrimes maxJobs = DEFMAXJOBS; /* Set default max concurrency */ 6261590Srgrimes#else 62718730Ssteve maxJobs = maxLocal; 6281590Srgrimes#endif 62928228Sfsmp forceJobs = FALSE; /* No -j flag */ 63018730Ssteve compatMake = FALSE; /* No compat mode */ 6311590Srgrimes 6328874Srgrimes 6331590Srgrimes /* 6341590Srgrimes * Initialize the parsing, directory and variable modules to prepare 6351590Srgrimes * for the reading of inclusion paths and variable settings on the 6361590Srgrimes * command line 6371590Srgrimes */ 6381590Srgrimes Dir_Init(); /* Initialize directory structures so -I flags 6391590Srgrimes * can be processed correctly */ 6401590Srgrimes Parse_Init(); /* Need to initialize the paths of #include 6411590Srgrimes * directories */ 6421590Srgrimes Var_Init(); /* As well as the lists of variables for 6431590Srgrimes * parsing arguments */ 6445814Sjkh str_init(); 6451590Srgrimes if (objdir != curdir) 6461590Srgrimes Dir_AddDir(dirSearchPath, curdir); 6471590Srgrimes Var_Set(".CURDIR", curdir, VAR_GLOBAL); 6481590Srgrimes Var_Set(".OBJDIR", objdir, VAR_GLOBAL); 6491590Srgrimes 6501590Srgrimes /* 6511590Srgrimes * Initialize various variables. 6521590Srgrimes * MAKE also gets this name, for compatibility 6531590Srgrimes * .MAKEFLAGS gets set to the empty string just in case. 6541590Srgrimes * MFLAGS also gets initialized empty, for compatibility. 6551590Srgrimes */ 6561590Srgrimes Var_Set("MAKE", argv[0], VAR_GLOBAL); 6571590Srgrimes Var_Set(MAKEFLAGS, "", VAR_GLOBAL); 6581590Srgrimes Var_Set("MFLAGS", "", VAR_GLOBAL); 6595814Sjkh Var_Set("MACHINE", machine, VAR_GLOBAL); 66044362Simp Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL); 66172679Skris Var_Set("MACHINE_CPU", machine_cpu, VAR_GLOBAL); 66297121Sru#ifdef MAKE_VERSION 66397121Sru Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL); 66497121Sru#endif 6651590Srgrimes 6661590Srgrimes /* 6671590Srgrimes * First snag any flags out of the MAKE environment variable. 6681590Srgrimes * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's 6691590Srgrimes * in a different format). 6701590Srgrimes */ 6711590Srgrimes#ifdef POSIX 6721590Srgrimes Main_ParseArgLine(getenv("MAKEFLAGS")); 6731590Srgrimes#else 6741590Srgrimes Main_ParseArgLine(getenv("MAKE")); 6751590Srgrimes#endif 6768874Srgrimes 6771590Srgrimes MainParseArgs(argc, argv); 6781590Srgrimes 6791590Srgrimes /* 68028228Sfsmp * Be compatible if user did not specify -j and did not explicitly 68128228Sfsmp * turned compatibility on 68228228Sfsmp */ 68328228Sfsmp if (!compatMake && !forceJobs) 68428228Sfsmp compatMake = TRUE; 68528228Sfsmp 68628228Sfsmp /* 6871590Srgrimes * Initialize archive, target and suffix modules in preparation for 6881590Srgrimes * parsing the makefile(s) 6891590Srgrimes */ 6901590Srgrimes Arch_Init(); 6911590Srgrimes Targ_Init(); 6921590Srgrimes Suff_Init(); 6931590Srgrimes 69469527Swill DEFAULT = NULL; 6951590Srgrimes (void)time(&now); 6961590Srgrimes 6971590Srgrimes /* 6981590Srgrimes * Set up the .TARGETS variable to contain the list of targets to be 6991590Srgrimes * created. If none specified, make the variable empty -- the parser 7001590Srgrimes * will fill the thing in with the default or .MAIN target. 7011590Srgrimes */ 7021590Srgrimes if (!Lst_IsEmpty(create)) { 7031590Srgrimes LstNode ln; 7041590Srgrimes 70569527Swill for (ln = Lst_First(create); ln != NULL; 7061590Srgrimes ln = Lst_Succ(ln)) { 7071590Srgrimes char *name = (char *)Lst_Datum(ln); 7081590Srgrimes 7091590Srgrimes Var_Append(".TARGETS", name, VAR_GLOBAL); 7101590Srgrimes } 7111590Srgrimes } else 7121590Srgrimes Var_Set(".TARGETS", "", VAR_GLOBAL); 7131590Srgrimes 71418730Ssteve 7151590Srgrimes /* 71618730Ssteve * If no user-supplied system path was given (through the -m option) 71718730Ssteve * add the directories from the DEFSYSPATH (more than one may be given 71818730Ssteve * as dir1:...:dirn) to the system include path. 7191590Srgrimes */ 72018730Ssteve if (Lst_IsEmpty(sysIncPath)) { 72118730Ssteve for (start = syspath; *start != '\0'; start = cp) { 72218730Ssteve for (cp = start; *cp != '\0' && *cp != ':'; cp++) 72318730Ssteve continue; 72418730Ssteve if (*cp == '\0') { 72518730Ssteve Dir_AddDir(sysIncPath, start); 72618730Ssteve } else { 72718730Ssteve *cp++ = '\0'; 72818730Ssteve Dir_AddDir(sysIncPath, start); 72918730Ssteve } 73018730Ssteve } 73118730Ssteve } 7321590Srgrimes 73318730Ssteve /* 73418730Ssteve * Read in the built-in rules first, followed by the specified 73518730Ssteve * makefile, if it was (makefile != (char *) NULL), or the default 73618730Ssteve * Makefile and makefile, in that order, if it wasn't. 73718730Ssteve */ 73818730Ssteve if (!noBuiltins) { 73918730Ssteve LstNode ln; 74018730Ssteve 74118730Ssteve sysMkPath = Lst_Init (FALSE); 74218730Ssteve Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath); 74318730Ssteve if (Lst_IsEmpty(sysMkPath)) 74418730Ssteve Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); 74569531Swill ln = Lst_Find(sysMkPath, (void *)NULL, ReadMakefile); 74669527Swill if (ln != NULL) 74718730Ssteve Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 74818730Ssteve } 74918730Ssteve 7501590Srgrimes if (!Lst_IsEmpty(makefiles)) { 7511590Srgrimes LstNode ln; 7521590Srgrimes 75369531Swill ln = Lst_Find(makefiles, (void *)NULL, ReadMakefile); 75469527Swill if (ln != NULL) 7551590Srgrimes Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 75694594Sobrien } else if (!ReadMakefile("BSDmakefile", NULL)) 75794594Sobrien if (!ReadMakefile("makefile", NULL)) 75818730Ssteve (void)ReadMakefile("Makefile", NULL); 7591590Srgrimes 76018730Ssteve (void)ReadMakefile(".depend", NULL); 7611590Srgrimes 7625814Sjkh Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL); 763105826Sjmallett free(p1); 7641590Srgrimes 7651590Srgrimes /* Install all the flags into the MAKE envariable. */ 7665814Sjkh if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p) 7671590Srgrimes#ifdef POSIX 7681590Srgrimes setenv("MAKEFLAGS", p, 1); 7691590Srgrimes#else 7701590Srgrimes setenv("MAKE", p, 1); 7711590Srgrimes#endif 772105826Sjmallett free(p1); 7731590Srgrimes 7741590Srgrimes /* 7751590Srgrimes * For compatibility, look at the directories in the VPATH variable 7761590Srgrimes * and add them to the search path, if the variable is defined. The 7771590Srgrimes * variable's value is in the same format as the PATH envariable, i.e. 7781590Srgrimes * <directory>:<directory>:<directory>... 7791590Srgrimes */ 7801590Srgrimes if (Var_Exists("VPATH", VAR_CMD)) { 781104692Sjmallett char *vpath, savec; 7821590Srgrimes /* 7831590Srgrimes * GCC stores string constants in read-only memory, but 7841590Srgrimes * Var_Subst will want to write this thing, so store it 7851590Srgrimes * in an array 7861590Srgrimes */ 7871590Srgrimes static char VPATH[] = "${VPATH}"; 7881590Srgrimes 7891590Srgrimes vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE); 790104692Sjmallett path = vpath; 7911590Srgrimes do { 7921590Srgrimes /* skip to end of directory */ 793104692Sjmallett for (cp = path; *cp != ':' && *cp != '\0'; cp++) 7941590Srgrimes continue; 7951590Srgrimes /* Save terminator character so know when to stop */ 796104692Sjmallett savec = *cp; 797104692Sjmallett *cp = '\0'; 7981590Srgrimes /* Add directory to search path */ 799104692Sjmallett Dir_AddDir(dirSearchPath, path); 800104692Sjmallett *cp = savec; 801104692Sjmallett path = cp + 1; 8021590Srgrimes } while (savec == ':'); 80369531Swill (void)free(vpath); 8041590Srgrimes } 8051590Srgrimes 8061590Srgrimes /* 8071590Srgrimes * Now that all search paths have been read for suffixes et al, it's 8081590Srgrimes * time to add the default search path to their lists... 8091590Srgrimes */ 8101590Srgrimes Suff_DoPaths(); 8111590Srgrimes 8121590Srgrimes /* print the initial graph, if the user requested it */ 8131590Srgrimes if (DEBUG(GRAPH1)) 8141590Srgrimes Targ_PrintGraph(1); 8151590Srgrimes 81617193Sbde /* print the values of any variables requested by the user */ 817101460Sru if (!Lst_IsEmpty(variables)) { 81817193Sbde LstNode ln; 81917193Sbde 82069527Swill for (ln = Lst_First(variables); ln != NULL; 82117193Sbde ln = Lst_Succ(ln)) { 82266365Speter char *value; 82366365Speter if (expandVars) { 82494506Scharnier p1 = emalloc(strlen((char *)Lst_Datum(ln)) + 1 + 3); 82566365Speter /* This sprintf is safe, because of the malloc above */ 82666365Speter (void)sprintf(p1, "${%s}", (char *)Lst_Datum(ln)); 82766365Speter value = Var_Subst(NULL, p1, VAR_GLOBAL, FALSE); 82866365Speter } else { 82966365Speter value = Var_Value((char *)Lst_Datum(ln), 83066365Speter VAR_GLOBAL, &p1); 83166365Speter } 83217193Sbde printf("%s\n", value ? value : ""); 83366365Speter if (p1) 83466365Speter free(p1); 83517193Sbde } 836101460Sru } else { 83717193Sbde 8381590Srgrimes /* 839101460Sru * Have now read the entire graph and need to make a list of targets 840101460Sru * to create. If none was given on the command line, we consult the 841101460Sru * parsing module to find the main target(s) to create. 8421590Srgrimes */ 843101460Sru if (Lst_IsEmpty(create)) 844101460Sru targs = Parse_MainName(); 845101460Sru else 846101460Sru targs = Targ_FindList(create, TARG_CREATE); 847101460Sru 848101460Sru if (!compatMake) { 849101460Sru /* 850101460Sru * Initialize job module before traversing the graph, now that 851101460Sru * any .BEGIN and .END targets have been read. This is done 852101460Sru * only if the -q flag wasn't given (to prevent the .BEGIN from 853101460Sru * being executed should it exist). 854101460Sru */ 855101460Sru if (!queryFlag) { 856101460Sru if (maxLocal == -1) 857101460Sru maxLocal = maxJobs; 858101460Sru Job_Init(maxJobs, maxLocal); 859101460Sru jobsRunning = TRUE; 860101460Sru } 861101460Sru 862101460Sru /* Traverse the graph, checking on all the targets */ 863101460Sru outOfDate = Make_Run(targs); 864101460Sru } else { 865101460Sru /* 866101460Sru * Compat_Init will take care of creating all the targets as 867101460Sru * well as initializing the module. 868101460Sru */ 869101460Sru Compat_Run(targs); 8701590Srgrimes } 871101672Sru Lst_Destroy(targs, NOFREE); 87217193Sbde } 8738874Srgrimes 87417193Sbde Lst_Destroy(variables, NOFREE); 8755814Sjkh Lst_Destroy(makefiles, NOFREE); 87692921Simp Lst_Destroy(create, (void (*)(void *)) free); 8775814Sjkh 8781590Srgrimes /* print the graph now it's been processed if the user requested it */ 8791590Srgrimes if (DEBUG(GRAPH2)) 8801590Srgrimes Targ_PrintGraph(2); 8811590Srgrimes 8825814Sjkh Suff_End(); 8835814Sjkh Targ_End(); 8845814Sjkh Arch_End(); 8855814Sjkh str_end(); 8865814Sjkh Var_End(); 8875814Sjkh Parse_End(); 8885814Sjkh Dir_End(); 8895814Sjkh 8901590Srgrimes if (queryFlag && outOfDate) 8911590Srgrimes return(1); 8921590Srgrimes else 8931590Srgrimes return(0); 8941590Srgrimes} 8951590Srgrimes 8961590Srgrimes/*- 8971590Srgrimes * ReadMakefile -- 8981590Srgrimes * Open and parse the given makefile. 8991590Srgrimes * 9001590Srgrimes * Results: 9011590Srgrimes * TRUE if ok. FALSE if couldn't open file. 9021590Srgrimes * 9031590Srgrimes * Side Effects: 9041590Srgrimes * lots 9051590Srgrimes */ 9061590Srgrimesstatic Boolean 907104696SjmallettReadMakefile(void *p, void *q __unused) 9081590Srgrimes{ 909104696Sjmallett char *fname; /* makefile to read */ 9101590Srgrimes FILE *stream; 91173262Simp char *name, path[MAXPATHLEN]; 91297163Sjmallett char *MAKEFILE; 91394990Sru int setMAKEFILE; 9141590Srgrimes 915104696Sjmallett fname = p; 916104696Sjmallett 9171590Srgrimes if (!strcmp(fname, "-")) { 9181590Srgrimes Parse_File("(stdin)", stdin); 9191590Srgrimes Var_Set("MAKEFILE", "", VAR_GLOBAL); 9201590Srgrimes } else { 92194990Sru setMAKEFILE = strcmp(fname, ".depend"); 92294990Sru 9231590Srgrimes /* if we've chdir'd, rebuild the path name */ 9241590Srgrimes if (curdir != objdir && *fname != '/') { 92569390Swill (void)snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname); 926100733Simp /* 927100733Simp * XXX The realpath stuff breaks relative includes 928100733Simp * XXX in some cases. The problem likely is in 929100733Simp * XXX parse.c where it does special things in 930100733Simp * XXX ParseDoInclude if the file is relateive 931100733Simp * XXX or absolute and not a system file. There 932100733Simp * XXX it assumes that if the current file that's 933100733Simp * XXX being included is absolute, that any files 934100733Simp * XXX that it includes shouldn't do the -I path 935100733Simp * XXX stuff, which is inconsistant with historical 936100733Simp * XXX behavior. However, I can't pentrate the mists 937100733Simp * XXX further, so I'm putting this workaround in 938100733Simp * XXX here until such time as the underlying bug 939100733Simp * XXX can be fixed. 940100733Simp */ 941100733Simp#if THIS_BREAKS_THINGS 94297077Sjmallett if (realpath(path, path) != NULL && 94397077Sjmallett (stream = fopen(path, "r")) != NULL) { 94497163Sjmallett MAKEFILE = fname; 9451590Srgrimes fname = path; 9461590Srgrimes goto found; 9471590Srgrimes } 94897077Sjmallett } else if (realpath(fname, path) != NULL) { 94997163Sjmallett MAKEFILE = fname; 95097077Sjmallett fname = path; 95197077Sjmallett if ((stream = fopen(fname, "r")) != NULL) 95297077Sjmallett goto found; 95397077Sjmallett } 954100733Simp#else 955100733Simp if ((stream = fopen(path, "r")) != NULL) { 956100733Simp MAKEFILE = fname; 957100733Simp fname = path; 958100733Simp goto found; 959100733Simp } 960100733Simp } else { 961100733Simp MAKEFILE = fname; 962100733Simp if ((stream = fopen(fname, "r")) != NULL) 963100733Simp goto found; 964100733Simp } 965100733Simp#endif 9661590Srgrimes /* look in -I and system include directories. */ 9671590Srgrimes name = Dir_FindFile(fname, parseIncPath); 9681590Srgrimes if (!name) 9691590Srgrimes name = Dir_FindFile(fname, sysIncPath); 9701590Srgrimes if (!name || !(stream = fopen(name, "r"))) 9711590Srgrimes return(FALSE); 97297163Sjmallett MAKEFILE = fname = name; 9731590Srgrimes /* 9741590Srgrimes * set the MAKEFILE variable desired by System V fans -- the 9751590Srgrimes * placement of the setting here means it gets set to the last 9761590Srgrimes * makefile specified, as it is set by SysV make. 9771590Srgrimes */ 97894990Srufound: 97994990Sru if (setMAKEFILE) 98097163Sjmallett Var_Set("MAKEFILE", MAKEFILE, VAR_GLOBAL); 9811590Srgrimes Parse_File(fname, stream); 9821590Srgrimes (void)fclose(stream); 9831590Srgrimes } 9841590Srgrimes return(TRUE); 9851590Srgrimes} 9861590Srgrimes 9871590Srgrimes/*- 98818730Ssteve * Cmd_Exec -- 98918730Ssteve * Execute the command in cmd, and return the output of that command 99018730Ssteve * in a string. 99118730Ssteve * 99218730Ssteve * Results: 99318730Ssteve * A string containing the output of the command, or the empty string 994104121Sjmallett * If error is not NULL, it contains the reason for the command failure 99518730Ssteve * 99618730Ssteve * Side Effects: 99718730Ssteve * The string must be freed by the caller. 99818730Ssteve */ 99918730Sstevechar * 1000104696SjmallettCmd_Exec(char *cmd, char **error) 100118730Ssteve{ 100218730Ssteve char *args[4]; /* Args for invoking the shell */ 100318730Ssteve int fds[2]; /* Pipe streams */ 100418730Ssteve int cpid; /* Child PID */ 100518730Ssteve int pid; /* PID from wait() */ 100618730Ssteve char *res; /* result */ 100718730Ssteve int status; /* command exit status */ 100818730Ssteve Buffer buf; /* buffer to store the result */ 100918730Ssteve char *cp; 101018730Ssteve int cc; 101118730Ssteve 1012104121Sjmallett *error = NULL; 101318730Ssteve 101418730Ssteve /* 101518730Ssteve * Set up arguments for shell 101618730Ssteve */ 101718730Ssteve args[0] = "sh"; 101818730Ssteve args[1] = "-c"; 101918730Ssteve args[2] = cmd; 102018730Ssteve args[3] = NULL; 102118730Ssteve 102218730Ssteve /* 102318730Ssteve * Open a pipe for fetching its output 102418730Ssteve */ 102518730Ssteve if (pipe(fds) == -1) { 1026104121Sjmallett *error = "Couldn't create pipe for \"%s\""; 102718730Ssteve goto bad; 102818730Ssteve } 102918730Ssteve 103018730Ssteve /* 103118730Ssteve * Fork 103218730Ssteve */ 103318730Ssteve switch (cpid = vfork()) { 103418730Ssteve case 0: 103518730Ssteve /* 103618730Ssteve * Close input side of pipe 103718730Ssteve */ 103818730Ssteve (void) close(fds[0]); 103918730Ssteve 104018730Ssteve /* 104118730Ssteve * Duplicate the output stream to the shell's output, then 104218730Ssteve * shut the extra thing down. Note we don't fetch the error 104318730Ssteve * stream...why not? Why? 104418730Ssteve */ 104518730Ssteve (void) dup2(fds[1], 1); 104618730Ssteve (void) close(fds[1]); 104718730Ssteve 1048104123Sjmallett#if defined(DEFSHELL) && DEFSHELL == 0 1049104123Sjmallett (void) execv("/bin/csh", args); 1050104123Sjmallett#elif DEFSHELL == 1 105197251Sru (void) execv("/bin/sh", args); 105264739Sgreen#elif DEFSHELL == 2 105397251Sru (void) execv("/bin/ksh", args); 105464739Sgreen#else 105564739Sgreen#error "DEFSHELL must be 1 or 2." 105664739Sgreen#endif 105718730Ssteve _exit(1); 105818730Ssteve /*NOTREACHED*/ 105918730Ssteve 106018730Ssteve case -1: 1061104121Sjmallett *error = "Couldn't exec \"%s\""; 106218730Ssteve goto bad; 106318730Ssteve 106418730Ssteve default: 106518730Ssteve /* 106618730Ssteve * No need for the writing half 106718730Ssteve */ 106818730Ssteve (void) close(fds[1]); 106918730Ssteve 107018730Ssteve buf = Buf_Init (MAKE_BSIZE); 107118730Ssteve 107218730Ssteve do { 107318730Ssteve char result[BUFSIZ]; 107418730Ssteve cc = read(fds[0], result, sizeof(result)); 107518730Ssteve if (cc > 0) 107618730Ssteve Buf_AddBytes(buf, cc, (Byte *) result); 107718730Ssteve } 107818730Ssteve while (cc > 0 || (cc == -1 && errno == EINTR)); 107918730Ssteve 108018730Ssteve /* 108118730Ssteve * Close the input side of the pipe. 108218730Ssteve */ 108318730Ssteve (void) close(fds[0]); 108418730Ssteve 108518730Ssteve /* 108618730Ssteve * Wait for the process to exit. 108718730Ssteve */ 108818730Ssteve while(((pid = wait(&status)) != cpid) && (pid >= 0)) 108918730Ssteve continue; 109018730Ssteve 109118877Ssteve if (cc == -1) 1092104121Sjmallett *error = "Error reading shell's output for \"%s\""; 109318864Ssteve 109418730Ssteve res = (char *)Buf_GetAll (buf, &cc); 109518730Ssteve Buf_Destroy (buf, FALSE); 109618730Ssteve 109718730Ssteve if (status) 1098104121Sjmallett *error = "\"%s\" returned non-zero status"; 109918730Ssteve 110018730Ssteve /* 110118730Ssteve * Null-terminate the result, convert newlines to spaces and 110218730Ssteve * install it in the variable. 110318730Ssteve */ 110418730Ssteve res[cc] = '\0'; 110518730Ssteve cp = &res[cc] - 1; 110618730Ssteve 110718730Ssteve if (*cp == '\n') { 110818730Ssteve /* 110918730Ssteve * A final newline is just stripped 111018730Ssteve */ 111118730Ssteve *cp-- = '\0'; 111218730Ssteve } 111318730Ssteve while (cp >= res) { 111418730Ssteve if (*cp == '\n') { 111518730Ssteve *cp = ' '; 111618730Ssteve } 111718730Ssteve cp--; 111818730Ssteve } 111918730Ssteve break; 112018730Ssteve } 112118730Ssteve return res; 112218730Sstevebad: 112318730Ssteve res = emalloc(1); 112418730Ssteve *res = '\0'; 112518730Ssteve return res; 112618730Ssteve} 112718730Ssteve 11281590Srgrimes/* 11291590Srgrimes * usage -- 11301590Srgrimes * exit with usage message 11311590Srgrimes */ 11321590Srgrimesstatic void 1133104696Sjmallettusage(void) 11341590Srgrimes{ 113527644Scharnier (void)fprintf(stderr, "%s\n%s\n%s\n", 113649332Shoek"usage: make [-Beiknqrstv] [-D variable] [-d flags] [-E variable] [-f makefile]", 113727644Scharnier" [-I directory] [-j max_jobs] [-m directory] [-V variable]", 113827644Scharnier" [variable=value] [target ...]"); 11391590Srgrimes exit(2); 11401590Srgrimes} 1141