diff options
author | Axel Beckert <abe@deuxchevaux.org> | 2020-02-14 01:58:20 +0100 |
---|---|---|
committer | Axel Beckert <abe@deuxchevaux.org> | 2020-02-14 01:58:20 +0100 |
commit | bfc5d42735c1660263904ec5254cccf539a0a458 (patch) | |
tree | 9bbb81b4a53941427e6f9e65ae55027d9108df8c /Src/exec.c | |
parent | 74561cc51b8867e43cb2937ab2edfb36e2a829bf (diff) | |
parent | 643de931640e01aa246723d2038328ef33737965 (diff) | |
download | zsh-bfc5d42735c1660263904ec5254cccf539a0a458.tar.gz zsh-bfc5d42735c1660263904ec5254cccf539a0a458.zip |
Merge tag 'zsh-5.7.1-test-3' into debian
Test release: 5.7.1-test-3
Diffstat (limited to 'Src/exec.c')
-rw-r--r-- | Src/exec.c | 90 |
1 files changed, 57 insertions, 33 deletions
diff --git a/Src/exec.c b/Src/exec.c index 042ba065a..50027654a 100644 --- a/Src/exec.c +++ b/Src/exec.c @@ -940,6 +940,8 @@ hashcmd(char *arg0, char **pp) char *s, buf[PATH_MAX+1]; char **pq; + if (*arg0 == '/') + return NULL; for (; *pp; pp++) if (**pp == '/') { s = buf; @@ -969,6 +971,10 @@ hashcmd(char *arg0, char **pp) return cn; } +/* The value that 'locallevel' had when we forked. When we get back to this + * level, the current process (which is a subshell) will terminate. + */ + /**/ int forklevel; @@ -1688,7 +1694,8 @@ execpline(Estate state, wordcode slcode, int how, int last1) lastwj = thisjob = newjob; - if (list_pipe || (pline_level && !(how & Z_TIMED))) + if (list_pipe || (pline_level && !(how & Z_TIMED) && + !(jn->stat & STAT_NOSTTY))) jn->stat |= STAT_NOPRINT; if (nowait) { @@ -2533,7 +2540,7 @@ setunderscore(char *str) { queue_signals(); if (str && *str) { - int l = strlen(str) + 1, nl = (l + 31) & ~31; + size_t l = strlen(str) + 1, nl = (l + 31) & ~31; if (nl > underscorelen || (underscorelen - nl) > 64) { zfree(zunderscore, underscorelen); @@ -2762,9 +2769,12 @@ execcmd_fork(Estate state, int how, int type, Wordcode varspc, sigtrapped[SIGEXIT] = 0; #ifdef HAVE_NICE /* Check if we should run background jobs at a lower priority. */ - if ((how & Z_ASYNC) && isset(BGNICE)) - if (nice(5) < 0) + if ((how & Z_ASYNC) && isset(BGNICE)) { + errno = 0; + nice(5); + if (errno) zwarn("nice(5) failed: %e", errno); + } #endif /* HAVE_NICE */ return 0; @@ -4293,7 +4303,7 @@ save_params(Estate state, Wordcode pc, LinkList *restore_p, LinkList *remove_p) (unset(RESTRICTED) || !(pm->node.flags & PM_RESTRICTED))) { /* * In this case we're just saving parts of - * the parameter in a tempory, so use heap allocation + * the parameter in a temporary, so use heap allocation * and don't bother copying every detail. */ tpm = (Param) hcalloc(sizeof *tpm); @@ -4405,8 +4415,10 @@ closem(int how, int all) /* * Process substitution needs to be visible to user; * fd's are explicitly cleaned up by filelist handling. + * External FDs are managed directly by the user. */ - (all || fdtable[i] != FDT_PROC_SUBST) && + (all || (fdtable[i] != FDT_PROC_SUBST && + fdtable[i] != FDT_EXTERNAL)) && (how == FDT_UNUSED || (fdtable[i] & FDT_TYPE_MASK) == how)) { if (i == SHTTY) SHTTY = -1; @@ -4638,19 +4650,25 @@ getoutput(char *cmd, int qt) return NULL; } -/* read output of command substitution */ +/* read output of command substitution + * + * The file descriptor "in" is closed by the function. + * + * "qt" indicates if the substitution was in double quotes. + * + * "readerror", if not NULL, is used to return any error that + * occurred during the read. + */ /**/ mod_export LinkList readoutput(int in, int qt, int *readerror) { LinkList ret; - char *buf, *ptr; - int bsiz, c, cnt = 0; - FILE *fin; + char *buf, *bufptr, *ptr, inbuf[64]; + int bsiz, c, cnt = 0, readret; int q = queue_signal_level(); - fin = fdopen(in, "r"); ret = newlinklist(); ptr = buf = (char *) hcalloc(bsiz = 64); /* @@ -4662,33 +4680,38 @@ readoutput(int in, int qt, int *readerror) */ dont_queue_signals(); child_unblock(); - while ((c = fgetc(fin)) != EOF || errno == EINTR) { - if (c == EOF) { - errno = 0; - clearerr(fin); - continue; - } - if (imeta(c)) { - *ptr++ = Meta; - c ^= 32; - cnt++; + for (;;) { + readret = read(in, inbuf, 64); + if (readret <= 0) { + if (readret < 0 && errno == EINTR) + continue; + else + break; } - if (++cnt >= bsiz) { - char *pp; - queue_signals(); - pp = (char *) hcalloc(bsiz *= 2); - dont_queue_signals(); + for (bufptr = inbuf; bufptr < inbuf + readret; bufptr++) { + c = *bufptr; + if (imeta(c)) { + *ptr++ = Meta; + c ^= 32; + cnt++; + } + if (++cnt >= bsiz) { + char *pp; + queue_signals(); + pp = (char *) hcalloc(bsiz *= 2); + dont_queue_signals(); - memcpy(pp, buf, cnt - 1); - ptr = (buf = pp) + cnt - 1; + memcpy(pp, buf, cnt - 1); + ptr = (buf = pp) + cnt - 1; + } + *ptr++ = c; } - *ptr++ = c; } child_block(); restore_queue_signals(q); if (readerror) - *readerror = ferror(fin) ? errno : 0; - fclose(fin); + *readerror = readret < 0 ? errno : 0; + close(in); while (cnt && ptr[-1] == '\n') ptr--, cnt--; *ptr = '\0'; @@ -4821,6 +4844,7 @@ getoutputfile(char *cmd, char **eptr) } /* pid == 0 */ + closem(FDT_UNUSED, 0); redup(fd, 1); entersubsh(ESUB_PGRP|ESUB_NOMONITOR, NULL); cmdpush(CS_CMDSUBST); @@ -4982,7 +5006,7 @@ getpipe(char *cmd, int nullexec) procsubstpid = pid; return pipes[!out]; } - entersubsh(ESUB_PGRP, NULL); + entersubsh(ESUB_ASYNC|ESUB_PGRP, NULL); redup(pipes[out], out); closem(FDT_UNUSED, 0); /* this closes pipes[!out] as well */ cmdpush(CS_CMDSUBST); @@ -5929,7 +5953,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval) * exit command was handled. */ stopmsg = 1; - zexit(exit_val, 0); + zexit(exit_val, ZEXIT_NORMAL); } } |