Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/bin/sh Add options to the builtin jobid command to allow dis...



details:   https://anonhg.NetBSD.org/src/rev/0d659f6aeb53
branches:  trunk
changeset: 357060:0d659f6aeb53
user:      kre <kre%NetBSD.org@localhost>
date:      Wed Oct 25 05:42:56 2017 +0000

description:
Add options to the builtin jobid command to allow discovering the
process group (-g), the process leader pid (-p) ($! if the job was &'d)
and the job identifier (-j) (the %n that refers to the job) in addition to
(default) the list of all pids in the job (which it has always done).
No change to the (single) "job" arg, which is a specifier of the job:
the process leader pid, or one of the % forms, and defaults to %% (aka %+).
(This is all now documented in sh(1))

Also document the jobs command properly (no change to the command, just
document what it actually is.)

And while here, a whole new section in sh(1) "Job Control".  It probably
needs better wording, but this is (perhaps) better than the nothing that
was there before.

diffstat:

 bin/sh/jobs.c |   46 ++++++++++-
 bin/sh/sh.1   |  235 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 272 insertions(+), 9 deletions(-)

diffs (truncated from 363 to 300 lines):

diff -r 0a78104fca5a -r 0d659f6aeb53 bin/sh/jobs.c
--- a/bin/sh/jobs.c     Wed Oct 25 04:45:41 2017 +0000
+++ b/bin/sh/jobs.c     Wed Oct 25 05:42:56 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: jobs.c,v 1.91 2017/10/23 10:52:07 kre Exp $    */
+/*     $NetBSD: jobs.c,v 1.92 2017/10/25 05:42:56 kre Exp $    */
 
 /*-
  * Copyright (c) 1991, 1993
@@ -37,7 +37,7 @@
 #if 0
 static char sccsid[] = "@(#)jobs.c     8.5 (Berkeley) 5/4/95";
 #else
-__RCSID("$NetBSD: jobs.c,v 1.91 2017/10/23 10:52:07 kre Exp $");
+__RCSID("$NetBSD: jobs.c,v 1.92 2017/10/25 05:42:56 kre Exp $");
 #endif
 #endif /* not lint */
 
@@ -384,6 +384,10 @@
                error("Cannot continue job (%s)", strerror(errno));
        for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
                if (WIFSTOPPED(ps->status)) {
+                       VTRACE(DBG_JOBS, (
+                          "restartjob: [%jd] pid %d status change"
+                          " from %#x (stopped) to -1 (running)\n",
+                          (size_t)(jp-jobtab+1), ps->pid, ps->status));
                        ps->status = -1;
                        jp->state = JOBRUNNING;
                }
@@ -720,9 +724,43 @@
 {
        struct job *jp;
        int i;
+       int pg = 0, onep = 0, job = 0;
 
-       nextopt("");
+       while ((i = nextopt("gjp"))) {
+               switch (i) {
+               case 'g':       pg = 1;         break;
+               case 'j':       job = 1;        break;
+               case 'p':       onep = 1;       break;
+               }
+       }
+       CTRACE(DBG_JOBS, ("jobidcmd%s%s%s%s %s\n", pg ? " -g" : "",
+           onep ? " -p" : "", job ? " -j" : "", jobs_invalid ? " [inv]" : "",
+           *argptr ? *argptr : "<implicit %%>"));
+       if (pg + onep + job > 1)
+               error("-g -j and -p options cannot be combined");
+
+       if (argptr[0] && argptr[1])
+               error("usage: jobid [-g|-p|-r] jobid");
+
        jp = getjob(*argptr, 0);
+       if (job) {
+               out1fmt("%%%jd\n", (size_t)(jp - jobtab + 1));
+               return 0;
+       }
+       if (pg) {
+               if (jp->pgrp != 0) {
+                       out1fmt("%ld\n", (long)jp->pgrp);
+                       return 0;
+               }
+               return 1;
+       }
+       if (onep) {
+               i = jp->nprocs - 1;
+               if (i < 0)
+                       return 1;
+               out1fmt("%ld\n", (long)jp->ps[i].pid);
+               return 0;
+       }
        for (i = 0 ; i < jp->nprocs ; ) {
                out1fmt("%ld", (long)jp->ps[i].pid);
                out1c(++i < jp->nprocs ? ' ' : '\n');
@@ -873,6 +911,7 @@
        jp->used = 1;
        jp->changed = 0;
        jp->nprocs = 0;
+       jp->pgrp = 0;
 #if JOBS
        jp->jobctl = jobctl;
        set_curjob(jp, 1);
@@ -939,6 +978,7 @@
                        pgrp = pid;
                else
                        pgrp = jp->ps[0].pid;
+               jp->pgrp = pgrp;
                /* This can fail because we are doing it in the child also */
                (void)setpgid(pid, pgrp);
        }
diff -r 0a78104fca5a -r 0d659f6aeb53 bin/sh/sh.1
--- a/bin/sh/sh.1       Wed Oct 25 04:45:41 2017 +0000
+++ b/bin/sh/sh.1       Wed Oct 25 05:42:56 2017 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: sh.1,v 1.168 2017/10/15 12:01:43 pgoyette Exp $
+.\"    $NetBSD: sh.1,v 1.169 2017/10/25 05:42:56 kre Exp $
 .\" Copyright (c) 1991, 1993
 .\"    The Regents of the University of California.  All rights reserved.
 .\"
@@ -31,7 +31,7 @@
 .\"
 .\"    @(#)sh.1        8.6 (Berkeley) 5/4/95
 .\"
-.Dd October 6, 2017
+.Dd October 24, 2017
 .Dt SH 1
 .\" everything except c o and s (keep them ordered)
 .ds flags abCEeFfhIiLmnpquVvx
@@ -2433,14 +2433,91 @@
 .Va file
 to set key bindings as defined by
 .Xr editrc 5 .
-.It jobid Op Ar job
-Print the process id's of the processes in the job.
+.It jobid Oo Fl g Ns \&| Ns Fl j Ns \&| Ns Fl p Oc  Op Ar job
+With no flags, print the process identifiers of the processes in the job.
 If the
 .Ar job
 argument is omitted, the current job is used.
-.It jobs
-This command lists out all the background processes
+Any of the ways to select a job may be used for
+.Ar job ,
+including the
+.Sq \&%
+forms, or the process id of the job leader
+.Po
+.Dq \&$!
+if the job was created in the background.
+.Pc
+.Pp
+If one of the flags is given, then instead of the list of
+process identifiers, the
+.Ic jobid
+command prints:
+.Bl -dash -compact
+.It
+With
+.Fl g
+the process group, if one was created for this job,
+or nothing otherwise (the job is in the same process
+group as the shell.)
+.It
+With
+.Fl j
+the job identifier (using
+.Sq \&%n
+notation, where n is a number) is printed.
+.It
+With
+.Fl p
+only the process id of the process group leader is printed.
+.El
+These flags are mutually exclusive.
+.Pp
+.Ic jobid
+exits with status 2 if there is an argument error,
+status 1, if with
+.Fl g
+the job had no separate process group,
+or with
+.Fl p
+there is no process group leader (should not happen),
+and otherwise exits with status 0.
+.It jobs Oo Fl l Ns \&| Ns Fl p Oc Op job...
+Without job arguments,
+this command lists out all the background processes
 which are children of the current shell process.
+With job arguments, the listed jobs are shown instead.
+Without flags, the output contains the job
+identifier (see
+.Sx Job Control
+below), an indicator character if the job is the current or previous job,
+the current status of the job (running, suspended, or terminated successfully,
+unsuccessfully, or by a signal)
+and a (usually abbreviated) command string.
+.Pp
+With the
+.Fl l
+flag the output is in a longer form, with the process identifiers
+of each process (run from the top level, as in a pipeline), and the
+status of each process, rather than the job status.
+.Pp
+With the
+.Fl p
+flag, the output contains only the process identifier of the lead
+process.
+.Pp
+In an interactive shell, each job shown as completed in the output
+from the jobs command is implicitly waited for, and is removed from
+the jobs table, never to be seen again.
+In an interactive shell, when a background job terminates, the
+.Ic jobs
+command (with that job as an argument) is implicitly run just
+before outputting the next PS1 command prompt, after the job
+terminated.
+This indicates that the job finished, shows its status,
+and cleans up the job table entry for that job.
+Non-interactive shells need to execute
+.Ic wait
+commands to clean up terminated background jobs.
 .It local Oo Fl INx Oc Oo Ar variable | \- Oc ...
 Define local variables for a function.
 Local variables have their attributes, and values,
@@ -3043,6 +3120,150 @@
 knowledge of the child is removed from the system,
 and it cannot be waited upon again.
 .El
+.Ss Job Control
+Each process (or set of processes) started by
+.Nm
+is created as a
+.Dq job
+and added to the jobs table.
+When enabled by the
+.Fl m
+option
+.Pq aka Fl o Ar monitor
+when the job is created,
+.Nm
+places each job (if run from the top level shell)
+into a process group of its own, which allows control
+of the process(es), and its/their descendants, as a unit.
+When the
+.Fl m
+option is off, or when started from a sub-shell environment,
+jobs share the same process group as the parent shell.
+The
+.Fl m
+option is enabled by default in interactive shells with
+a terminal as standard input and standard error.
+.Pp
+Jobs with separate process groups may be stopped, and then later
+resumed in the foreground (with access to the terminal)
+or in the background (where attempting to read from the
+terminal will result in the job stopping.)
+A list of current jobs can be obtained using the
+.Ic jobs
+built-in command.
+Jobs are identified using either the process identifier
+of the lead process of the job (the value available in
+the special parameter
+.Sq \&$!
+if the job is started in the background), or using percent
+notation.
+Each job is given a
+.Dq job number
+which is a small integer, starting from 1, and can be
+referenced as
+.Sq \&%n
+where n is that number.
+Note that this applies to jobs both with and without their own process groups.
+Job numbers are shown in the output from the
+.Ic jobs
+command enclosed in brackets
+.Po
+.Sq \&[
+and
+.Sq \&]
+.Pc .
+Whenever the job table becomes empty, the numbers begin at one again.
+In addition, there is the concept of a current, and a previous job,
+identified by
+.Sq \&%+
+.Po
+or
+.Sq \&%%
+or even just
+.Sq \&%
+.Pc ,
+and a previous job, identified by
+.Sq \&%\- .
+Whenever a background job is started,
+or a job is resumed in the background,
+it becomes the current job.
+The job that was the current job
+(prepare for a big surprise here, drum roll..., wait for it...\&)
+becomes the previous job.
+When the current job terminates, the previous job is
+promoted to be the current job.
+In addition the form
+.Dq %string
+finds the job for which the command starts with
+.Dq string
+and the form
+.Dq %?string
+finds the job which contains the
+.Dq string
+in its command somewhere.
+Both forms require the result to be unambiguous.
+For this purpose the
+.Dq command
+is that shown in the output from the
+.Ic jobs
+command, not the original command line.
+.Pp
+The
+.Ic bg ,
+.Ic fg ,
+.Ic jobid ,



Home | Main Index | Thread Index | Old Index