summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorru <ru@FreeBSD.org>2004-10-23 21:34:41 +0000
committerru <ru@FreeBSD.org>2004-10-23 21:34:41 +0000
commit2f410fc7e2e8560258b86e1a9d71d559453140e9 (patch)
tree6c6a4b030e6179c38af1f4774457a0f5c68fea66
parent80dc3e1bc2d61be3d57a34c9fdb4d5c0f07d93ea (diff)
downloadFreeBSD-src-2f410fc7e2e8560258b86e1a9d71d559453140e9.zip
FreeBSD-src-2f410fc7e2e8560258b86e1a9d71d559453140e9.tar.gz
Expand the scope of the .SHELL specification to also cover
the compat mode of operation and the != operator. While here, fixed a bug in the .SHELL directive processing when only the name= attribute is specified and no built-in shell matches this name, causing null pointer dereference. Obtained from: NetBSD (except for bugs)
-rw-r--r--usr.bin/make/compat.c7
-rw-r--r--usr.bin/make/job.c51
-rw-r--r--usr.bin/make/job.h4
-rw-r--r--usr.bin/make/main.c14
4 files changed, 46 insertions, 30 deletions
diff --git a/usr.bin/make/compat.c b/usr.bin/make/compat.c
index 79531ef..b9ba32b 100644
--- a/usr.bin/make/compat.c
+++ b/usr.bin/make/compat.c
@@ -303,8 +303,9 @@ Compat_RunCommand (void *cmdp, void *gnp)
* -e flag as well as -c if it's supposed to exit when it hits an
* error.
*/
- static char *shargv[4] = { "/bin/sh" };
+ static char *shargv[4];
+ shargv[0] = shellPath;
shargv[1] = (errCheck ? "-ec" : "-c");
shargv[2] = cmd;
shargv[3] = (char *)NULL;
@@ -315,13 +316,14 @@ Compat_RunCommand (void *cmdp, void *gnp)
* This command must be passed by the shell for other reasons..
* or.. possibly not at all.
*/
- static char *shargv[4] = { "/bin/sh" };
+ static char *shargv[4];
if (internal == -1) {
/* Command does not need to be executed */
return (0);
}
+ shargv[0] = shellPath;
shargv[1] = (errCheck ? "-ec" : "-c");
shargv[2] = cmd;
shargv[3] = (char *)NULL;
@@ -655,6 +657,7 @@ Compat_Run(Lst targs)
int errors; /* Number of targets not remade due to errors */
CompatInit();
+ Shell_Init(); /* Set up shell. */
if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
signal(SIGINT, CompatInterrupt);
diff --git a/usr.bin/make/job.c b/usr.bin/make/job.c
index 8f0310b..4f1f83f 100644
--- a/usr.bin/make/job.c
+++ b/usr.bin/make/job.c
@@ -224,9 +224,9 @@ static Shell *commandShell = &shells[DEFSHELL];/* this is the shell to
* commands in the Makefile.
* It is set by the
* Job_ParseShell function */
-static char *shellPath = NULL, /* full pathname of
+char *shellPath = NULL, /* full pathname of
* executable image */
- *shellName; /* last component of shell */
+ *shellName = NULL; /* last component of shell */
static int maxJobs; /* The most children we can run at once */
@@ -2332,6 +2332,22 @@ Job_Make(GNode *gn)
(void) JobStart(gn, 0, NULL);
}
+void
+Shell_Init(void)
+{
+ if (shellPath == NULL) {
+ /*
+ * The user didn't specify a shell to use, so we are using the
+ * default one... Both the absolute path and the last component
+ * must be set. The last component is taken from the 'name' field
+ * of the default shell description pointed-to by commandShell.
+ * All default shells are located in _PATH_DEFSHELLDIR.
+ */
+ shellName = commandShell->name;
+ shellPath = str_concat(_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH);
+ }
+}
+
/*-
*-----------------------------------------------------------------------
* Job_Init --
@@ -2377,18 +2393,7 @@ Job_Init(int maxproc, int maxlocal)
targFmt = TARG_FMT;
}
- if (shellPath == NULL) {
- /*
- * The user didn't specify a shell to use, so we are using the
- * default one... Both the absolute path and the last component
- * must be set. The last component is taken from the 'name' field
- * of the default shell description pointed-to by commandShell.
- * All default shells are located in _PATH_DEFSHELLDIR.
- */
- shellName = commandShell->name;
- shellPath = str_concat(_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH);
- }
-
+ Shell_Init();
if (commandShell->exit == NULL) {
commandShell->exit = "";
}
@@ -2547,7 +2552,7 @@ JobMatchShell(char *name)
match = sh;
}
}
- return(match == NULL ? sh : match);
+ return(match);
}
/*-
@@ -2601,7 +2606,7 @@ Job_ParseShell(char *line)
char **argv;
int argc;
char *path;
- Shell newShell;
+ Shell newShell, *sh;
Boolean fullSpec = FALSE;
while (isspace((unsigned char) *line)) {
@@ -2661,7 +2666,12 @@ Job_ParseShell(char *line)
Parse_Error(PARSE_FATAL, "Neither path nor name specified");
return(FAILURE);
} else {
- commandShell = JobMatchShell(newShell.name);
+ if ((sh = JobMatchShell(newShell.name)) == NULL) {
+ Parse_Error(PARSE_FATAL, "%s: no matching shell",
+ newShell.name);
+ return(FAILURE);
+ }
+ commandShell = sh;
shellName = newShell.name;
}
} else {
@@ -2685,7 +2695,12 @@ Job_ParseShell(char *line)
shellName = path;
}
if (!fullSpec) {
- commandShell = JobMatchShell(shellName);
+ if ((sh = JobMatchShell(shellName)) == NULL) {
+ Parse_Error(PARSE_FATAL, "%s: no matching shell",
+ shellName);
+ return(FAILURE);
+ }
+ commandShell = sh;
} else {
commandShell = (Shell *) emalloc(sizeof(Shell));
*commandShell = newShell;
diff --git a/usr.bin/make/job.h b/usr.bin/make/job.h
index 284b16b..3dcad23 100644
--- a/usr.bin/make/job.h
+++ b/usr.bin/make/job.h
@@ -205,6 +205,9 @@ typedef struct Shell {
char *exit; /* exit on error */
} Shell;
+extern char *shellPath;
+extern char *shellName;
+
/*
* If REMOTE is defined then these things need exposed, otherwise they are
* static to job.c!
@@ -229,6 +232,7 @@ extern Boolean jobFull; /* Non-zero if no more jobs should/will start*/
extern int maxJobs; /* Number of jobs that may run */
+void Shell_Init(void);
void Job_Touch(GNode *, Boolean);
Boolean Job_CheckCommands(GNode *, void (*abortProc)(const char *, ...));
void Job_CatchChildren(Boolean);
diff --git a/usr.bin/make/main.c b/usr.bin/make/main.c
index 284cfe2..da2be48 100644
--- a/usr.bin/make/main.c
+++ b/usr.bin/make/main.c
@@ -1042,10 +1042,12 @@ Cmd_Exec(char *cmd, char **error)
*error = NULL;
+ if (shellPath == NULL)
+ Shell_Init();
/*
* Set up arguments for shell
*/
- args[0] = "sh";
+ args[0] = shellName;
args[1] = "-c";
args[2] = cmd;
args[3] = NULL;
@@ -1076,15 +1078,7 @@ Cmd_Exec(char *cmd, char **error)
(void) dup2(fds[1], 1);
(void) close(fds[1]);
-#if defined(DEFSHELL) && DEFSHELL == 0
- (void) execv("/bin/csh", args);
-#elif DEFSHELL == 1
- (void) execv("/bin/sh", args);
-#elif DEFSHELL == 2
- (void) execv("/bin/ksh", args);
-#else
-#error "DEFSHELL must be 1 or 2."
-#endif
+ (void) execv(shellPath, args);
_exit(1);
/*NOTREACHED*/
OpenPOWER on IntegriCloud