View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000531 | tcsh | General | public | 2024-05-31 04:46 | 2024-05-31 04:46 |
Reporter | MProG10 | Assigned To | |||
Priority | normal | Severity | minor | Reproducibility | N/A |
Status | new | Resolution | open | ||
Summary | 0000531: Variable assignment from pipes and redirections | ||||
Description | In recognition of Bourne-compatible Shells and Mashey Shell, I came up with an implementation for assigning variables from pipes and redirections. Normal assignment reads until EOF or a newline is found. Indexed assignment reads until EOF. This is implemented for environment variable assignment as well. In order to avoid confusion with manual assignment, assignment from pipes and redirections is only possible if the variable name doesn't precede the assignment operator [equal sign]. This means subsequent names in a single command (e.g: set a b c) will be assigned from a pipe or redirection. If the name precedes the assignment operator, subsequent names, even if preceded or not by the assignment operator, won't read from a pipe or redirection. This work also provides a fix for pipes and piped built-ins, at the cost of having piped built-ins forked. I don't think this cost should be taken badly, since most (if not all) Bourne-compatible Shells fork piped built-ins. The fix remedies the issue regarded here [https://mailman.astron.com/pipermail/tcsh/2023-November/000337.html], on blank output from pipes. | ||||
Additional Information | https://github.com/tcsh-org/tcsh/pull/105 https://mailman.astron.com/pipermail/tcsh/2023-November/000337.html | ||||
Tags | No tags attached. | ||||
|
sh.func.c.diff (590 bytes)
--- a/sh.func.c +++ b/sh.func.c @@ -1353,8 +1353,21 @@ dosetenv(Char **v, struct command *c) if (*lp != '\0') stderror(ERR_NAME | ERR_VARALNUM); - if ((lp = *v++) == 0) - lp = STRNULL; + if ((lp = *v++) == 0) { + if (c->t_dlef || !isatty(OLDSTD)) { + Char c; + struct Strbuf s = Strbuf_INIT; + + while (wide_read(0, &c, (size_t) 1, 0) > 0) { + if (c == '\n') + break; + Strbuf_append1(&s, c | LITERAL); + } + Strbuf_terminate(&s); + lp = s.s; + } else + lp = STRNULL; + } lp = globone(lp, G_APPEND); cleanup_push(lp, xfree); sh.sem.c.diff (2,517 bytes)
--- a/sh.sem.c +++ b/sh.sem.c @@ -367,23 +367,13 @@ execute(struct command *t, volatile int wanttty, int *pipein, int *pipeout, if (bifunc && (t->t_dflg & F_PIPEIN)) t->t_dflg &= ~(F_NOFORK); #endif /* BACKPIPE */ - /* - * Prevent forking cd, pushd, popd, chdir cause this will cause the - * shell not to change dir! (XXX: but only for nice?) - */ - if (bifunc && (bifunc->bfunct == (bfunc_t)dochngd || - bifunc->bfunct == (bfunc_t)dopushd || - bifunc->bfunct == (bfunc_t)dopopd)) - t->t_dflg &= ~(F_NICE); - if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 && (!bifunc || t->t_dflg & (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP | F_HUP)))) || /* - * We have to fork for eval too. + * We have to fork for piped built-ins too. */ - (bifunc && (t->t_dflg & F_PIPEIN) != 0 && - bifunc->bfunct == (bfunc_t)doeval)) { + (bifunc && (t->t_dflg & F_PIPEIN) != 0)) { #ifdef VFORK if (t->t_dtyp == NODE_PAREN || t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) @@ -631,17 +621,6 @@ execute(struct command *t, volatile int wanttty, int *pipein, int *pipeout, } doio(t, pipein, pipeout); -#ifdef BACKPIPE - if (t->t_dflg & F_PIPEIN) { - xclose(pipein[0]); - xclose(pipein[1]); - } -#else /* !BACKPIPE */ - if (t->t_dflg & F_PIPEOUT) { - xclose(pipeout[0]); - xclose(pipeout[1]); - } -#endif /* BACKPIPE */ /* * Perform a builtin function. If we are not forked, arrange for * possible stopping @@ -717,7 +696,6 @@ execute(struct command *t, volatile int wanttty, int *pipein, int *pipeout, execute(t->t_dcdr, wanttty, pv, pipeout, do_glob); #endif /* BACKPIPE */ break; - case NODE_LIST: if (t->t_dcar) { t->t_dcar->t_dflg |= t->t_dflg & (F_NOINTERRUPT | F_BACKQ); @@ -871,8 +849,7 @@ doio(struct command *t, int *pipein, int *pipeout) } else if (flags & F_PIPEIN) { xclose(0); - TCSH_IGNORE(dup(pipein[0])); - xclose(pipein[0]); + OLDSTD = dmove(pipein[0], 0); xclose(pipein[1]); } else if ((flags & F_NOINTERRUPT) && tpgrp == -1) { @@ -934,7 +911,7 @@ doio(struct command *t, int *pipein, int *pipeout) } else if (flags & F_PIPEOUT) { xclose(1); - TCSH_IGNORE(dup(pipeout[1])); + SHOUT = dcopy(pipeout[1], 1); is1atty = 0; } else { @@ -948,7 +925,7 @@ doio(struct command *t, int *pipein, int *pipeout) xclose(2); if (flags & F_STDERR) { - TCSH_IGNORE(dup(1)); + SHDIAG = dcopy(1, 2); is2atty = is1atty; } else { sh.set.c.diff (1,746 bytes)
--- a/sh.set.c +++ b/sh.set.c @@ -248,7 +248,8 @@ doset(Char **v, struct command *c) int flags = VAR_READWRITE; int first_match = 0; int last_match = 0; - int changed = 0; + int changed; + int pipe; USE(c); v++; @@ -278,6 +279,9 @@ doset(Char **v, struct command *c) plist(&shvhed, flags); return; } + pipe = 0; + if (c->t_dlef || !isatty(OLDSTD)) + pipe = 1; do { hadsub = 0; vp = p; @@ -300,6 +304,7 @@ doset(Char **v, struct command *c) else if (*v && eq(*v, STRequal)) { if (*++v != NULL) p = *v++; + pipe = 0; } if (eq(p, STRLparen)) { Char **e = v; @@ -328,14 +333,48 @@ doset(Char **v, struct command *c) else if (hadsub) { Char *copy; - copy = Strsave(p); + if (pipe) { + Char c; + struct Strbuf s = Strbuf_INIT; + + while (wide_read(0, &c, (size_t) 1, 0) > 0) + Strbuf_append1(&s, c | LITERAL); + Strbuf_terminate(&s); + copy = s.s; + } else + copy = Strsave(p); cleanup_push(copy, xfree); asx(vp, subscr, copy); cleanup_ignore(copy); cleanup_until(copy); } - else - setv(vp, Strsave(p), flags); + else { + if (pipe) { + Char c; + struct Strbuf s = Strbuf_INIT; + int empty = 1; + + while (wide_read(0, &c, (size_t) 1, 0) > 0) { + if (c == '\n') { + empty = 0; + + break; + } + Strbuf_append1(&s, c | LITERAL); + } + if (empty && s.s == NULL) { + Char **empty; + + *(empty = xmalloc(sizeof *empty)) = NULL; + set1(vp, empty, &shvhed, flags); + } + else { + Strbuf_terminate(&s); + setv(vp, s.s, flags); + } + } else + setv(vp, Strsave(p), flags); + } update_vars(vp); } while ((p = *v++) != NULL); } |