svn commit: r216217 - head/bin/sh

Jilles Tjoelker jilles at FreeBSD.org
Sun Dec 5 22:37:02 UTC 2010


Author: jilles
Date: Sun Dec  5 22:37:01 2010
New Revision: 216217
URL: http://svn.freebsd.org/changeset/base/216217

Log:
  sh: Improve jobs output of pipelines.
  
  If describing the status of a pipeline, write all elements of the pipeline
  and show the status of the last process (which would also end up in $?).
  Only write one report per job, not one for every process that exits.
  
  To keep some earlier behaviour, if any process started by the shell in a
  foreground job terminates because of a signal, write a message about the
  signal (at most one message per job, however).
  
  Also, do not write messages about signals in the wait builtin in
  non-interactive shells. Only true foreground jobs now write such messages
  (for example, "Terminated").

Modified:
  head/bin/sh/jobs.c

Modified: head/bin/sh/jobs.c
==============================================================================
--- head/bin/sh/jobs.c	Sun Dec  5 22:24:34 2010	(r216216)
+++ head/bin/sh/jobs.c	Sun Dec  5 22:37:01 2010	(r216217)
@@ -100,7 +100,8 @@ static void setcurjob(struct job *);
 static void deljob(struct job *);
 static struct job *getcurjob(struct job *);
 #endif
-static void showjob(struct job *, pid_t, int);
+static void printjobcmd(struct job *);
+static void showjob(struct job *, int);
 
 
 /*
@@ -205,8 +206,7 @@ fgcmd(int argc __unused, char **argv)
 	jp = getjob(argv[1]);
 	if (jp->jobctl == 0)
 		error("job not created under job control");
-	out1str(jp->ps[0].cmd);
-	out1c('\n');
+	printjobcmd(jp);
 	flushout(&output);
 	pgrp = jp->ps[0].pid;
 	tcsetpgrp(ttyfd, pgrp);
@@ -235,8 +235,7 @@ bgcmd(int argc, char **argv)
 		jp->foreground = 0;
 		fmtstr(s, 64, "[%td] ", jp - jobtab + 1);
 		out1str(s);
-		out1str(jp->ps[0].cmd);
-		out1c('\n');
+		printjobcmd(jp);
 	} while (--argc > 1);
 	return 0;
 }
@@ -296,15 +295,30 @@ jobscmd(int argc, char *argv[])
 		showjobs(0, mode);
 	else
 		while ((id = *argv++) != NULL)
-			showjob(getjob(id), 0, mode);
+			showjob(getjob(id), mode);
 
 	return (0);
 }
 
 static void
-showjob(struct job *jp, pid_t pid, int mode)
+printjobcmd(struct job *jp)
+{
+	struct procstat *ps;
+	int i;
+
+	for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
+		out1str(ps->cmd);
+		if (i > 0)
+			out1str(" | ");
+	}
+	out1c('\n');
+}
+
+static void
+showjob(struct job *jp, int mode)
 {
 	char s[64];
+	char statestr[64];
 	struct procstat *ps;
 	struct job *j;
 	int col, curr, i, jobno, prev, procno;
@@ -320,14 +334,44 @@ showjob(struct job *jp, pid_t pid, int m
 			prev = j - jobtab + 1;
 	}
 #endif
+	ps = jp->ps + jp->nprocs - 1;
+	if (jp->state == 0) {
+		strcpy(statestr, "Running");
+#if JOBS
+	} else if (jp->state == JOBSTOPPED) {
+		while (!WIFSTOPPED(ps->status) && ps > jp->ps)
+			ps--;
+		if (WIFSTOPPED(ps->status))
+			i = WSTOPSIG(ps->status);
+		else
+			i = -1;
+		if (i > 0 && i < sys_nsig && sys_siglist[i])
+			strcpy(statestr, sys_siglist[i]);
+		else
+			strcpy(statestr, "Suspended");
+#endif
+	} else if (WIFEXITED(ps->status)) {
+		if (WEXITSTATUS(ps->status) == 0)
+			strcpy(statestr, "Done");
+		else
+			fmtstr(statestr, 64, "Done (%d)",
+			    WEXITSTATUS(ps->status));
+	} else {
+		i = WTERMSIG(ps->status);
+		if (i > 0 && i < sys_nsig && sys_siglist[i])
+			strcpy(statestr, sys_siglist[i]);
+		else
+			fmtstr(statestr, 64, "Signal %d", i);
+		if (WCOREDUMP(ps->status))
+			strcat(statestr, " (core dumped)");
+	}
+
 	for (ps = jp->ps ; ; ps++) {	/* for each process */
 		if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
 			out1fmt("%d\n", (int)ps->pid);
 			goto skip;
 		}
