summaryrefslogtreecommitdiffstats
path: root/usr.bin/make/main.c
diff options
context:
space:
mode:
authorsteve <steve@FreeBSD.org>1996-10-06 02:35:38 +0000
committersteve <steve@FreeBSD.org>1996-10-06 02:35:38 +0000
commit49662693d9f1e004b037bebf6cc4663e64ae7baa (patch)
treeab5bd5270becce85fa203b4b54d26c39fa7c14bc /usr.bin/make/main.c
parent7dcbb4192b730b0ebfec18a71b61cd487c61320a (diff)
downloadFreeBSD-src-49662693d9f1e004b037bebf6cc4663e64ae7baa.zip
FreeBSD-src-49662693d9f1e004b037bebf6cc4663e64ae7baa.tar.gz
Merge in NetBSD's changes to make(1). Changes include:
- Add the .PHONY, .PARALLEL, and .WAIT directives - Added the -B and -m commandline flags - misc. man page cleanups - numerous job-related enhancements - removed unused header file (bit.h) - add util.c for functions not found in other envs. - and a few coordinated whitespace changes Special thanks to Christos Zoulas <christos@netbsd.org> for help in the merge. A 'diff -ur' between Net and FreeBSD now only contains sccsid-related diffs. :) Obtained from: NetBSD, christos@netbsd.org, and me
Diffstat (limited to 'usr.bin/make/main.c')
-rw-r--r--usr.bin/make/main.c321
1 files changed, 286 insertions, 35 deletions
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c
index 81c5b39..60804ef 100644
--- a/usr.bin/make/main.c
+++ b/usr.bin/make/main.c
@@ -79,7 +79,10 @@ static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
#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 +99,7 @@ static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
#ifndef DEFMAXLOCAL
#define DEFMAXLOCAL DEFMAXJOBS
-#endif DEFMAXLOCAL
+#endif /* DEFMAXLOCAL */
#define MAKEFLAGS ".MAKEFLAGS"
@@ -109,7 +112,7 @@ static Boolean noBuiltins; /* -r flag */
static Lst makefiles; /* ordered list of makefiles to read */
static Boolean printVars; /* print value of one or more vars */
static Lst variables; /* list of variables to print */
-int maxJobs; /* -J argument */
+int maxJobs; /* -j argument */
static int maxLocal; /* -L argument */
Boolean compatMake; /* -B argument */
Boolean debug; /* -d flag */
@@ -124,8 +127,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 */
@@ -152,12 +157,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:PSV:d:ef:ij:knqrst"
+#ifdef REMOTE
+# define OPTFLAGS "BD:I:L:PSV:d:ef:ij:km:nqrst"
#else
-# define OPTFLAGS "D:I:V: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) {
@@ -177,15 +183,16 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
Var_Append(MAKEFLAGS, optarg, VAR_GLOBAL);
break;
-#ifdef notyet
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);
@@ -194,7 +201,6 @@ rearg: while((c = getopt(argc, argv, OPTFLAGS)) != EOF) {
keepgoing = FALSE;
Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
break;
-#endif
case 'd': {
char *modules = optarg;
@@ -262,7 +268,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;
@@ -270,6 +280,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);
@@ -297,6 +312,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;
/*
@@ -317,7 +339,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));
}
}
@@ -407,13 +429,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, *pathp, *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
@@ -447,6 +485,8 @@ main(argc, argv)
*/
if (!machine) {
#ifndef MACHINE
+ struct utsname utsname;
+
if (uname(&utsname) == -1) {
perror("make: uname");
exit(2);
@@ -512,13 +552,13 @@ 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 */
/*
@@ -593,13 +633,41 @@ main(argc, argv)
} else
Var_Set(".TARGETS", "", VAR_GLOBAL);
+
/*
- * 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 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 (!noBuiltins && !ReadMakefile(_PATH_DEFSYSMK))
- Fatal("make: no system rules (%s).", _PATH_DEFSYSMK);
+ 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.
+ */
+ 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;
@@ -607,10 +675,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)
@@ -693,10 +761,6 @@ 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 && !printVars) {
/*
* Initialize job module before traversing the graph, now that
@@ -755,10 +819,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];
@@ -796,6 +861,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.
*
@@ -952,18 +1153,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.
*/
@@ -975,6 +1205,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
*/
@@ -982,8 +1232,9 @@ static void
usage()
{
(void)fprintf(stderr,
-"usage: make [-eiknqrst] [-D variable] [-d flags] [-f makefile] [-I directory]\n\
- [-j max_jobs] [-V variable] [variable=value] [target ...]\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