aboutsummaryrefslogtreecommitdiff
path: root/toys
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2020-04-06 13:35:21 -0500
committerRob Landley <rob@landley.net>2020-04-06 13:35:21 -0500
commit017a59e211c7430631329fe8a40427accca9b92d (patch)
tree7972804fe672c95ab5ff4cdf78b1767540d92c90 /toys
parentce6220787701c4144ac46cc2b461f6690043787a (diff)
downloadtoybox-017a59e211c7430631329fe8a40427accca9b92d.tar.gz
Pass more tests, and detect ELF files (don't try to run them as shell scripts).
Don't fall back to stdin if we can't find shell script on command line.
Diffstat (limited to 'toys')
-rw-r--r--toys/pending/sh.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/toys/pending/sh.c b/toys/pending/sh.c
index e09fe3e8..55c30a19 100644
--- a/toys/pending/sh.c
+++ b/toys/pending/sh.c
@@ -501,7 +501,7 @@ static char *parse_word(char *start, int early)
if (s != end) return (end == start) ? s : end;
// (( is a special quote at the start of a word
- if (strstart(&end, "((")) toybuf[quote++] = 255;
+ if (strstart(&end, "((")) toybuf[quote++] = 254;
// find end of this word
while (*end) {
@@ -517,13 +517,14 @@ static char *parse_word(char *start, int early)
if ((q = quote ? toybuf[quote-1] : 0)) {
// when waiting for parentheses, they nest
- if ((q == ')' || q == '\xff') && (*end == '(' || *end == ')')) {
+ if ((q == ')' || q >= 254) && (*end == '(' || *end == ')')) {
if (*end == '(') qc++;
else if (qc) qc--;
- else if (q == '\xff') {
+ else if (q >= 254) {
// (( can end with )) or retroactively become two (( if we hit one )
if (strstart(&end, "))")) quote--;
- else return start+1;
+ else if (q == 254) return start+1;
+ else if (q == 255) toybuf[quote-1] = ')';
} else if (*end == ')') quote--;
end++;
@@ -871,7 +872,7 @@ if (BUGBUG) dprintf(255, "expand %s\n", str);
s = str+ii-1;
kk = parse_word(str+ii-1, 1)-s;
- if (*toybuf == 0xff) {
+ if (*toybuf == 255) {
s += 3;
kk -= 5;
dprintf(2, "TODO: do math for %.*s\n", kk, s);
@@ -899,7 +900,7 @@ dprintf(2, "TODO: do math for %.*s\n", kk, s);
}
// TODO what does \ in `` mean? What is echo `printf %s \$x` supposed to do?
- if (!ss) jj = pipe_subshell(s, kk, 1);
+ if (!ss) jj = pipe_subshell(s, kk, 0);
if ((ifs = del = readfd(jj, 0, &pp)))
for (kk = strlen(ifs); kk && ifs[kk-1]=='\n'; ifs[--kk] = 0);
close(jj);
@@ -1634,6 +1635,7 @@ static int parse_line(char *line, struct sh_function *sp)
// Parse next word and detect overflow (too many nested quotes).
if ((end = parse_word(start, 0)) == (void *)1) goto flush;
+if (BUGBUG>1) dprintf(255, "[%.*s]%c", end ? (int)(end-start) : 0, start, pl ? ' ' : '\n');
// Is this a new pipeline segment?
if (!pl) {
pl = xzalloc(sizeof(struct sh_pipeline));
@@ -2417,11 +2419,12 @@ static void subshell_setup(void)
void sh_main(void)
{
- FILE *f;
char *new, *cc = TT.sh.c;
struct sh_function scratch;
int prompt = 0, ii = FLAG(i);
+ struct string_list *sl = 0;
struct sh_arg arg;
+ FILE *f;
signal(SIGPIPE, SIG_IGN);
@@ -2459,18 +2462,17 @@ if (BUGBUG) { int fd = open("/dev/tty", O_RDWR); dup2(fd, 255); close(fd); }
else if (*toys.optargs) {
// TODO: syntax_err should exit from shell scripts
if (!(f = fopen(*toys.optargs, "r"))) {
- char *pp = getvar("PATH");
-
- struct string_list *sl = find_in_path(pp?pp:_PATH_DEFPATH, *toys.optargs);
+ char *pp = getvar("PATH") ? : _PATH_DEFPATH;
- for (;sl; free(llist_pop(&sl))) if ((f = fopen(sl->str, "r"))) break;
- llist_traverse(sl, free);
+ for (sl = find_in_path(pp, *toys.optargs); sl; free(llist_pop(&sl)))
+ if ((f = fopen(sl->str, "r"))) break;
+ if (sl) llist_traverse(sl->next, free);
+ else perror_exit_raw(*toys.optargs);
}
} else f = stdin;
+ // Loop prompting and reading lines
for (;;) {
-
- // Prompt and read line
TT.lineno++;
if (ii && f == stdin) {
char *s = getvar(prompt ? "PS2" : "PS1");
@@ -2480,7 +2482,12 @@ if (BUGBUG) { int fd = open("/dev/tty", O_RDWR); dup2(fd, 255); close(fd); }
}
// TODO line editing/history, should set $COLUMNS $LINES and sigwinch update
- if (!(new = xgetline(f ? f : stdin, 0))) break;
+ if (!(new = xgetline(f, 0))) break;
+ if (sl) {
+ if (*new == 0x7f) error_exit("'%s' is ELF", sl->str);
+ free(sl);
+ sl = 0;
+ }
// TODO if (!isspace(*new)) add_to_history(line);
// returns 0 if line consumed, command if it needs more data