main.c revision 120053
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 120053 2003-09-14 12:31:33Z ru $"); 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 4881590Srgrimes 4895814Sjkh /* 49039006Skato * PC-98 kernel sets the `i386' string to the utsname.machine and 49139006Skato * it cannot be distinguished from IBM-PC by uname(3). Therefore, 49239006Skato * we check machine.ispc98 and adjust the machine variable before 49339006Skato * using usname(3) below. 49453631Smarcel * NOTE: machdep.ispc98 was defined on 1998/8/31. At that time, 49553631Smarcel * __FreeBSD_version was defined as 300003. So, this check can 49653631Smarcel * safely be done with any kernel with version > 300003. 49739006Skato */ 49839006Skato if (!machine) { 49939006Skato int ispc98; 50039006Skato size_t len; 50139006Skato 50239006Skato len = sizeof(ispc98); 50339006Skato if (!sysctlbyname("machdep.ispc98", &ispc98, &len, NULL, 0)) { 50439006Skato if (ispc98) 50539006Skato machine = "pc98"; 50639006Skato } 50739006Skato } 50839006Skato 50939006Skato /* 5105814Sjkh * Get the name of this type of MACHINE from utsname 5115814Sjkh * so we can share an executable for similar machines. 5125814Sjkh * (i.e. m68k: amiga hp300, mac68k, sun3, ...) 5135814Sjkh * 5145814Sjkh * Note that while MACHINE is decided at run-time, 5155814Sjkh * MACHINE_ARCH is always known at compile time. 5165814Sjkh */ 51718864Ssteve if (!machine) { 51818339Sswallace#ifndef MACHINE 51918730Ssteve struct utsname utsname; 52018730Ssteve 52194506Scharnier if (uname(&utsname) == -1) 52294506Scharnier err(2, "uname"); 5235814Sjkh machine = utsname.machine; 52418339Sswallace#else 52518339Sswallace machine = MACHINE; 52618339Sswallace#endif 5275814Sjkh } 5281590Srgrimes 52944362Simp if (!machine_arch) { 53044362Simp#ifndef MACHINE_ARCH 53144362Simp machine_arch = "unknown"; 53244362Simp#else 53344362Simp machine_arch = MACHINE_ARCH; 53444362Simp#endif 53544362Simp } 53644362Simp 5371590Srgrimes /* 53872679Skris * Set machine_cpu to the minumum supported CPU revision based 53972679Skris * on the target architecture, if not already set. 54072679Skris */ 54172679Skris if (!machine_cpu) { 54272679Skris if (!strcmp(machine_arch, "i386")) 54372679Skris machine_cpu = "i386"; 54472679Skris else if (!strcmp(machine_arch, "alpha")) 54572679Skris machine_cpu = "ev4"; 54672679Skris else 54772679Skris machine_cpu = "unknown"; 54872679Skris } 5491590Srgrimes 5501590Srgrimes create = Lst_Init(FALSE); 5511590Srgrimes makefiles = Lst_Init(FALSE); 55249332Shoek envFirstVars = Lst_Init(FALSE); 55366365Speter expandVars = TRUE; 55417193Sbde variables = Lst_Init(FALSE); 5551590Srgrimes beSilent = FALSE; /* Print commands as executed */ 5561590Srgrimes ignoreErrors = FALSE; /* Pay attention to non-zero returns */ 5571590Srgrimes noExecute = FALSE; /* Execute all commands */ 5581590Srgrimes keepgoing = FALSE; /* Stop on error */ 5591590Srgrimes allPrecious = FALSE; /* Remove targets when interrupted */ 5601590Srgrimes queryFlag = FALSE; /* This is not just a check-run */ 5611590Srgrimes noBuiltins = FALSE; /* Read the built-in rules */ 5621590Srgrimes touchFlag = FALSE; /* Actually update targets */ 5631590Srgrimes usePipes = TRUE; /* Catch child output in pipes */ 5641590Srgrimes debug = 0; /* No debug verbosity, please. */ 5651590Srgrimes jobsRunning = FALSE; 5661590Srgrimes 56718730Ssteve maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */ 56818730Ssteve#ifdef REMOTE 5691590Srgrimes maxJobs = DEFMAXJOBS; /* Set default max concurrency */ 5701590Srgrimes#else 57118730Ssteve maxJobs = maxLocal; 5721590Srgrimes#endif 57328228Sfsmp forceJobs = FALSE; /* No -j flag */ 57418730Ssteve compatMake = FALSE; /* No compat mode */ 5751590Srgrimes 5768874Srgrimes 5771590Srgrimes /* 5781590Srgrimes * Initialize the parsing, directory and variable modules to prepare 5791590Srgrimes * for the reading of inclusion paths and variable settings on the 5801590Srgrimes * command line 5811590Srgrimes */ 5821590Srgrimes Dir_Init(); /* Initialize directory structures so -I flags 5831590Srgrimes * can be processed correctly */ 5841590Srgrimes Parse_Init(); /* Need to initialize the paths of #include 5851590Srgrimes * directories */ 5861590Srgrimes Var_Init(); /* As well as the lists of variables for 5871590Srgrimes * parsing arguments */ 5885814Sjkh str_init(); 5891590Srgrimes 5901590Srgrimes /* 5911590Srgrimes * Initialize various variables. 5921590Srgrimes * MAKE also gets this name, for compatibility 5931590Srgrimes * .MAKEFLAGS gets set to the empty string just in case. 5941590Srgrimes * MFLAGS also gets initialized empty, for compatibility. 5951590Srgrimes */ 5961590Srgrimes Var_Set("MAKE", argv[0], VAR_GLOBAL); 5971590Srgrimes Var_Set(MAKEFLAGS, "", VAR_GLOBAL); 5981590Srgrimes Var_Set("MFLAGS", "", VAR_GLOBAL); 5995814Sjkh Var_Set("MACHINE", machine, VAR_GLOBAL); 60044362Simp Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL); 60172679Skris Var_Set("MACHINE_CPU", machine_cpu, VAR_GLOBAL); 60297121Sru#ifdef MAKE_VERSION 60397121Sru Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL); 60497121Sru#endif 6051590Srgrimes 6061590Srgrimes /* 6071590Srgrimes * First snag any flags out of the MAKE environment variable. 6081590Srgrimes * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's 6091590Srgrimes * in a different format). 6101590Srgrimes */ 6111590Srgrimes#ifdef POSIX 6121590Srgrimes Main_ParseArgLine(getenv("MAKEFLAGS")); 6131590Srgrimes#else 6141590Srgrimes Main_ParseArgLine(getenv("MAKE")); 6151590Srgrimes#endif 6168874Srgrimes 6171590Srgrimes MainParseArgs(argc, argv); 6181590Srgrimes 6191590Srgrimes /* 620120053Sru * Find where we are... 621120053Sru * All this code is so that we know where we are when we start up 622120053Sru * on a different machine with pmake. 623120053Sru */ 624120053Sru curdir = cdpath; 625120053Sru if (getcwd(curdir, MAXPATHLEN) == NULL) 626120053Sru err(2, NULL); 627120053Sru 628120053Sru if (stat(curdir, &sa) == -1) 629120053Sru err(2, "%s", curdir); 630120053Sru 631120053Sru /* 632120053Sru * The object directory location is determined using the 633120053Sru * following order of preference: 634120053Sru * 635120053Sru * 1. MAKEOBJDIRPREFIX`cwd` 636120053Sru * 2. MAKEOBJDIR 637120053Sru * 3. _PATH_OBJDIR.${MACHINE} 638120053Sru * 4. _PATH_OBJDIR 639120053Sru * 5. _PATH_OBJDIRPREFIX`cwd` 640120053Sru * 641120053Sru * If one of the first two fails, use the current directory. 642120053Sru * If the remaining three all fail, use the current directory. 643120053Sru * 644120053Sru * Once things are initted, 645120053Sru * have to add the original directory to the search path, 646120053Sru * and modify the paths for the Makefiles apropriately. The 647120053Sru * current directory is also placed as a variable for make scripts. 648120053Sru */ 649120053Sru if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) { 650120053Sru if (!(path = getenv("MAKEOBJDIR"))) { 651120053Sru path = _PATH_OBJDIR; 652120053Sru pathp = _PATH_OBJDIRPREFIX; 653120053Sru (void) snprintf(mdpath, MAXPATHLEN, "%s.%s", 654120053Sru path, machine); 655120053Sru if (!(objdir = chdir_verify_path(mdpath, obpath))) 656120053Sru if (!(objdir=chdir_verify_path(path, obpath))) { 657120053Sru (void) snprintf(mdpath, MAXPATHLEN, 658120053Sru "%s%s", pathp, curdir); 659120053Sru if (!(objdir=chdir_verify_path(mdpath, 660120053Sru obpath))) 661120053Sru objdir = curdir; 662120053Sru } 663120053Sru } 664120053Sru else if (!(objdir = chdir_verify_path(path, obpath))) 665120053Sru objdir = curdir; 666120053Sru } 667120053Sru else { 668120053Sru (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir); 669120053Sru if (!(objdir = chdir_verify_path(mdpath, obpath))) 670120053Sru objdir = curdir; 671120053Sru } 672120053Sru Dir_InitDot(); /* Initialize the "." directory */ 673120053Sru if (objdir != curdir) 674120053Sru Dir_AddDir(dirSearchPath, curdir); 675120053Sru Var_Set(".CURDIR", curdir, VAR_GLOBAL); 676120053Sru Var_Set(".OBJDIR", objdir, VAR_GLOBAL); 677120053Sru 678120053Sru /* 67928228Sfsmp * Be compatible if user did not specify -j and did not explicitly 68028228Sfsmp * turned compatibility on 68128228Sfsmp */ 68228228Sfsmp if (!compatMake && !forceJobs) 68328228Sfsmp compatMake = TRUE; 68428228Sfsmp 68528228Sfsmp /* 6861590Srgrimes * Initialize archive, target and suffix modules in preparation for 6871590Srgrimes * parsing the makefile(s) 6881590Srgrimes */ 6891590Srgrimes Arch_Init(); 6901590Srgrimes Targ_Init(); 6911590Srgrimes Suff_Init(); 6921590Srgrimes 69369527Swill DEFAULT = NULL; 6941590Srgrimes (void)time(&now); 6951590Srgrimes 6961590Srgrimes /* 6971590Srgrimes * Set up the .TARGETS variable to contain the list of targets to be 6981590Srgrimes * created. If none specified, make the variable empty -- the parser 6991590Srgrimes * will fill the thing in with the default or .MAIN target. 7001590Srgrimes */ 7011590Srgrimes if (!Lst_IsEmpty(create)) { 7021590Srgrimes LstNode ln; 7031590Srgrimes 70469527Swill for (ln = Lst_First(create); ln != NULL; 7051590Srgrimes ln = Lst_Succ(ln)) { 7061590Srgrimes char *name = (char *)Lst_Datum(ln); 7071590Srgrimes 7081590Srgrimes Var_Append(".TARGETS", name, VAR_GLOBAL); 7091590Srgrimes } 7101590Srgrimes } else 7111590Srgrimes Var_Set(".TARGETS", "", VAR_GLOBAL); 7121590Srgrimes 71318730Ssteve 7141590Srgrimes /* 71518730Ssteve * If no user-supplied system path was given (through the -m option) 71618730Ssteve * add the directories from the DEFSYSPATH (more than one may be given 71718730Ssteve * as dir1:...:dirn) to the system include path. 7181590Srgrimes */ 71918730Ssteve if (Lst_IsEmpty(sysIncPath)) { 72018730Ssteve for (start = syspath; *start != '\0'; start = cp) { 72118730Ssteve for (cp = start; *cp != '\0' && *cp != ':'; cp++) 72218730Ssteve continue; 72318730Ssteve if (*cp == '\0') { 72418730Ssteve Dir_AddDir(sysIncPath, start); 72518730Ssteve } else { 72618730Ssteve *cp++ = '\0'; 72718730Ssteve Dir_AddDir(sysIncPath, start); 72818730Ssteve } 72918730Ssteve } 73018730Ssteve } 7311590Srgrimes 73218730Ssteve /* 73318730Ssteve * Read in the built-in rules first, followed by the specified 73418730Ssteve * makefile, if it was (makefile != (char *) NULL), or the default 73518730Ssteve * Makefile and makefile, in that order, if it wasn't. 73618730Ssteve */ 73718730Ssteve if (!noBuiltins) { 73818730Ssteve LstNode ln; 73918730Ssteve 74018730Ssteve sysMkPath = Lst_Init (FALSE); 74118730Ssteve Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath); 74218730Ssteve if (Lst_IsEmpty(sysMkPath)) 74318730Ssteve Fatal("make: no system rules (%s).", _PATH_DEFSYSMK); 74469531Swill ln = Lst_Find(sysMkPath, (void *)NULL, ReadMakefile); 74569527Swill if (ln != NULL) 74618730Ssteve Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 74718730Ssteve } 74818730Ssteve 7491590Srgrimes if (!Lst_IsEmpty(makefiles)) { 7501590Srgrimes LstNode ln; 7511590Srgrimes 75269531Swill ln = Lst_Find(makefiles, (void *)NULL, ReadMakefile); 75369527Swill if (ln != NULL) 7541590Srgrimes Fatal("make: cannot open %s.", (char *)Lst_Datum(ln)); 75594594Sobrien } else if (!ReadMakefile("BSDmakefile", NULL)) 75694594Sobrien if (!ReadMakefile("makefile", NULL)) 75718730Ssteve (void)ReadMakefile("Makefile", NULL); 7581590Srgrimes 75918730Ssteve (void)ReadMakefile(".depend", NULL); 7601590Srgrimes 7615814Sjkh Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL); 762105826Sjmallett free(p1); 7631590Srgrimes 7641590Srgrimes /* Install all the flags into the MAKE envariable. */ 7655814Sjkh if (((p = Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1)) != NULL) && *p) 7661590Srgrimes#ifdef POSIX 7671590Srgrimes setenv("MAKEFLAGS", p, 1); 7681590Srgrimes#else 7691590Srgrimes setenv("MAKE", p, 1); 7701590Srgrimes#endif 771105826Sjmallett free(p1); 7721590Srgrimes 7731590Srgrimes /* 7741590Srgrimes * For compatibility, look at the directories in the VPATH variable 7751590Srgrimes * and add them to the search path, if the variable is defined. The 7761590Srgrimes * variable's value is in the same format as the PATH envariable, i.e. 7771590Srgrimes * <directory>:<directory>:<directory>... 7781590Srgrimes */ 7791590Srgrimes if (Var_Exists("VPATH", VAR_CMD)) { 780104692Sjmallett char *vpath, savec; 7811590Srgrimes /* 7821590Srgrimes * GCC stores string constants in read-only memory, but 7831590Srgrimes * Var_Subst will want to write this thing, so store it 7841590Srgrimes * in an array 7851590Srgrimes */ 7861590Srgrimes static char VPATH[] = "${VPATH}"; 7871590Srgrimes 7881590Srgrimes vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE); 789104692Sjmallett path = vpath; 7901590Srgrimes do { 7911590Srgrimes /* skip to end of directory */ 792104692Sjmallett for (cp = path; *cp != ':' && *cp != '\0'; cp++) 7931590Srgrimes continue; 7941590Srgrimes /* Save terminator character so know when to stop */ 795104692Sjmallett savec = *cp; 796104692Sjmallett *cp = '\0'; 7971590Srgrimes /* Add directory to search path */ 798104692Sjmallett Dir_AddDir(dirSearchPath, path); 799104692Sjmallett *cp = savec; 800104692Sjmallett path = cp + 1; 8011590Srgrimes } while (savec == ':'); 80269531Swill (void)free(vpath); 8031590Srgrimes } 8041590Srgrimes 8051590Srgrimes /* 8061590Srgrimes * Now that all search paths have been read for suffixes et al, it's 8071590Srgrimes * time to add the default search path to their lists... 8081590Srgrimes */ 8091590Srgrimes Suff_DoPaths(); 8101590Srgrimes 8111590Srgrimes /* print the initial graph, if the user requested it */ 8121590Srgrimes if (DEBUG(GRAPH1)) 8131590Srgrimes Targ_PrintGraph(1); 8141590Srgrimes 81517193Sbde /* print the values of any variables requested by the user */ 816101460Sru if (!Lst_IsEmpty(variables)) { 81717193Sbde LstNode ln; 81817193Sbde 81969527Swill for (ln = Lst_First(variables); ln != NULL; 82017193Sbde ln = Lst_Succ(ln)) { 82166365Speter char *value; 82266365Speter if (expandVars) { 82394506Scharnier p1 = emalloc(strlen((char *)Lst_Datum(ln)) + 1 + 3); 82466365Speter /* This sprintf is safe, because of the malloc above */ 82566365Speter (void)sprintf(p1, "${%s}", (char *)Lst_Datum(ln)); 82666365Speter value = Var_Subst(NULL, p1, VAR_GLOBAL, FALSE); 82766365Speter } else { 82866365Speter value = Var_Value((char *)Lst_Datum(ln), 82966365Speter VAR_GLOBAL, &p1); 83066365Speter } 83117193Sbde printf("%s\n", value ? value : ""); 83266365Speter if (p1) 83366365Speter free(p1); 83417193Sbde } 835101460Sru } else { 83617193Sbde 8371590Srgrimes /* 838101460Sru * Have now read the entire graph and need to make a list of targets 839101460Sru * to create. If none was given on the command line, we consult the 840101460Sru * parsing module to find the main target(s) to create. 8411590Srgrimes */ 842101460Sru if (Lst_IsEmpty(create)) 843101460Sru targs = Parse_MainName(); 844101460Sru else 845101460Sru targs = Targ_FindList(create, TARG_CREATE); 846101460Sru 847101460Sru if (!compatMake) { 848101460Sru /* 849101460Sru * Initialize job module before traversing the graph, now that 850101460Sru * any .BEGIN and .END targets have been read. This is done 851101460Sru * only if the -q flag wasn't given (to prevent the .BEGIN from 852101460Sru * being executed should it exist). 853101460Sru */ 854101460Sru if (!queryFlag) { 855101460Sru if (maxLocal == -1) 856101460Sru maxLocal = maxJobs; 857101460Sru Job_Init(maxJobs, maxLocal); 858101460Sru jobsRunning = TRUE; 859101460Sru } 860101460Sru 861101460Sru /* Traverse the graph, checking on all the targets */ 862101460Sru outOfDate = Make_Run(targs); 863101460Sru } else { 864101460Sru /* 865101460Sru * Compat_Init will take care of creating all the targets as 866101460Sru * well as initializing the module. 867101460Sru */ 868101460Sru Compat_Run(targs); 8691590Srgrimes } 870101672Sru Lst_Destroy(targs, NOFREE); 87117193Sbde } 8728874Srgrimes 87317193Sbde Lst_Destroy(variables, NOFREE); 8745814Sjkh Lst_Destroy(makefiles, NOFREE); 87592921Simp Lst_Destroy(create, (void (*)(void *)) free); 8765814Sjkh 8771590Srgrimes /* print the graph now it's been processed if the user requested it */ 8781590Srgrimes if (DEBUG(GRAPH2)) 8791590Srgrimes Targ_PrintGraph(2); 8801590Srgrimes 8815814Sjkh Suff_End(); 8825814Sjkh Targ_End(); 8835814Sjkh Arch_End(); 8845814Sjkh str_end(); 8855814Sjkh Var_End(); 8865814Sjkh Parse_End(); 8875814Sjkh Dir_End(); 8885814Sjkh 8891590Srgrimes if (queryFlag && outOfDate) 8901590Srgrimes return(1); 8911590Srgrimes else 8921590Srgrimes return(0); 8931590Srgrimes} 8941590Srgrimes 8951590Srgrimes/*- 8961590Srgrimes * ReadMakefile -- 8971590Srgrimes * Open and parse the given makefile. 8981590Srgrimes * 8991590Srgrimes * Results: 9001590Srgrimes * TRUE if ok. FALSE if couldn't open file. 9011590Srgrimes * 9021590Srgrimes * Side Effects: 9031590Srgrimes * lots 9041590Srgrimes */ 9051590Srgrimesstatic Boolean 906104696SjmallettReadMakefile(void *p, void *q __unused) 9071590Srgrimes{ 908104696Sjmallett char *fname; /* makefile to read */ 9091590Srgrimes FILE *stream; 91073262Simp char *name, path[MAXPATHLEN]; 91197163Sjmallett char *MAKEFILE; 91294990Sru int setMAKEFILE; 9131590Srgrimes 914104696Sjmallett fname = p; 915104696Sjmallett 9161590Srgrimes if (!strcmp(fname, "-")) { 9171590Srgrimes Parse_File("(stdin)", stdin); 9181590Srgrimes Var_Set("MAKEFILE", "", VAR_GLOBAL); 9191590Srgrimes } else { 92094990Sru setMAKEFILE = strcmp(fname, ".depend"); 92194990Sru 9221590Srgrimes /* if we've chdir'd, rebuild the path name */ 9231590Srgrimes if (curdir != objdir && *fname != '/') { 92469390Swill (void)snprintf(path, MAXPATHLEN, "%s/%s", curdir, fname); 925100733Simp /* 926100733Simp * XXX The realpath stuff breaks relative includes 927100733Simp * XXX in some cases. The problem likely is in 928100733Simp * XXX parse.c where it does special things in 929100733Simp * XXX ParseDoInclude if the file is relateive 930100733Simp * XXX or absolute and not a system file. There 931100733Simp * XXX it assumes that if the current file that's 932100733Simp * XXX being included is absolute, that any files 933100733Simp * XXX that it includes shouldn't do the -I path 934100733Simp * XXX stuff, which is inconsistant with historical 935100733Simp * XXX behavior. However, I can't pentrate the mists 936100733Simp * XXX further, so I'm putting this workaround in 937100733Simp * XXX here until such time as the underlying bug 938100733Simp * XXX can be fixed. 939100733Simp */ 940100733Simp#if THIS_BREAKS_THINGS 94197077Sjmallett if (realpath(path, path) != NULL && 94297077Sjmallett (stream = fopen(path, "r")) != NULL) { 94397163Sjmallett MAKEFILE = fname; 9441590Srgrimes fname = path; 9451590Srgrimes goto found; 9461590Srgrimes } 94797077Sjmallett } else if (realpath(fname, path) != NULL) { 94897163Sjmallett MAKEFILE = fname; 94997077Sjmallett fname = path; 95097077Sjmallett if ((stream = fopen(fname, "r")) != NULL) 95197077Sjmallett goto found; 95297077Sjmallett } 953100733Simp#else 954100733Simp if ((stream = fopen(path, "r")) != NULL) { 955100733Simp MAKEFILE = fname; 956100733Simp fname = path; 957100733Simp goto found; 958100733Simp } 959100733Simp } else { 960100733Simp MAKEFILE = fname; 961100733Simp if ((stream = fopen(fname, "r")) != NULL) 962100733Simp goto found; 963100733Simp } 964100733Simp#endif 9651590Srgrimes /* look in -I and system include directories. */ 9661590Srgrimes name = Dir_FindFile(fname, parseIncPath); 9671590Srgrimes if (!name) 9681590Srgrimes name = Dir_FindFile(fname, sysIncPath); 9691590Srgrimes if (!name || !(stream = fopen(name, "r"))) 9701590Srgrimes return(FALSE); 97197163Sjmallett MAKEFILE = fname = name; 9721590Srgrimes /* 9731590Srgrimes * set the MAKEFILE variable desired by System V fans -- the 9741590Srgrimes * placement of the setting here means it gets set to the last 9751590Srgrimes * makefile specified, as it is set by SysV make. 9761590Srgrimes */ 97794990Srufound: 97894990Sru if (setMAKEFILE) 97997163Sjmallett Var_Set("MAKEFILE", MAKEFILE, VAR_GLOBAL); 9801590Srgrimes Parse_File(fname, stream); 9811590Srgrimes (void)fclose(stream); 9821590Srgrimes } 9831590Srgrimes return(TRUE); 9841590Srgrimes} 9851590Srgrimes 9861590Srgrimes/*- 98718730Ssteve * Cmd_Exec -- 98818730Ssteve * Execute the command in cmd, and return the output of that command 98918730Ssteve * in a string. 99018730Ssteve * 99118730Ssteve * Results: 99218730Ssteve * A string containing the output of the command, or the empty string 993104121Sjmallett * If error is not NULL, it contains the reason for the command failure 99418730Ssteve * 99518730Ssteve * Side Effects: 99618730Ssteve * The string must be freed by the caller. 99718730Ssteve */ 99818730Sstevechar * 999104696SjmallettCmd_Exec(char *cmd, char **error) 100018730Ssteve{ 100118730Ssteve char *args[4]; /* Args for invoking the shell */ 100218730Ssteve int fds[2]; /* Pipe streams */ 100318730Ssteve int cpid; /* Child PID */ 100418730Ssteve int pid; /* PID from wait() */ 100518730Ssteve char *res; /* result */ 100618730Ssteve int status; /* command exit status */ 100718730Ssteve Buffer buf; /* buffer to store the result */ 100818730Ssteve char *cp; 100918730Ssteve int cc; 101018730Ssteve 1011104121Sjmallett *error = NULL; 101218730Ssteve 101318730Ssteve /* 101418730Ssteve * Set up arguments for shell 101518730Ssteve */ 101618730Ssteve args[0] = "sh"; 101718730Ssteve args[1] = "-c"; 101818730Ssteve args[2] = cmd; 101918730Ssteve args[3] = NULL; 102018730Ssteve 102118730Ssteve /* 102218730Ssteve * Open a pipe for fetching its output 102318730Ssteve */ 102418730Ssteve if (pipe(fds) == -1) { 1025104121Sjmallett *error = "Couldn't create pipe for \"%s\""; 102618730Ssteve goto bad; 102718730Ssteve } 102818730Ssteve 102918730Ssteve /* 103018730Ssteve * Fork 103118730Ssteve */ 103218730Ssteve switch (cpid = vfork()) { 103318730Ssteve case 0: 103418730Ssteve /* 103518730Ssteve * Close input side of pipe 103618730Ssteve */ 103718730Ssteve (void) close(fds[0]); 103818730Ssteve 103918730Ssteve /* 104018730Ssteve * Duplicate the output stream to the shell's output, then 104118730Ssteve * shut the extra thing down. Note we don't fetch the error 104218730Ssteve * stream...why not? Why? 104318730Ssteve */ 104418730Ssteve (void) dup2(fds[1], 1); 104518730Ssteve (void) close(fds[1]); 104618730Ssteve 1047104123Sjmallett#if defined(DEFSHELL) && DEFSHELL == 0 1048104123Sjmallett (void) execv("/bin/csh", args); 1049104123Sjmallett#elif DEFSHELL == 1 105097251Sru (void) execv("/bin/sh", args); 105164739Sgreen#elif DEFSHELL == 2 105297251Sru (void) execv("/bin/ksh", args); 105364739Sgreen#else 105464739Sgreen#error "DEFSHELL must be 1 or 2." 105564739Sgreen#endif 105618730Ssteve _exit(1); 105718730Ssteve /*NOTREACHED*/ 105818730Ssteve 105918730Ssteve case -1: 1060104121Sjmallett *error = "Couldn't exec \"%s\""; 106118730Ssteve goto bad; 106218730Ssteve 106318730Ssteve default: 106418730Ssteve /* 106518730Ssteve * No need for the writing half 106618730Ssteve */ 106718730Ssteve (void) close(fds[1]); 106818730Ssteve 106918730Ssteve buf = Buf_Init (MAKE_BSIZE); 107018730Ssteve 107118730Ssteve do { 107218730Ssteve char result[BUFSIZ]; 107318730Ssteve cc = read(fds[0], result, sizeof(result)); 107418730Ssteve if (cc > 0) 107518730Ssteve Buf_AddBytes(buf, cc, (Byte *) result); 107618730Ssteve } 107718730Ssteve while (cc > 0 || (cc == -1 && errno == EINTR)); 107818730Ssteve 107918730Ssteve /* 108018730Ssteve * Close the input side of the pipe. 108118730Ssteve */ 108218730Ssteve (void) close(fds[0]); 108318730Ssteve 108418730Ssteve /* 108518730Ssteve * Wait for the process to exit. 108618730Ssteve */ 108718730Ssteve while(((pid = wait(&status)) != cpid) && (pid >= 0)) 108818730Ssteve continue; 108918730Ssteve 109018877Ssteve if (cc == -1) 1091104121Sjmallett *error = "Error reading shell's output for \"%s\""; 109218864Ssteve 109318730Ssteve res = (char *)Buf_GetAll (buf, &cc); 109418730Ssteve Buf_Destroy (buf, FALSE); 109518730Ssteve 109618730Ssteve if (status) 1097104121Sjmallett *error = "\"%s\" returned non-zero status"; 109818730Ssteve 109918730Ssteve /* 110018730Ssteve * Null-terminate the result, convert newlines to spaces and 110118730Ssteve * install it in the variable. 110218730Ssteve */ 110318730Ssteve res[cc] = '\0'; 110418730Ssteve cp = &res[cc] - 1; 110518730Ssteve 110618730Ssteve if (*cp == '\n') { 110718730Ssteve /* 110818730Ssteve * A final newline is just stripped 110918730Ssteve */ 111018730Ssteve *cp-- = '\0'; 111118730Ssteve } 111218730Ssteve while (cp >= res) { 111318730Ssteve if (*cp == '\n') { 111418730Ssteve *cp = ' '; 111518730Ssteve } 111618730Ssteve cp--; 111718730Ssteve } 111818730Ssteve break; 111918730Ssteve } 112018730Ssteve return res; 112118730Sstevebad: 112218730Ssteve res = emalloc(1); 112318730Ssteve *res = '\0'; 112418730Ssteve return res; 112518730Ssteve} 112618730Ssteve 11271590Srgrimes/* 11281590Srgrimes * usage -- 11291590Srgrimes * exit with usage message 11301590Srgrimes */ 11311590Srgrimesstatic void 1132104696Sjmallettusage(void) 11331590Srgrimes{ 113427644Scharnier (void)fprintf(stderr, "%s\n%s\n%s\n", 1135113512Sru"usage: make [-BPSXeiknqrstv] [-C directory] [-D variable] [-d flags]", 1136113512Sru" [-E variable] [-f makefile] [-I directory] [-j max_jobs]", 1137113512Sru" [-m directory] [-V variable] [variable=value] [target ...]"); 11381590Srgrimes exit(2); 11391590Srgrimes} 1140