summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--Doc/Zsh/options.yo11
-rw-r--r--Src/exec.c26
-rw-r--r--Src/jobs.c103
-rw-r--r--Src/options.c1
-rw-r--r--Src/signals.c1
-rw-r--r--Src/zsh.h2
-rw-r--r--Test/A01grammar.ztst4
8 files changed, 111 insertions, 47 deletions
diff --git a/ChangeLog b/ChangeLog
index 2965824e1..fea458cff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2009-07-10 Peter Stephenson <pws@csr.com>
+ * 27122: Doc/Zsh/options.yo, Src/jobs.c, Src/options.c, Src/zsh.h:
+ add POSIX_JOBS option to print only job text for bg and fg.
+
+ * 27106: Src/exec.c, Src/signals.c, Src/zsh.h,
+ Test/A01grammar.ztst: on a command line that had text that
+ expanded to nothing reset the status (unless it should come
+ from a command substitution).
+
* 27119: Src/jobs.c: correct 27112: output is to stdout, not
stderr, and there's no automated jobs notification if not
INTERACTIVE.
@@ -11937,5 +11945,5 @@
*****************************************************
* This is used by the shell to define $ZSH_PATCHLEVEL
-* $Revision: 1.4732 $
+* $Revision: 1.4733 $
*****************************************************
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index c9e9b7be5..7a2c732d1 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -1274,6 +1274,17 @@ item(tt(NOTIFY) (tt(-5), ksh: tt(-b)) <Z>)(
Report the status of background jobs immediately, rather than
waiting until just before printing a prompt.
)
+pindex(POSIX_JOBS)
+pindex(POSIXJOBS)
+pindex(NO_POSIX_JOBS)
+pindex(NOPOSIXJOBS)
+cindex(bg, output in POSIX format)
+cindex(fg, output in POSIX format)
+item(tt(POSIX_JOBS) <K> <S>)(
+When putting jobs in the background or foreground with tt(bg) or tt(fg),
+just print the text of the job as required by POSIX,
+rather than the full information that would be output by tt(jobs).
+)
enditem()
subsect(Prompting)
diff --git a/Src/exec.c b/Src/exec.c
index 4f15ebefa..852d75bb5 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -151,6 +151,15 @@ pid_t cmdoutpid;
/**/
int cmdoutval;
+/*
+ * This is set by an exiting $(...) substitution to indicate we need
+ * to retain the status. We initialize it to zero if we think we need
+ * to reset the status for a command.
+ */
+
+/**/
+int use_cmdoutval;
+
/* The context in which a shell function is called, see SFC_* in zsh.h. */
/**/
@@ -2262,6 +2271,14 @@ execcmd(Estate state, int input, int output, int how, int last1)
*/
if (!args && varspc)
lastval = errflag ? errflag : cmdoutval;
+ /*
+ * If there are arguments, we should reset the status for the
+ * command before execution---unless we are using the result of a
+ * command substitution, which will be indicated by setting
+ * use_cmdoutval to 1. We haven't kicked those off yet, so
+ * there's no race.
+ */
+ use_cmdoutval = !args;
for (i = 0; i < 10; i++) {
save[i] = -2;
@@ -2478,7 +2495,12 @@ execcmd(Estate state, int input, int output, int how, int last1)
lastval = 0;
return;
} else {
- cmdoutval = lastval;
+ /*
+ * No arguments. Reset the status if there were
+ * arguments before and no command substitution
+ * has provided a status.
+ */
+ cmdoutval = use_cmdoutval ? lastval : 0;
if (varspc)
addvars(state, varspc, 0);
if (errflag)
@@ -4674,6 +4696,7 @@ execsave(void)
es->badcshglob = badcshglob;
es->cmdoutpid = cmdoutpid;
es->cmdoutval = cmdoutval;
+ es->use_cmdoutval = use_cmdoutval;
es->trap_return = trap_return;
es->trap_state = trap_state;
es->trapisfunc = trapisfunc;
@@ -4704,6 +4727,7 @@ execrestore(void)
badcshglob = exstack->badcshglob;
cmdoutpid = exstack->cmdoutpid;
cmdoutval = exstack->cmdoutval;
+ use_cmdoutval = exstack->use_cmdoutval;
trap_return = exstack->trap_return;
trap_state = exstack->trap_state;
trapisfunc = exstack->trapisfunc;
diff --git a/Src/jobs.c b/Src/jobs.c
index 0841a45c9..6c673b74a 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -813,6 +813,7 @@ should_report_time(Job j)
* synch = 0 means asynchronous
* synch = 1 means synchronous
* synch = 2 means called synchronously from jobs
+ * synch = 3 means called synchronously from bg or fg
*
* Returns 1 if some output was done.
*
@@ -884,12 +885,18 @@ printjob(Job jn, int lng, int synch)
}
}
-/* print if necessary: ignore option state on explicit call to `jobs'. */
-
+ /*
+ * - Always print if called from jobs
+ * - Otherwise, require MONITOR option ("jobbing") and some
+ * change of state
+ * - also either the shell is interactive or this is synchronous.
+ */
if (synch == 2 ||
- (interact && jobbing &&
+ ((interact || synch) && jobbing &&
((jn->stat & STAT_STOPPED) || sflag || job != thisjob))) {
int len2, fline = 1;
+ /* POSIX requires just the job text for bg and fg */
+ int plainfmt = (synch == 3) && isset(POSIXJOBS);
/* use special format for current job, except in `jobs' */
int thisfmt = job == thisjob && synch != 2;
Process qn;
@@ -908,54 +915,60 @@ printjob(Job jn, int lng, int synch)
for (qn = pn->next; qn; qn = qn->next) {
if (qn->status != pn->status)
break;
- if ((int)strlen(qn->text) + len2 + ((qn->next) ? 3 : 0) > lineleng)
+ if ((int)strlen(qn->text) + len2 + ((qn->next) ? 3 : 0)
+ > lineleng)
break;
len2 += strlen(qn->text) + 2;
}
doneprint = 1;
- if (!thisfmt || lng) {
- if (fline)
- fprintf(fout, "[%ld] %c ",
- (long)job,
- (job == curjob) ? '+'
- : (job == prevjob) ? '-' : ' ');
- else
- fprintf(fout, (job > 9) ? " " : " ");
- } else
- fprintf(fout, "zsh: ");
- if (lng & 1)
- fprintf(fout, "%ld ", (long) pn->pid);
- else if (lng & 2) {
- pid_t x = jn->gleader;
-
- fprintf(fout, "%ld ", (long) x);
- do
+ if (!plainfmt) {
+ if (!thisfmt || lng) {
+ if (fline)
+ fprintf(fout, "[%ld] %c ",
+ (long)job,
+ (job == curjob) ? '+'
+ : (job == prevjob) ? '-' : ' ');
+ else
+ fprintf(fout, (job > 9) ? " " : " ");
+ } else
+ fprintf(fout, "zsh: ");
+ if (lng & 1)
+ fprintf(fout, "%ld ", (long) pn->pid);
+ else if (lng & 2) {
+ pid_t x = jn->gleader;
+
+ fprintf(fout, "%ld ", (long) x);
+ do
+ skip++;
+ while ((x /= 10));
skip++;
- while ((x /= 10));
- skip++;
- lng &= ~3;
- } else
- fprintf(fout, "%*s", skip, "");
- if (pn->status == SP_RUNNING) {
- if (!conted)
- fprintf(fout, "running%*s", len - 7 + 2, "");
+ lng &= ~3;
+ } else
+ fprintf(fout, "%*s", skip, "");
+ if (pn->status == SP_RUNNING) {
+ if (!conted)
+ fprintf(fout, "running%*s", len - 7 + 2, "");
+ else
+ fprintf(fout, "continued%*s", len - 9 + 2, "");
+ }
+ else if (WIFEXITED(pn->status)) {
+ if (WEXITSTATUS(pn->status))
+ fprintf(fout, "exit %-4d%*s", WEXITSTATUS(pn->status),
+ len - 9 + 2, "");
+ else
+ fprintf(fout, "done%*s", len - 4 + 2, "");
+ } else if (WIFSTOPPED(pn->status))
+ fprintf(fout, "%-*s", len + 2,
+ sigmsg(WSTOPSIG(pn->status)));
+ else if (WCOREDUMP(pn->status))
+ fprintf(fout, "%s (core dumped)%*s",
+ sigmsg(WTERMSIG(pn->status)),
+ (int)(len - 14 + 2 -
+ strlen(sigmsg(WTERMSIG(pn->status)))), "");
else
- fprintf(fout, "continued%*s", len - 9 + 2, "");
+ fprintf(fout, "%-*s", len + 2,
+ sigmsg(WTERMSIG(pn->status)));
}
- else if (WIFEXITED(pn->status)) {
- if (WEXITSTATUS(pn->status))
- fprintf(fout, "exit %-4d%*s", WEXITSTATUS(pn->status),
- len - 9 + 2, "");
- else
- fprintf(fout, "done%*s", len - 4 + 2, "");
- } else if (WIFSTOPPED(pn->status))
- fprintf(fout, "%-*s", len + 2, sigmsg(WSTOPSIG(pn->status)));
- else if (WCOREDUMP(pn->status))
- fprintf(fout, "%s (core dumped)%*s",
- sigmsg(WTERMSIG(pn->status)),
- (int)(len - 14 + 2 - strlen(sigmsg(WTERMSIG(pn->status)))), "");
- else
- fprintf(fout, "%-*s", len + 2, sigmsg(WTERMSIG(pn->status)));
for (; pn != qn; pn = pn->next) {
char *txt = dupstring(pn->text);
int txtlen;
@@ -1905,7 +1918,7 @@ bin_fg(char *name, char **argv, Options ops, int func)
}
if (func != BIN_WAIT)
/* for bg and fg -- show the job we are operating on */
- printjob(jobtab + job, (stopped) ? -1 : lng, 1);
+ printjob(jobtab + job, (stopped) ? -1 : lng, 3);
if (func != BIN_BG) { /* fg or wait */
if (jobtab[job].pwd && strcmp(jobtab[job].pwd, pwd)) {
FILE *fout = (func == BIN_JOBS || !shout) ? stdout : shout;
diff --git a/Src/options.c b/Src/options.c
index b2b306cd9..8e5308c0b 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -201,6 +201,7 @@ static struct optname optns[] = {
{{NULL, "posixaliases", OPT_EMULATE|OPT_BOURNE}, POSIXALIASES},
{{NULL, "posixbuiltins", OPT_EMULATE|OPT_BOURNE}, POSIXBUILTINS},
{{NULL, "posixidentifiers", OPT_EMULATE|OPT_BOURNE}, POSIXIDENTIFIERS},
+{{NULL, "posixjobs", OPT_EMULATE|OPT_BOURNE}, POSIXJOBS},
{{NULL, "printeightbit", 0}, PRINTEIGHTBIT},
{{NULL, "printexitvalue", 0}, PRINTEXITVALUE},
{{NULL, "privileged", OPT_SPECIAL}, PRIVILEGED},
diff --git a/Src/signals.c b/Src/signals.c
index 5d1797f2f..723b121a8 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -494,6 +494,7 @@ zhandler(int sig)
*procsubval = (0200 | WTERMSIG(status));
else
*procsubval = WEXITSTATUS(status);
+ use_cmdoutval = 1;
get_usage();
cont = 1;
break;
diff --git a/Src/zsh.h b/Src/zsh.h
index bd872a55a..2a23ad36a 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -930,6 +930,7 @@ struct execstack {
int badcshglob;
pid_t cmdoutpid;
int cmdoutval;
+ int use_cmdoutval;
int trap_return;
int trap_state;
int trapisfunc;
@@ -1955,6 +1956,7 @@ enum {
POSIXALIASES,
POSIXBUILTINS,
POSIXIDENTIFIERS,
+ POSIXJOBS,
PRINTEIGHTBIT,
PRINTEXITVALUE,
PRIVILEGED,
diff --git a/Test/A01grammar.ztst b/Test/A01grammar.ztst
index e976c8356..b250d0984 100644
--- a/Test/A01grammar.ztst
+++ b/Test/A01grammar.ztst
@@ -23,6 +23,10 @@
true | false
1:Exit status of pipeline with builtins (false)
+ false
+ $nonexistent_variable
+0:Executing command that evaluates to empty resets status
+
fn() { local foo; read foo; print $foo; }
coproc fn
print -p coproc test output