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)
This commit is contained in:
Ruslan Ermilov 2004-10-23 21:34:41 +00:00
parent 85986ce002
commit 3ecaab1c99
4 changed files with 46 additions and 30 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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*/