From 447bd6683729eb6d0f09e30eb68add6297881d01 Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Fri, 30 May 2008 22:28:32 +0000 Subject: msh: fix the case where the file has exec bit but can't be run directly (run "$SHELL $file" instead) msh: fix exit codes when command is not found or can't be execed (with testcases) --- shell/msh.c | 19 +++++++++++++------ shell/msh_test/msh-execution/exitcode_EACCES.right | 2 ++ shell/msh_test/msh-execution/exitcode_EACCES.tests | 2 ++ shell/msh_test/msh-execution/exitcode_ENOENT.right | 2 ++ shell/msh_test/msh-execution/exitcode_ENOENT.tests | 2 ++ 5 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 shell/msh_test/msh-execution/exitcode_EACCES.right create mode 100755 shell/msh_test/msh-execution/exitcode_EACCES.tests create mode 100644 shell/msh_test/msh-execution/exitcode_ENOENT.right create mode 100755 shell/msh_test/msh-execution/exitcode_ENOENT.tests diff --git a/shell/msh.c b/shell/msh.c index 9e06a3b..840c8bb 100644 --- a/shell/msh.c +++ b/shell/msh.c @@ -594,7 +594,7 @@ static struct op *dowholefile(int /*, int*/); /* Globals */ static char **dolv; static int dolc; -static int exstat; +static uint8_t exstat; static smallint gflg; /* (seems to be a parse error indicator) */ static smallint interactive; /* Is this an interactive shell */ static smallint execflg; @@ -806,7 +806,8 @@ static void warn(const char *s) { if (*s) { prs(s); - exstat = -1; + if (!exstat) + exstat = 255; } prs("\n"); if (FLAG['e']) @@ -3071,8 +3072,6 @@ static const char *rexecve(char *c, char **v, char **envp) if (tp != global_env.linep) *tp++ = '/'; strcpy(tp, c); - //for (i = 0; (*tp++ = c[i++]) != '\0';) - // continue; DBGPRINTF3(("REXECVE: global_env.linep is %s\n", global_env.linep)); @@ -3080,10 +3079,13 @@ static const char *rexecve(char *c, char **v, char **envp) switch (errno) { case ENOEXEC: + /* File is executable but file format isnt recognized */ + /* Run it as a shell script */ + /* (execve above didnt do it itself, unlike execvp) */ *v = global_env.linep; v--; tp = *v; - *v = global_env.linep; + *v = (char*)DEFAULT_SHELL; execve(DEFAULT_SHELL, v, envp); *v = tp; return "no shell"; @@ -3095,7 +3097,12 @@ static const char *rexecve(char *c, char **v, char **envp) return "argument list too long"; } } - return errno == ENOENT ? "not found" : "cannot execute"; + if (errno == ENOENT) { + exstat = 127; /* standards require this */ + return "not found"; + } + exstat = 126; /* mimic bash */ + return "cannot execute"; } /* diff --git a/shell/msh_test/msh-execution/exitcode_EACCES.right b/shell/msh_test/msh-execution/exitcode_EACCES.right new file mode 100644 index 0000000..b13682c --- /dev/null +++ b/shell/msh_test/msh-execution/exitcode_EACCES.right @@ -0,0 +1,2 @@ +./: cannot execute +126 diff --git a/shell/msh_test/msh-execution/exitcode_EACCES.tests b/shell/msh_test/msh-execution/exitcode_EACCES.tests new file mode 100755 index 0000000..26b5c61 --- /dev/null +++ b/shell/msh_test/msh-execution/exitcode_EACCES.tests @@ -0,0 +1,2 @@ +./ +echo $? diff --git a/shell/msh_test/msh-execution/exitcode_ENOENT.right b/shell/msh_test/msh-execution/exitcode_ENOENT.right new file mode 100644 index 0000000..e2bad05 --- /dev/null +++ b/shell/msh_test/msh-execution/exitcode_ENOENT.right @@ -0,0 +1,2 @@ +./does_exist_for_sure: not found +127 diff --git a/shell/msh_test/msh-execution/exitcode_ENOENT.tests b/shell/msh_test/msh-execution/exitcode_ENOENT.tests new file mode 100755 index 0000000..c886653 --- /dev/null +++ b/shell/msh_test/msh-execution/exitcode_ENOENT.tests @@ -0,0 +1,2 @@ +./does_exist_for_sure +echo $? -- cgit v1.1