-		if (mode != SHOWJOBS_VERBOSE && ps != jp->ps && pid == 0)
-			goto skip;
-		if (pid != 0 && pid != ps->pid)
+		if (mode != SHOWJOBS_VERBOSE && ps != jp->ps)
 			goto skip;
 		if (jobno == curr && ps == jp->ps)
 			c = '+';
@@ -346,39 +390,19 @@ showjob(struct job *jp, pid_t pid, int m
 			out1str(s);
 			col += strlen(s);
 		}
-		s[0] = '\0';
-		if (ps != jp->ps) {
-			*s = '\0';
-		} else if (ps->status == -1) {
-			strcpy(s, "Running");
-		} else if (WIFEXITED(ps->status)) {
-			if (WEXITSTATUS(ps->status) == 0)
-				strcpy(s, "Done");
-			else
-				fmtstr(s, 64, "Done (%d)",
-				    WEXITSTATUS(ps->status));
-		} else {
-#if JOBS
-			if (WIFSTOPPED(ps->status))
-				i = WSTOPSIG(ps->status);
-			else
-#endif
-				i = WTERMSIG(ps->status);
-			if ((i & 0x7F) < sys_nsig && sys_siglist[i & 0x7F])
-				scopy(sys_siglist[i & 0x7F], s);
-			else
-				fmtstr(s, 64, "Signal %d", i & 0x7F);
-			if (WCOREDUMP(ps->status))
-				strcat(s, " (core dumped)");
+		if (ps == jp->ps) {
+			out1str(statestr);
+			col += strlen(statestr);
 		}
-		out1str(s);
-		col += strlen(s);
 		do {
 			out1c(' ');
 			col++;
 		} while (col < 30);
-		out1str(ps->cmd);
-		out1c('\n');
+		if (mode == SHOWJOBS_VERBOSE) {
+			out1str(ps->cmd);
+			out1c('\n');
+		} else
+			printjobcmd(jp);
 skip:		if (--procno <= 0)
 			break;
 	}
@@ -410,7 +434,7 @@ showjobs(int change, int mode)
 		}
 		if (change && ! jp->changed)
 			continue;
-		showjob(jp, 0, mode);
+		showjob(jp, mode);
 		jp->changed = 0;
 		/* Hack: discard jobs for which $! has not been referenced
 		 * in interactive mode when they terminate.
@@ -958,7 +982,7 @@ dowait(int block, struct job *job)
 	int done;
 	int stopped;
 	int sig;
-	int i;
+	int coredump;
 
 	in_dowait++;
 	TRACE(("dowait(%d) called\n", block));
@@ -1017,36 +1041,29 @@ dowait(int block, struct job *job)
 		}
 	}
 	INTON;
-	if (! rootshell || ! iflag || (job && thisjob == job)) {
-#if JOBS
-		if (WIFSTOPPED(status))
-			sig = WSTOPSIG(status);
-		else
-#endif
-		{
-			if (WIFEXITED(status))
-				sig = 0;
+	if (!thisjob || thisjob->state == 0)
+		;
+	else if ((!rootshell || !iflag || thisjob == job) &&
+	    thisjob->foreground && thisjob->state != JOBSTOPPED) {
+		sig = 0;
+		coredump = 0;
+		for (sp = thisjob->ps; sp < thisjob->ps + thisjob->nprocs; sp++)
+			if (WIFSIGNALED(sp->status)) {
+				sig = WTERMSIG(sp->status);
+				coredump = WCOREDUMP(sp->status);
+			}
+		if (sig > 0 && sig != SIGINT && sig != SIGPIPE) {
+			if (sig < sys_nsig && sys_siglist[sig])
+				out1str(sys_siglist[sig]);
 			else
-				sig = WTERMSIG(status);
-		}
-		if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
-			if (!mflag ||
-			    (thisjob->foreground && !WIFSTOPPED(status))) {
-				i = WTERMSIG(status);
-				if ((i & 0x7F) < sys_nsig && sys_siglist[i & 0x7F])
-					out1str(sys_siglist[i & 0x7F]);
-				else
-					out1fmt("Signal %d", i & 0x7F);
-				if (WCOREDUMP(status))
-					out1str(" (core dumped)");
-				out1c('\n');
-			} else
-				showjob(thisjob, pid, SHOWJOBS_DEFAULT);
+				out1fmt("Signal %d", sig);
+			if (coredump)
+				out1str(" (core dumped)");
+			out1c('\n');
 		}
 	} else {
 		TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell, job));
-		if (thisjob)
-			thisjob->changed = 1;
+		thisjob->changed = 1;
 	}
 	return pid;
 }


More information about the svn-src-head mailing list