From 7819e9ab69305b9516d6f50f05b04633464eebf2 Mon Sep 17 00:00:00 2001 From: stefanf Date: Sat, 7 Oct 2006 16:51:16 +0000 Subject: Add the POSIX option -p to the jobs builtin command. It prints the PID of the process leader for each job. Now the last specified option for the output format (-l, -p or -s) wins, previously -s trumped -l. PR: 99926 Submitted by: Ed Schouten and novel (patches modified by me) --- bin/sh/jobs.c | 40 +++++++++++++++++++++++----------------- bin/sh/jobs.h | 9 ++++++++- bin/sh/main.c | 2 +- bin/sh/sh.1 | 11 ++++++++--- 4 files changed, 40 insertions(+), 22 deletions(-) (limited to 'bin/sh') diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index 7e1c2c5..be9acab 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -98,7 +98,7 @@ 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, int); +STATIC void showjob(struct job *, pid_t, int); /* @@ -265,18 +265,21 @@ int jobscmd(int argc, char *argv[]) { char *id; - int ch, sformat, lformat; + int ch, mode; optind = optreset = 1; opterr = 0; - sformat = lformat = 0; - while ((ch = getopt(argc, argv, "ls")) != -1) { + mode = SHOWJOBS_DEFAULT; + while ((ch = getopt(argc, argv, "lps")) != -1) { switch (ch) { case 'l': - lformat = 1; + mode = SHOWJOBS_VERBOSE; + break; + case 'p': + mode = SHOWJOBS_PGIDS; break; case 's': - sformat = 1; + mode = SHOWJOBS_PIDS; break; case '?': default: @@ -287,24 +290,25 @@ jobscmd(int argc, char *argv[]) argv += optind; if (argc == 0) - showjobs(0, sformat, lformat); + showjobs(0, mode); else while ((id = *argv++) != NULL) - showjob(getjob(id), 0, sformat, lformat); + showjob(getjob(id), 0, mode); return (0); } STATIC void -showjob(struct job *jp, pid_t pid, int sformat, int lformat) +showjob(struct job *jp, pid_t pid, int mode) { char s[64]; struct procstat *ps; struct job *j; int col, curr, i, jobno, prev, procno; + pid_t ppid; char c; - procno = jp->nprocs; + procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs; jobno = jp - jobtab + 1; curr = prev = 0; #if JOBS @@ -315,11 +319,13 @@ showjob(struct job *jp, pid_t pid, int sformat, int lformat) } #endif for (ps = jp->ps ; ; ps++) { /* for each process */ - if (sformat) { - out1fmt("%d\n", (int)ps->pid); + if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) { + ppid = (mode == SHOWJOBS_PIDS) ? ps->pid : + getpgid(ps->pid); + out1fmt("%d\n", (int)ppid); goto skip; } - if (!lformat && ps != jp->ps && pid == 0) + if (mode != SHOWJOBS_VERBOSE && ps != jp->ps && pid == 0) goto skip; if (pid != 0 && pid != ps->pid) goto skip; @@ -335,7 +341,7 @@ showjob(struct job *jp, pid_t pid, int sformat, int lformat) fmtstr(s, 64, " %c ", c); out1str(s); col = strlen(s); - if (lformat) { + if (mode == SHOWJOBS_VERBOSE) { fmtstr(s, 64, "%d ", (int)ps->pid); out1str(s); col += strlen(s); @@ -388,7 +394,7 @@ skip: if (--procno <= 0) */ void -showjobs(int change, int sformat, int lformat) +showjobs(int change, int mode) { int jobno; struct job *jp; @@ -404,7 +410,7 @@ showjobs(int change, int sformat, int lformat) } if (change && ! jp->changed) continue; - showjob(jp, 0, sformat, lformat); + showjob(jp, 0, mode); jp->changed = 0; if (jp->state == JOBDONE) { freejob(jp); @@ -992,7 +998,7 @@ dowait(int block, struct job *job) out1str(" (core dumped)"); out1c('\n'); } else - showjob(thisjob, pid, 0, 0); + showjob(thisjob, pid, SHOWJOBS_DEFAULT); } } else { TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell, job)); diff --git a/bin/sh/jobs.h b/bin/sh/jobs.h index 54894e9..c75c353 100644 --- a/bin/sh/jobs.h +++ b/bin/sh/jobs.h @@ -74,6 +74,13 @@ struct job { #endif }; +enum { + SHOWJOBS_DEFAULT, /* job number, status, command */ + SHOWJOBS_VERBOSE, /* job number, PID, status, command */ + SHOWJOBS_PIDS, /* PID only */ + SHOWJOBS_PGIDS /* PID of the group leader only */ +}; + extern pid_t backgndpid; /* pid of last background process */ extern int job_warning; /* user was warned about stopped jobs */ extern int in_waitcmd; /* are we in waitcmd()? */ @@ -84,7 +91,7 @@ void setjobctl(int); int fgcmd(int, char **); int bgcmd(int, char **); int jobscmd(int, char **); -void showjobs(int, int, int); +void showjobs(int, int); int waitcmd(int, char **); int jobidcmd(int, char **); struct job *makejob(union node *, int); diff --git a/bin/sh/main.c b/bin/sh/main.c index a23efd0..e77ff4e 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -211,7 +211,7 @@ cmdloop(int top) inter = 0; if (iflag && top) { inter++; - showjobs(1, 0, 0); + showjobs(1, SHOWJOBS_DEFAULT); chkmail(0); flushout(&output); } diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index aebdb78..75d243c 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -32,7 +32,7 @@ .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" $FreeBSD$ .\" -.Dd July 29, 2006 +.Dd October 7, 2006 .Dt SH 1 .Os .Sh NAME @@ -1777,7 +1777,7 @@ Print the process id's of the processes in the specified If the .Ar job argument is omitted, use the current job. -.It Ic jobs Oo Fl ls Oc Op Ar job ... +.It Ic jobs Oo Fl lps Oc Op Ar job ... Print information about the specified jobs, or all jobs if no .Ar job argument is given. @@ -1787,8 +1787,13 @@ If the .Fl l option is specified, the PID of each job is also printed. If the +.Fl p +option is specified, only the process IDs for the process group leaders +are printed, one per line. +If the .Fl s -option is specified, only the PIDs of the jobs are printed, one per line. +option is specified, only the PIDs of the job commands are printed, one per +line. .It Ic local Oo Ar variable ... Oc Op Fl See the .Sx Functions -- cgit v1.1