Index: src/usr.bin/make/main.c =================================================================== RCS file: /home/ncvs/src/usr.bin/make/main.c,v retrieving revision 1.35.2.10 diff -u -r1.35.2.10 main.c --- src/usr.bin/make/main.c 16 Dec 2003 08:34:11 -0000 1.35.2.10 +++ src/usr.bin/make/main.c 6 Jan 2004 10:04:42 -0000 @@ -95,6 +95,7 @@ #include #include #include +#include #include #include #ifdef __STDC__ @@ -145,6 +146,8 @@ static void MainParseArgs __P((int, char **)); char * chdir_verify_path __P((char *, char *)); static int ReadMakefile __P((ClientData, ClientData)); +static void ReadEnvProc __P((const char *envproc, + const char *envprocdir, const char *curdir)); static void usage __P((void)); static char *curdir; /* startup directory */ @@ -493,6 +496,8 @@ char *cp = NULL, *start; /* avoid faults on read-only strings */ static char syspath[] = _PATH_DEFSYSPATH; + char *envproc = getenv("MAKEENVPROC"); + char *envprocdir = getenv("MAKEENVDIR"); { /* @@ -535,6 +540,12 @@ if (stat(curdir, &sa) == -1) err(2, "%s", curdir); + /* + * Look for an environment processor as early as possible + */ + if ((envproc != NULL) && (envproc[0] != '\0')) + ReadEnvProc(envproc, envprocdir, curdir); + #ifdef WANT_ENV_PWD if ((pwd = getenv("PWD")) != NULL) { if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino && @@ -682,7 +693,6 @@ forceJobs = FALSE; /* No -j flag */ compatMake = FALSE; /* No compat mode */ - /* * Initialize the parsing, directory and variable modules to prepare * for the reading of inclusion paths and variable settings on the @@ -1420,3 +1430,79 @@ printf("%lx ", (unsigned long) a); return b ? 0 : 0; } + +/*- + * ReadEnvProc -- + * Read the output of an environment processor program and + * set or unset environment variables accordingly. + * + * Results: + * none + * + * Side effects: + * Executes the program specified by the envproc argument and + * sets or unsets environment variables according to the program output. + */ + +static void +ReadEnvProc(const char *envproc, const char *envprocdir, const char *curdir) { + regex_t regdir; + int r; + char regerr[128]; + FILE *envout; + char *s, *new; + size_t len; + + /* First check if the env processor needs to run at all here */ + if ((envprocdir != NULL) && (envprocdir[0] != '\0')) { + memset(®dir, 0, sizeof(regdir)); + r = regcomp(®dir, envprocdir, REG_EXTENDED | REG_NOSUB); + if (r != 0) { + regerror(r, ®dir, regerr, sizeof(regerr)); + errx(1, "parsing regexp %s: %s", envprocdir, regerr); + } + + /* If curdir does not match, return w/o executing anything */ + r = regexec(®dir, curdir, 0, NULL, 0); + if (r == REG_NOMATCH) + return; + if (r != 0) { + regerror(r, ®dir, regerr, sizeof(regerr)); + errx(1, "matching regexp %s against %s: %s", + envprocdir, curdir, regerr); + } + } + + if ((envout = popen(envproc, "r")) == NULL) + err(1, "invoking environment processor '%s'", envproc); + + while ((s = fgetln(envout, &len)) != NULL) { + /* Null-terminate as needed */ + if (s[len - 1] == '\n') { + s[len - 1] = '\0'; + new = NULL; + } else { + if ((new = realloc(s, len + 1)) == NULL) + err(1, "reading env processor output"); + memcpy(new, s, len); + new[len] = '\0'; + s = new; + } + + /* + * A 'var=value' specification sets the variable, while + * a mere variable name unsets it. + */ + if (strchr(s, '=') != NULL) + putenv(s); + else + unsetenv(s); + + if (new != NULL) + free(new); + } + if (ferror(envout)) + err(1, "reading env processor output"); + + pclose(envout); +} Index: src/usr.bin/make/make.1 =================================================================== RCS file: /home/ncvs/src/usr.bin/make/make.1,v retrieving revision 1.29.2.16 diff -u -r1.29.2.16 make.1 --- src/usr.bin/make/make.1 10 Jul 2004 08:14:42 -0000 1.29.2.16 +++ src/usr.bin/make/make.1 12 Jul 2004 07:58:59 -0000 @@ -379,7 +379,9 @@ .It Environment variables Variables defined as part of .Nm Ns 's -environment. +environment or in the output of the +.Ev MAKEENVPROC +program, if specified (see the ENVIRONMENT PROCESSORS section below). .It Global variables Variables defined in the makefile or in included makefiles. .It Command line variables @@ -753,6 +755,47 @@ .It Cm U Converts variable to upper-case letters. .El +.Sh ENVIRONMENT PROCESSORS +External programs, called +.Dq environment processors , +may provide +additional environment data before any Makefile parsing is done. +If the +.Ev MAKEENVPROC +environment variable is set before +.Nm +is invoked, it is interpreted as a command to obtain additional environment +variables from. +.Nm +executes the command using the +.Xr popen 3 +function and examines each line of its output. +If the line contains a +.Sq = +character, it is treated as a +.Ar variable Ns No = Ns Ar value +assignment operator and +.Nm +sets the respective variable in its environment to the specified value. +If the line does not contain a +.Sq = +character, it is treated as the name of a variable to be removed from the +.Nm +environment. +.Pp +If the +.Ev MAKEENVDIR +environment variable is also set, +.Nm +treats it as an extended regular expression (see +.Xr re_format 7 ) +and matches the current directory against it. +If there is no match, the environment processor is not executed at all. +This allows for running the processor only in certain directory trees, e.g. +.Pa /usr/ports , +without the burden of the additional command execution when running +.Nm +in other directories. .Sh DIRECTIVES, CONDITIONALS, AND FOR LOOPS Directives, conditionals, and for loops reminiscent of the C programming language are provided in @@ -1214,6 +1257,8 @@ utility uses the following environment variables, if they exist: .Ev MACHINE , .Ev MAKE , +.Ev MAKEENVDIR , +.Ev MAKEENVPROC , .Ev MAKEFLAGS , .Ev MAKEOBJDIR , .Ev MAKEOBJDIRPREFIX ,