EXPERIMENTAL optimisation for “sh -c 'foo'” to equal “sh -c 'exit foo'” iff

several conditions are met as outlined below; for more background, refer to
http://www.FreeBSD.org/cgi/query-pr.cgi?pr=113860

We don’t yet optimise 「% sh -c '{ echo a; sleep 10;}&'; sleep 1; ps T」 so
the FreeBSD® sh approach cannot work for us, but scanning the “sh -c” argu‐
ment for disallowed characters and, if not, setting a flag that enables the
shell to exec the tree when parsed as TCOM *and not c_trap()* was possible.

Disallowed characters are currently C_QUOTE except space, that is:
Tab Newline " # $ & ' ( ) * ; < = > ? [ \ ] ` |

This should catch all cases of magic, variables, subshells, pipelines, etc.
This commit is contained in:
tg
2012-10-21 21:26:41 +00:00
parent 1f43cc907d
commit bebb2d2254
3 changed files with 38 additions and 6 deletions

25
main.c
View File

@@ -34,7 +34,7 @@
#include <locale.h>
#endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.229 2012/10/21 17:16:45 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.230 2012/10/21 21:26:40 tg Exp $");
extern char **environ;
@@ -464,6 +464,16 @@ main_init(int argc, const char *argv[], Source **sp, struct block **lp)
s = pushs(SSTRINGCMDLINE, ATEMP);
if (!(s->start = s->str = argv[argi++]))
errorf("%s %s", "-c", "requires an argument");
#ifndef MKSH_SMALL
while (*s->str) {
if (*s->str != ' ' && ctype(*s->str, C_QUOTE))
break;
s->str++;
}
if (!*s->str)
s->flags |= SF_MAYEXEC;
s->str = s->start;
#endif
#ifdef MKSH_MIDNIGHTBSD01ASH_COMPAT
/* compatibility to MidnightBSD 0.1 /bin/sh (kludge) */
if (Flag(FSH) && argv[argi] && !strcmp(argv[argi], "--"))
@@ -818,7 +828,9 @@ shell(Source * volatile s, volatile bool toplevel)
}
t = compile(s, sfirst);
sfirst = false;
if (t != NULL && t->type == TEOF) {
if (!t)
goto source_no_tree;
if (t->type == TEOF) {
if (wastty && Flag(FIGNOREEOF) && --attempts > 0) {
shellf("Use 'exit' to leave mksh\n");
s->type = SSTDIN;
@@ -838,12 +850,17 @@ shell(Source * volatile s, volatile bool toplevel)
break;
}
}
if (t && (!Flag(FNOEXEC) || (s->flags & SF_TTY)))
#ifndef MKSH_SMALL
else if ((s->flags & SF_MAYEXEC) && t->type == TCOM)
t->u.evalflags |= DOTCOMEXEC;
#endif
if (!Flag(FNOEXEC) || (s->flags & SF_TTY))
exstat = execute(t, 0, NULL);
if (t != NULL && t->type != TEOF && interactive && really_exit)
if (t->type != TEOF && interactive && really_exit)
really_exit = false;
source_no_tree:
reclaim();
}
quitenv(NULL);