msh: fix the case where the file has exec bit but can't be run directly
authorDenis Vlasenko <vda.linux@googlemail.com>
Fri, 30 May 2008 22:28:32 +0000 (22:28 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Fri, 30 May 2008 22:28:32 +0000 (22:28 -0000)
     (run "$SHELL $file" instead)
msh: fix exit codes when command is not found or can't be execed
     (with testcases)

shell/msh.c
shell/msh_test/msh-execution/exitcode_EACCES.right [new file with mode: 0644]
shell/msh_test/msh-execution/exitcode_EACCES.tests [new file with mode: 0755]
shell/msh_test/msh-execution/exitcode_ENOENT.right [new file with mode: 0644]
shell/msh_test/msh-execution/exitcode_ENOENT.tests [new file with mode: 0755]

index 9e06a3bff2181481d3e416bc49f4d9fcdfa82648..840c8bb931974e4626c7943a4e418d811612e4bf 100644 (file)
@@ -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 (file)
index 0000000..b13682c
--- /dev/null
@@ -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 (executable)
index 0000000..26b5c61
--- /dev/null
@@ -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 (file)
index 0000000..e2bad05
--- /dev/null
@@ -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 (executable)
index 0000000..c886653
--- /dev/null
@@ -0,0 +1,2 @@
+./does_exist_for_sure
+echo $?