ash: make "jobs -l" more similar to bash. By Earl Chew. Fixes bug 481

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2009-08-23 22:10:04 +02:00
parent bd73f1d85a
commit a12af2d9f3

View File

@ -3240,9 +3240,9 @@ unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
#define FORK_NOJOB 2 #define FORK_NOJOB 2
/* mode flags for showjob(s) */ /* mode flags for showjob(s) */
#define SHOW_PGID 0x01 /* only show pgid - for jobs -p */ #define SHOW_ONLY_PGID 0x01 /* show only pgid (jobs -p) */
#define SHOW_PID 0x04 /* include process pid */ #define SHOW_PIDS 0x02 /* show individual pids, not just one line per job */
#define SHOW_CHANGED 0x08 /* only jobs whose state has changed */ #define SHOW_CHANGED 0x04 /* only jobs whose state has changed */
/* /*
* A job structure contains information about a job. A job is either a * A job structure contains information about a job. A job is either a
@ -3250,7 +3250,6 @@ unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
* latter case, pidlist will be non-NULL, and will point to a -1 terminated * latter case, pidlist will be non-NULL, and will point to a -1 terminated
* array of pids. * array of pids.
*/ */
struct procstat { struct procstat {
pid_t pid; /* process id */ pid_t pid; /* process id */
int status; /* last process status from wait() */ int status; /* last process status from wait() */
@ -3935,7 +3934,7 @@ showjob(FILE *out, struct job *jp, int mode)
ps = jp->ps; ps = jp->ps;
if (mode & SHOW_PGID) { if (mode & SHOW_ONLY_PGID) { /* jobs -p */
/* just output process (group) id of pipeline */ /* just output process (group) id of pipeline */
fprintf(out, "%d\n", ps->pid); fprintf(out, "%d\n", ps->pid);
return; return;
@ -3945,11 +3944,11 @@ showjob(FILE *out, struct job *jp, int mode)
indent_col = col; indent_col = col;
if (jp == curjob) if (jp == curjob)
s[col - 2] = '+'; s[col - 3] = '+';
else if (curjob && jp == curjob->prev_job) else if (curjob && jp == curjob->prev_job)
s[col - 2] = '-'; s[col - 3] = '-';
if (mode & SHOW_PID) if (mode & SHOW_PIDS)
col += fmtstr(s + col, 16, "%d ", ps->pid); col += fmtstr(s + col, 16, "%d ", ps->pid);
psend = ps + jp->nprocs; psend = ps + jp->nprocs;
@ -3963,25 +3962,32 @@ showjob(FILE *out, struct job *jp, int mode)
status = jp->stopstatus; status = jp->stopstatus;
col += sprint_status(s + col, status, 0); col += sprint_status(s + col, status, 0);
} }
/* By now, "[JOBID]* [maybe PID] STATUS" is printed */
/* This loop either prints "<cmd1> | <cmd2> | <cmd3>" line
* or prints several "PID | <cmdN>" lines,
* depending on SHOW_PIDS bit.
* We do not print status of individual processes
* between PID and <cmdN>. bash does it, but not very well:
* first line shows overall job status, not process status,
* making it impossible to know 1st process status.
*/
goto start; goto start;
while (1) {
do {
/* for each process */ /* for each process */
col = fmtstr(s, 48, " |\n%*c%d ", indent_col, ' ', ps->pid) - 3; s[0] = '\0';
col = 33;
if (mode & SHOW_PIDS)
col = fmtstr(s, 48, "\n%*c%d ", indent_col, ' ', ps->pid) - 1;
start: start:
fprintf(out, "%s%*c%s", fprintf(out, "%s%*c", s, 33 - col >= 0 ? 33 - col : 0, ' ');
s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd if (ps != jp->ps)
); fprintf(out, "| ");
if (!(mode & SHOW_PID)) { fprintf(out, "%s", ps->cmd);
showpipe(jp, out); if (++ps == psend)
break; break;
} }
if (++ps == psend) { outcslow('\n', out);
outcslow('\n', out);
break;
}
} while (1);
jp->changed = 0; jp->changed = 0;
@ -4021,15 +4027,15 @@ jobscmd(int argc UNUSED_PARAM, char **argv)
mode = 0; mode = 0;
while ((m = nextopt("lp"))) { while ((m = nextopt("lp"))) {
if (m == 'l') if (m == 'l')
mode = SHOW_PID; mode |= SHOW_PIDS;
else else
mode = SHOW_PGID; mode |= SHOW_ONLY_PGID;
} }
argv = argptr; argv = argptr;
if (*argv) { if (*argv) {
do do
showjob(stdout, getjob(*argv,0), mode); showjob(stdout, getjob(*argv, 0), mode);
while (*++argv); while (*++argv);
} else } else
showjobs(stdout, mode); showjobs(stdout, mode);