diff options
author | steve <steve@FreeBSD.org> | 1996-10-06 02:35:38 +0000 |
---|---|---|
committer | steve <steve@FreeBSD.org> | 1996-10-06 02:35:38 +0000 |
commit | 49662693d9f1e004b037bebf6cc4663e64ae7baa (patch) | |
tree | ab5bd5270becce85fa203b4b54d26c39fa7c14bc /usr.bin/make/main.c | |
parent | 7dcbb4192b730b0ebfec18a71b61cd487c61320a (diff) | |
download | FreeBSD-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.c | 321 |
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); } |