about summary refs log tree commit diff
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