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)

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 @@
 /* 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 @@
 {
 	if (*s) {
 		prs(s);
-		exstat = -1;
+		if (!exstat)
+			exstat = 255;
 	}
 	prs("\n");
 	if (FLAG['e'])
@@ -3071,8 +3072,6 @@
 		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 @@
 
 		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 @@
 			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 $?