summaryrefslogtreecommitdiffstats
path: root/usr.bin/make/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/make/main.c')
-rw-r--r--usr.bin/make/main.c477
1 files changed, 389 insertions, 88 deletions
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c
index 8607fbb..d8b1708 100644
--- a/usr.bin/make/main.c
+++ b/usr.bin/make/main.c
@@ -1,3 +1,5 @@
+/* $NetBSD: main.c,v 1.30 1996/08/13 16:42:08 christos Exp $ */
+
/*
* Copyright (c) 1988, 1989, 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -43,7 +45,11 @@ static char copyright[] =
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 4/28/95";
+#if 0
+static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
+#else
+static char rcsid[] = "$NetBSD: main.c,v 1.30 1996/08/13 16:42:08 christos Exp $";
+#endif
#endif /* not lint */
/*-
@@ -79,7 +85,10 @@ static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 4/28/95";
#include <sys/resource.h>
#include <sys/signal.h>
#include <sys/stat.h>
+#ifndef MACHINE
#include <sys/utsname.h>
+#endif
+#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@@ -96,7 +105,7 @@ static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 4/28/95";
#ifndef DEFMAXLOCAL
#define DEFMAXLOCAL DEFMAXJOBS
-#endif DEFMAXLOCAL
+#endif /* DEFMAXLOCAL */
#define MAKEFLAGS ".MAKEFLAGS"
@@ -107,7 +116,9 @@ Boolean allPrecious; /* .PRECIOUS given on line by itself */
static Boolean noBuiltins; /* -r flag */
static Lst makefiles; /* ordered list of makefiles to read */
-int maxJobs; /* -J argument */
+static Boolean printVars; /* print value of one or more vars */
+static Lst variables; /* list of variables to print */
+int maxJobs; /* -j argument */
static int maxLocal; /* -L argument */
Boolean compatMake; /* -B argument */
Boolean debug; /* -d flag */
@@ -122,8 +133,10 @@ Boolean oldVars; /* variable substitution style */
Boolean checkEnvFirst; /* -e flag */
static Boolean jobsRunning; /* TRUE if the jobs might be running */
-static Boolean ReadMakefile();
-static void usage();
+static void MainParseArgs __P((int, char **));
+char * chdir_verify_path __P((char *, char *));
+static int ReadMakefile __P((ClientData, ClientData));
+static void usage __P((void));
static char *curdir; /* startup directory */
static char *objdir; /* where we chdir'ed to */
@@ -150,12 +163,13 @@ MainParseArgs(argc, argv)
extern int optind;
extern char *optarg;
int c;
+ int forceJobs = 0;
optind = 1; /* since we're called more than once */
-#ifdef notyet
-# define OPTFLAGS "BD:I:L:PSd:ef:ij:knqrst"
+#ifdef REMOTE
+# define OPTFLAGS "BD:I:L:PSV:d:ef:ij:km:nqrst"
#else
-# define OPTFLAGS "D:I:d:ef:ij:knqrst"
+# define OPTFLAGS "BD:I:PSV:d:ef:ij:km:nqrst"
#endif
rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
switch(c) {
@@ -169,15 +183,22 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
break;
-#ifdef notyet
+ case 'V':
+ printVars = TRUE;
+ (void)Lst_AtEnd(variables, (ClientData)optarg);
+ Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
+ Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
+ break;
case 'B':
compatMake = TRUE;
break;
+#ifdef REMOTE
case 'L':
maxLocal = atoi(optarg);
Var_Append(MAKEFLAGS, "-L", VAR_GLOBAL);
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
break;
+#endif
case 'P':
usePipes = FALSE;
Var_Append(MAKEFLAGS, "-P", VAR_GLOBAL);
@@ -186,7 +207,6 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
keepgoing = FALSE;
Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
break;
-#endif
case 'd': {
char *modules = optarg;
@@ -254,7 +274,11 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
break;
case 'j':
+ forceJobs = TRUE;
maxJobs = atoi(optarg);
+#ifndef REMOTE
+ maxLocal = maxJobs;
+#endif
Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
break;
@@ -262,6 +286,11 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
keepgoing = TRUE;
Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
break;
+ case 'm':
+ Dir_AddDir(sysIncPath, optarg);
+ Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
+ Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
+ break;
case 'n':
noExecute = TRUE;
Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
@@ -289,6 +318,13 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
}
}
+ /*
+ * Be compatible if user did not specify -j and did not explicitly
+ * turned compatibility on
+ */
+ if (!compatMake && !forceJobs)
+ compatMake = TRUE;
+
oldVars = TRUE;
/*
@@ -309,7 +345,7 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
optind = 1; /* - */
goto rearg;
}
- (void)Lst_AtEnd(create, (ClientData)strdup(*argv));
+ (void)Lst_AtEnd(create, (ClientData)estrdup(*argv));
}
}
@@ -346,6 +382,34 @@ Main_ParseArgLine(line)
MainParseArgs(argc, argv);
}
+char *
+chdir_verify_path(path, obpath)
+ char *path;
+ char *obpath;
+{
+ struct stat sb;
+
+ if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
+ if (chdir(path)) {
+ (void)fprintf(stderr, "make warning: %s: %s.\n",
+ path, strerror(errno));
+ return 0;
+ }
+ else {
+ if (path[0] != '/') {
+ (void) snprintf(obpath, MAXPATHLEN, "%s/%s",
+ curdir, path);
+ return obpath;
+ }
+ else
+ return path;
+ }
+ }
+
+ return 0;
+}
+
+
/*-
* main --
* The main function, for obvious reasons. Initializes variables
@@ -371,13 +435,29 @@ main(argc, argv)
Lst targs; /* target nodes to create -- passed to Make_Init */
Boolean outOfDate = TRUE; /* FALSE if all targets up to date */
struct stat sb, sa;
- char *p, *p1, *path, *pwd, *getenv(), *getwd();
+ char *p, *p1, *path, *pathp, *pwd;
char mdpath[MAXPATHLEN + 1];
char obpath[MAXPATHLEN + 1];
char cdpath[MAXPATHLEN + 1];
- struct utsname utsname;
char *machine = getenv("MACHINE");
+ Lst sysMkPath; /* Path of sys.mk */
+ char *cp = NULL, *start;
+ /* avoid faults on read-only strings */
+ static char syspath[] = _PATH_DEFSYSPATH;
+#ifdef RLIMIT_NOFILE
+ /*
+ * get rid of resource limit on file descriptors
+ */
+ {
+ struct rlimit rl;
+ if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
+ rl.rlim_cur != rl.rlim_max) {
+ rl.rlim_cur = rl.rlim_max;
+ (void) setrlimit(RLIMIT_NOFILE, &rl);
+ }
+ }
+#endif
/*
* Find where we are and take care of PWD for the automounter...
* All this code is so that we know where we are when we start up
@@ -397,7 +477,7 @@ main(argc, argv)
if ((pwd = getenv("PWD")) != NULL) {
if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
- sa.st_dev == sb.st_dev)
+ sa.st_dev == sb.st_dev)
(void) strcpy(curdir, pwd);
}
@@ -410,62 +490,53 @@ main(argc, argv)
* MACHINE_ARCH is always known at compile time.
*/
if (!machine) {
- if (uname(&utsname)) {
+#ifndef MACHINE
+ struct utsname utsname;
+
+ if (uname(&utsname) == -1) {
perror("make: uname");
exit(2);
}
machine = utsname.machine;
+#else
+ machine = MACHINE;
+#endif
}
/*
- * if the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory
- * exists, change into it and build there. Once things are
- * initted, have to add the original directory to the search path,
+ * If the MAKEOBJDIR (or by default, the _PATH_OBJDIR) directory
+ * exists, change into it and build there. (If a .${MACHINE} suffix
+ * exists, use that directory instead).
+ * Otherwise check MAKEOBJDIRPREFIX`cwd` (or by default,
+ * _PATH_OBJDIRPREFIX`cwd`) and build there if it exists.
+ * If all fails, use the current directory to build.
+ *
+ * Once things are initted,
+ * have to add the original directory to the search path,
* and modify the paths for the Makefiles apropriately. The
* current directory is also placed as a variable for make scripts.
*/
- if (!(path = getenv("MAKEOBJDIR"))) {
- path = _PATH_OBJDIR;
- (void) sprintf(mdpath, "%s.%s", path, machine);
- }
- else
- (void) strncpy(mdpath, path, MAXPATHLEN + 1);
-
- if (stat(mdpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
-
- if (chdir(mdpath)) {
- (void)fprintf(stderr, "make warning: %s: %s.\n",
- mdpath, strerror(errno));
- objdir = curdir;
- }
- else {
- if (mdpath[0] != '/') {
- (void) sprintf(obpath, "%s/%s", curdir, mdpath);
- objdir = obpath;
- }
- else
- objdir = mdpath;
+ if (!(pathp = getenv("MAKEOBJDIRPREFIX"))) {
+ if (!(path = getenv("MAKEOBJDIR"))) {
+ path = _PATH_OBJDIR;
+ pathp = _PATH_OBJDIRPREFIX;
+ (void) snprintf(mdpath, MAXPATHLEN, "%s.%s",
+ path, machine);
+ if (!(objdir = chdir_verify_path(mdpath, obpath)))
+ if (!(objdir=chdir_verify_path(path, obpath))) {
+ (void) snprintf(mdpath, MAXPATHLEN,
+ "%s%s", pathp, curdir);
+ if (!(objdir=chdir_verify_path(mdpath,
+ obpath)))
+ objdir = curdir;
+ }
}
+ else if (!(objdir = chdir_verify_path(path, obpath)))
+ objdir = curdir;
}
else {
- if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
-
- if (chdir(path)) {
- (void)fprintf(stderr, "make warning: %s: %s.\n",
- path, strerror(errno));
- objdir = curdir;
- }
- else {
- if (path[0] != '/') {
- (void) sprintf(obpath, "%s/%s", curdir,
- path);
- objdir = obpath;
- }
- else
- objdir = obpath;
- }
- }
- else
+ (void) snprintf(mdpath, MAXPATHLEN, "%s%s", pathp, curdir);
+ if (!(objdir = chdir_verify_path(mdpath, obpath)))
objdir = curdir;
}
@@ -473,6 +544,8 @@ main(argc, argv)
create = Lst_Init(FALSE);
makefiles = Lst_Init(FALSE);
+ printVars = FALSE;
+ variables = Lst_Init(FALSE);
beSilent = FALSE; /* Print commands as executed */
ignoreErrors = FALSE; /* Pay attention to non-zero returns */
noExecute = FALSE; /* Execute all commands */
@@ -485,14 +558,14 @@ main(argc, argv)
debug = 0; /* No debug verbosity, please. */
jobsRunning = FALSE;
- maxJobs = DEFMAXJOBS; /* Set default max concurrency */
maxLocal = DEFMAXLOCAL; /* Set default local max concurrency */
-#ifdef notyet
- compatMake = FALSE; /* No compat mode */
+#ifdef REMOTE
+ maxJobs = DEFMAXJOBS; /* Set default max concurrency */
#else
- compatMake = TRUE; /* No compat mode */
+ maxJobs = maxLocal;
#endif
-
+ compatMake = FALSE; /* No compat mode */
+
/*
* Initialize the parsing, directory and variable modules to prepare
@@ -535,7 +608,7 @@ main(argc, argv)
#else
Main_ParseArgLine(getenv("MAKE"));
#endif
-
+
MainParseArgs(argc, argv);
/*
@@ -566,13 +639,41 @@ main(argc, argv)
} else
Var_Set(".TARGETS", "", VAR_GLOBAL);
+
+ /*
+ * If no user-supplied system path was given (through the -m option)
+ * add the directories from the DEFSYSPATH (more than one may be given
+ * as dir1:...:dirn) to the system include path.
+ */
+ if (Lst_IsEmpty(sysIncPath)) {
+ for (start = syspath; *start != '\0'; start = cp) {
+ for (cp = start; *cp != '\0' && *cp != ':'; cp++)
+ continue;
+ if (*cp == '\0') {
+ Dir_AddDir(sysIncPath, start);
+ } else {
+ *cp++ = '\0';
+ Dir_AddDir(sysIncPath, start);
+ }
+ }
+ }
+
/*
- * Read in the built-in rules first, followed by the specified makefile,
- * if it was (makefile != (char *) NULL), or the default Makefile and
- * makefile, in that order, if it wasn't.
+ * Read in the built-in rules first, followed by the specified
+ * makefile, if it was (makefile != (char *) NULL), or the default
+ * Makefile and makefile, in that order, if it wasn't.
*/
- if (!noBuiltins && !ReadMakefile(_PATH_DEFSYSMK))
- Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
+ if (!noBuiltins) {
+ LstNode ln;
+
+ sysMkPath = Lst_Init (FALSE);
+ Dir_Expand (_PATH_DEFSYSMK, sysIncPath, sysMkPath);
+ if (Lst_IsEmpty(sysMkPath))
+ Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
+ ln = Lst_Find(sysMkPath, (ClientData)NULL, ReadMakefile);
+ if (ln != NILLNODE)
+ Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
+ }
if (!Lst_IsEmpty(makefiles)) {
LstNode ln;
@@ -580,10 +681,10 @@ main(argc, argv)
ln = Lst_Find(makefiles, (ClientData)NULL, ReadMakefile);
if (ln != NILLNODE)
Fatal("make: cannot open %s.", (char *)Lst_Datum(ln));
- } else if (!ReadMakefile("makefile"))
- (void)ReadMakefile("Makefile");
+ } else if (!ReadMakefile("makefile", NULL))
+ (void)ReadMakefile("Makefile", NULL);
- (void)ReadMakefile(".depend");
+ (void)ReadMakefile(".depend", NULL);
Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
if (p1)
@@ -641,6 +742,21 @@ main(argc, argv)
if (DEBUG(GRAPH1))
Targ_PrintGraph(1);
+ /* print the values of any variables requested by the user */
+ if (printVars) {
+ LstNode ln;
+
+ for (ln = Lst_First(variables); ln != NILLNODE;
+ ln = Lst_Succ(ln)) {
+ char *value = Var_Value((char *)Lst_Datum(ln),
+ VAR_GLOBAL, &p1);
+
+ printf("%s\n", value ? value : "");
+ if (p1)
+ free(p1);
+ }
+ }
+
/*
* Have now read the entire graph and need to make a list of targets
* to create. If none was given on the command line, we consult the
@@ -651,11 +767,7 @@ main(argc, argv)
else
targs = Targ_FindList(create, TARG_CREATE);
-/*
- * this was original amMake -- want to allow parallelism, so put this
- * back in, eventually.
- */
- if (!compatMake) {
+ if (!compatMake && !printVars) {
/*
* Initialize job module before traversing the graph, now that
* any .BEGIN and .END targets have been read. This is done
@@ -671,14 +783,16 @@ main(argc, argv)
/* Traverse the graph, checking on all the targets */
outOfDate = Make_Run(targs);
- } else
+ } else if (!printVars) {
/*
* Compat_Init will take care of creating all the targets as
* well as initializing the module.
*/
Compat_Run(targs);
-
+ }
+
Lst_Destroy(targs, NOFREE);
+ Lst_Destroy(variables, NOFREE);
Lst_Destroy(makefiles, NOFREE);
Lst_Destroy(create, (void (*) __P((ClientData))) free);
@@ -711,10 +825,11 @@ main(argc, argv)
* lots
*/
static Boolean
-ReadMakefile(fname)
- char *fname; /* makefile to read */
+ReadMakefile(p, q)
+ ClientData p, q;
{
- extern Lst parseIncPath, sysIncPath;
+ char *fname = p; /* makefile to read */
+ extern Lst parseIncPath;
FILE *stream;
char *name, path[MAXPATHLEN + 1];
@@ -752,6 +867,142 @@ found: Var_Set("MAKEFILE", fname, VAR_GLOBAL);
}
/*-
+ * Cmd_Exec --
+ * Execute the command in cmd, and return the output of that command
+ * in a string.
+ *
+ * Results:
+ * A string containing the output of the command, or the empty string
+ * If err is not NULL, it contains the reason for the command failure
+ *
+ * Side Effects:
+ * The string must be freed by the caller.
+ */
+char *
+Cmd_Exec(cmd, err)
+ char *cmd;
+ char **err;
+{
+ char *args[4]; /* Args for invoking the shell */
+ int fds[2]; /* Pipe streams */
+ int cpid; /* Child PID */
+ int pid; /* PID from wait() */
+ char *res; /* result */
+ int status; /* command exit status */
+ Buffer buf; /* buffer to store the result */
+ char *cp;
+ int cc;
+
+
+ *err = NULL;
+
+ /*
+ * Set up arguments for shell
+ */
+ args[0] = "sh";
+ args[1] = "-c";
+ args[2] = cmd;
+ args[3] = NULL;
+
+ /*
+ * Open a pipe for fetching its output
+ */
+ if (pipe(fds) == -1) {
+ *err = "Couldn't create pipe for \"%s\"";
+ goto bad;
+ }
+
+ /*
+ * Fork
+ */
+ switch (cpid = vfork()) {
+ case 0:
+ /*
+ * Close input side of pipe
+ */
+ (void) close(fds[0]);
+
+ /*
+ * Duplicate the output stream to the shell's output, then
+ * shut the extra thing down. Note we don't fetch the error
+ * stream...why not? Why?
+ */
+ (void) dup2(fds[1], 1);
+ (void) close(fds[1]);
+
+ (void) execv("/bin/sh", args);
+ _exit(1);
+ /*NOTREACHED*/
+
+ case -1:
+ *err = "Couldn't exec \"%s\"";
+ goto bad;
+
+ default:
+ /*
+ * No need for the writing half
+ */
+ (void) close(fds[1]);
+
+ buf = Buf_Init (MAKE_BSIZE);
+
+ do {
+ char result[BUFSIZ];
+ cc = read(fds[0], result, sizeof(result));
+ if (cc > 0)
+ Buf_AddBytes(buf, cc, (Byte *) result);
+ }
+ while (cc > 0 || (cc == -1 && errno == EINTR));
+
+ /*
+ * Close the input side of the pipe.
+ */
+ (void) close(fds[0]);
+
+ /*
+ * Wait for the process to exit.
+ */
+ while(((pid = wait(&status)) != cpid) && (pid >= 0))
+ continue;
+
+ res = (char *)Buf_GetAll (buf, &cc);
+ Buf_Destroy (buf, FALSE);
+
+ if (cc == 0)
+ *err = "Couldn't read shell's output for \"%s\"";
+
+ if (status)
+ *err = "\"%s\" returned non-zero status";
+
+ /*
+ * Null-terminate the result, convert newlines to spaces and
+ * install it in the variable.
+ */
+ res[cc] = '\0';
+ cp = &res[cc] - 1;
+
+ if (*cp == '\n') {
+ /*
+ * A final newline is just stripped
+ */
+ *cp-- = '\0';
+ }
+ while (cp >= res) {
+ if (*cp == '\n') {
+ *cp = ' ';
+ }
+ cp--;
+ }
+ break;
+ }
+ return res;
+bad:
+ res = emalloc(1);
+ *res = '\0';
+ return res;
+}
+
+/*-
* Error --
* Print an error message given its format.
*
@@ -833,7 +1084,7 @@ Fatal(va_alist)
* a message and exits.
*
* Results:
- * None
+ * None
*
* Side Effects:
* All children are killed indiscriminately and the program Lib_Exits
@@ -889,10 +1140,10 @@ DieHorribly()
/*
* Finish --
* Called when aborting due to errors in child shell to signal
- * abnormal exit.
+ * abnormal exit.
*
* Results:
- * None
+ * None
*
* Side Effects:
* The program exits
@@ -908,18 +1159,47 @@ Finish(errors)
* emalloc --
* malloc, but die on error.
*/
-char *
+void *
emalloc(len)
size_t len;
{
+ void *p;
+
+ if ((p = malloc(len)) == NULL)
+ enomem();
+ return(p);
+}
+
+/*
+ * estrdup --
+ * strdup, but die on error.
+ */
+char *
+estrdup(str)
+ const char *str;
+{
char *p;
- if ((p = (char *) malloc(len)) == NULL)
+ if ((p = strdup(str)) == NULL)
enomem();
return(p);
}
/*
+ * erealloc --
+ * realloc, but die on error.
+ */
+void *
+erealloc(ptr, size)
+ void *ptr;
+ size_t size;
+{
+ if ((ptr = realloc(ptr, size)) == NULL)
+ enomem();
+ return(ptr);
+}
+
+/*
* enomem --
* die when out of memory.
*/
@@ -931,6 +1211,26 @@ enomem()
}
/*
+ * enunlink --
+ * Remove a file carefully, avoiding directories.
+ */
+int
+eunlink(file)
+ const char *file;
+{
+ struct stat st;
+
+ if (lstat(file, &st) == -1)
+ return -1;
+
+ if (S_ISDIR(st.st_mode)) {
+ errno = EISDIR;
+ return -1;
+ }
+ return unlink(file);
+}
+
+/*
* usage --
* exit with usage message
*/
@@ -938,8 +1238,9 @@ static void
usage()
{
(void)fprintf(stderr,
-"usage: make [-eiknqrst] [-D variable] [-d flags] [-f makefile ]\n\
- [-I directory] [-j max_jobs] [variable=value]\n");
+"usage: make [-Beiknqrst] [-D variable] [-d flags] [-f makefile ]\n\
+ [-I directory] [-j max_jobs] [-m directory] [-V variable]\n\
+ [variable=value] [target ...]\n");
exit(2);
}
OpenPOWER on IntegriCloud