]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
commit bash-20200408 snapshot
authorChet Ramey <chet.ramey@case.edu>
Fri, 10 Apr 2020 22:26:33 +0000 (18:26 -0400)
committerChet Ramey <chet.ramey@case.edu>
Fri, 10 Apr 2020 22:26:33 +0000 (18:26 -0400)
12 files changed:
CWRU/CWRU.chlog
bashline.c
builtins/wait.def
doc/bash.1
doc/bashref.texi
doc/version.texi
jobs.c
jobs.h
lib/readline/readline.c
tests/RUN-ONE-TEST
tests/jobs.right
tests/jobs5.sub

index 49067d9ef6f4d6e4fdf6fef2ebcba2aaf50d4689..025eeb2b7dc1f4f8748f27074853808ee2d8adef 100644 (file)
@@ -7921,3 +7921,30 @@ execute_cmd.c
        - execute_in_subshell,execute_simple_command,execute_disk_command:
          remove calls to CHECK_SIGTERM, since we don't install a handler
          any more
+
+lib/readline/readline.c
+       - _rl_enable_bracketed_paste: enabled by default for the time being
+
+                                   4/9
+                                   ---
+jobs.h
+       - JWAIT_WAITING: new flag for wait functions; means only wait for jobs
+         with the J_WAITING flag set
+       - J_WAITING: new job flag, part of arg list to `wait -n'
+       - IS_WAITING(i): job i has the J_WAITING flag set
+
+jobs.c
+       - wait_for_any_job: if the flags includes JWAIT_WAITING, we only return
+         jobs with the J_WAITING flag already set; otherwise we skip them.
+         For `wait -n args' support
+
+builtins/wait.def
+       - set_waitlist: take a list of jobspecs and set the J_WAITING flag in
+         each valid job from the list
+       - unset_waitlist: turn off the J_WAITING flag for all jobs where it's
+         set
+       - wait_builtin: if -n is supplied with a list of arguments, set the
+         J_WAITING flag in each job in the list, call wait_for_any_job with
+         the JWAIT_WAITING flag, and clean up by calling unset_waitlist().
+         From a suggestion from Robert Elz <kre@munnari.oz.au> back in 3/2019
+         (originally in 10/2017)
index e089d1b8588255914e06f6e4b26e86eacacbe7b9..cd36b0be516396fdfa016540bf3475e22e458be3 100644 (file)
@@ -4161,7 +4161,7 @@ set_filename_bstab (string)
 
   memset (filename_bstab, 0, sizeof (filename_bstab));
   for (s = string; s && *s; s++)
-    filename_bstab[*s] = 1;
+    filename_bstab[(unsigned char)*s] = 1;
 }
 
 /* Quote a filename using double quotes, single quotes, or backslashes
index 90d7eece69189283326788ca62d660893a2f1d60..12260737a95174bce196192e0f210cdd8e40149e 100644 (file)
@@ -1,7 +1,7 @@
 This file is wait.def, from which is created wait.c.
 It implements the builtin "wait" in Bash.
 
-Copyright (C) 1987-2019 Free Software Foundation, Inc.
+Copyright (C) 1987-2020 Free Software Foundation, Inc.
 
 This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -31,8 +31,9 @@ given, waits for all currently active child processes, and the return
 status is zero.  If ID is a job specification, waits for all processes
 in that job's pipeline.
 
-If the -n option is supplied, waits for the next job to terminate and
-returns its exit status.
+If the -n option is supplied, waits for a single job from the list of IDs,
+or, if no IDs are supplied, for the next job to complete and returns its
+exit status.
 
 If the -p option is supplied, the process or job identifier of the job
 for which the exit status is returned is assigned to the variable VAR
@@ -44,7 +45,8 @@ specified ID to terminate, instead of waiting for it to change status.
 
 Exit Status:
 Returns the status of the last ID; fails if ID is invalid or an invalid
-option is given.
+option is given, or if -n is supplied and the shell has no unwaited-for
+children.
 $END
 
 $BUILTIN wait
@@ -79,6 +81,7 @@ $END
 #include "../execute_cmd.h"
 #include "../jobs.h"
 #include "../trap.h"
+#include "../sig.h"
 #include "common.h"
 #include "bashgetopt.h"
 
@@ -87,6 +90,9 @@ extern int wait_signal_received;
 procenv_t wait_intr_buf;
 int wait_intr_flag;
 
+static int set_waitlist PARAMS((WORD_LIST *));
+static void unset_waitlist PARAMS((void));
+
 /* Wait for the pid in LIST to stop or die.  If no arguments are given, then
    wait for all of the active background processes of the shell and return
    0.  If a list of pids or job specs are given, return the exit status of
@@ -198,11 +204,22 @@ wait_builtin (list)
 #if defined (JOB_CONTROL)
   if (nflag)
     {
+      if (list)
+       {
+         opt = set_waitlist (list);
+         if (opt == 0)
+           WAIT_RETURN (127);
+         wflags |= JWAIT_WAITING;
+       }
+
       status = wait_for_any_job (wflags, &pstat);
       if (status < 0)
        status = 127;
+
       if (vname && status >= 0)
        bind_var_to_int (vname, pstat.pid);
+      if (list)
+       unset_waitlist ();
       WAIT_RETURN (status);
     }
 #endif
@@ -291,3 +308,57 @@ wait_builtin (list)
 
   WAIT_RETURN (status);
 }
+
+#if defined (JOB_CONTROL)
+/* Take each valid pid or jobspec in LIST and mark the corresponding job as
+   J_WAITING, so wait -n knows which jobs to wait for. Return the number of
+   jobs we found. */
+static int
+set_waitlist (list)
+     WORD_LIST *list;
+{
+  sigset_t set, oset;
+  int job, r, njob;
+  intmax_t pid;
+  WORD_LIST *l;
+
+  BLOCK_CHILD (set, oset);
+  njob = 0;
+  for (l = list; l; l = l->next)
+    {
+      job = NO_JOB;
+      job = (l && legal_number (l->word->word, &pid) && pid == (pid_t) pid)
+               ? get_job_by_pid ((pid_t) pid, 0, 0)
+               : get_job_spec (l);
+      if (job == NO_JOB || jobs == 0 || INVALID_JOB (job))
+       {
+         sh_badjob (l->word->word);
+         continue;
+       }
+      /* We don't check yet to see if one of the desired jobs has already
+        terminated, but we could. We wait until wait_for_any_job(). This
+        has the advantage of validating all the arguments. */
+      if ((jobs[job]->flags & J_WAITING) == 0)
+       {
+         njob++;
+         jobs[job]->flags |= J_WAITING;
+       }
+    }
+  UNBLOCK_CHILD (oset);
+  return (njob);
+}
+
+/* Clean up after a call to wait -n jobs */
+static void
+unset_waitlist ()
+{
+  int i;
+  sigset_t set, oset;
+
+  BLOCK_CHILD (set, oset);
+  for (i = 0; i < js.j_jobslots; i++)
+    if (jobs[i] && (jobs[i]->flags & J_WAITING))
+      jobs[i]->flags &= ~J_WAITING;
+  UNBLOCK_CHILD (oset);
+}
+#endif
index b573ffd50ee782e47714048ad47bbc49bfcc18ad..a2b659b55441a53f33a4080f65dc0b9111daf3b2 100644 (file)
@@ -5,12 +5,12 @@
 .\"    Case Western Reserve University
 .\"    chet.ramey@case.edu
 .\"
-.\"    Last Change: Tue Mar 24 16:38:43 EDT 2020
+.\"    Last Change: Thu Apr  9 11:50:30 EDT 2020
 .\"
 .\" bash_builtins, strip all but Built-Ins section
 .if \n(zZ=1 .ig zZ
 .if \n(zY=1 .ig zY
-.TH BASH 1 "2020 March 24" "GNU Bash 5.0"
+.TH BASH 1 "2020 April 9" "GNU Bash 5.0"
 .\"
 .\" There's some problem with having a `@'
 .\" in a tagged paragraph with the BSD man macros.
@@ -10863,8 +10863,13 @@ is not given,
 the last-executed process substitution, if its process id is the same as
 \fB$!\fP,
 and the return status is zero.
-If the \fB\-n\fP option is supplied, \fBwait\fP waits for a single job
-to terminate and returns its exit status.
+If the \fB\-n\fP option is supplied,
+\fBwait\fP waits for a single job
+from the list of \fIid\fPs or, if no \fIid\fPs are supplied, any job,
+to complete and returns its exit status.
+If none of the supplied arguments is a child of the shell, or if no arguments
+are supplied and the shell has no unwaited-for children, the exit status
+is 127.
 If the \fB\-p\fP option is supplied, the process or job identifier of the job
 for which the exit status is returned is assigned to the variable
 \fIvarname\fP named by the option argument.
index 3590350e8ff7bb979ec4cb38279968734d42214f..4a57871a8fca1e2dc3891a614fa78fd6dc023557 100644 (file)
@@ -8227,7 +8227,12 @@ the last-executed process substitution, if its process id is the same as
 @var{$!},
 and the return status is zero.
 If the @option{-n} option is supplied, @code{wait} waits for a single job
-to terminate and returns its exit status.
+from the list of @var{pids} or @var{jobspecs} or, if no arguments are
+supplied, any job, 
+to complete and returns its exit status.
+If none of the supplied arguments is a child of the shell, or if no arguments
+are supplied and the shell has no unwaited-for children, the exit status
+is 127.
 If the @option{-p} option is supplied, the process or job identifier of the job
 for which the exit status is returned is assigned to the variable
 @var{varname} named by the option argument.
index c50a14be49a068caef2128877d94b5d7e196d4b9..3098b9c7428d88cd77c2ee9def8f90f2f486d6c0 100644 (file)
@@ -2,10 +2,10 @@
 Copyright (C) 1988-2020 Free Software Foundation, Inc.
 @end ignore
 
-@set LASTCHANGE Tue Mar 24 16:38:56 EDT 2020
+@set LASTCHANGE Thu Apr  9 11:58:06 EDT 2020
 
 @set EDITION 5.0
 @set VERSION 5.0
 
-@set UPDATED 24 March 2020
-@set UPDATED-MONTH March 2020
+@set UPDATED 9 April 2020
+@set UPDATED-MONTH April 2020
diff --git a/jobs.c b/jobs.c
index 6bc5f2ae740ac4f3c39895da9908787f76d57cea..516239e36572c27990eaee8417d829d6a8069974 100644 (file)
--- a/jobs.c
+++ b/jobs.c
@@ -3286,6 +3286,8 @@ wait_for_any_job (flags, ps)
   BLOCK_CHILD (set, oset);
   for (i = 0; i < js.j_jobslots; i++)
     {
+      if ((flags & JWAIT_WAITING) && jobs[i] && IS_WAITING (i) == 0)
+       continue;               /* if we don't want it, skip it */
       if (jobs[i] && DEADJOB (i) && IS_NOTIFIED (i) == 0)
        {
 return_job:
@@ -3336,8 +3338,12 @@ return_job:
       /* Now we see if we have any dead jobs and return the first one */
       BLOCK_CHILD (set, oset);
       for (i = 0; i < js.j_jobslots; i++)
-       if (jobs[i] && DEADJOB (i))
-         goto return_job;
+       {
+         if ((flags & JWAIT_WAITING) && jobs[i] && IS_WAITING (i) == 0)
+           continue;           /* if we don't want it, skip it */
+         if (jobs[i] && DEADJOB (i))
+           goto return_job;
+       }
       UNBLOCK_CHILD (oset);
     }
 
diff --git a/jobs.h b/jobs.h
index 37f4389c575f1c41c4811dea705271e2d15c9ea1..945fe3da96a86809441224a678aff25f18f900aa 100644 (file)
--- a/jobs.h
+++ b/jobs.h
@@ -42,6 +42,7 @@
 #define JWAIT_PERROR           0x01
 #define JWAIT_FORCE            0x02 
 #define JWAIT_NOWAIT           0x04    /* don't waitpid(), just return status if already exited */
+#define JWAIT_WAITING          0x08    /* wait for jobs marked J_WAITING only */
 
 /* The max time to sleep while retrying fork() on EAGAIN failure */
 #define FORKSLEEP_MAX  16
@@ -105,11 +106,13 @@ typedef enum { JNONE = -1, JRUNNING = 1, JSTOPPED = 2, JDEAD = 4, JMIXED = 8 } J
 #define J_STATSAVED  0x10 /* A process in this job had status saved via $! */
 #define J_ASYNC             0x20 /* Job was started asynchronously */
 #define J_PIPEFAIL   0x40 /* pipefail set when job was started */
+#define J_WAITING    0x80 /* one of a list of jobs for which we are waiting */
 
 #define IS_FOREGROUND(j)       ((jobs[j]->flags & J_FOREGROUND) != 0)
 #define IS_NOTIFIED(j)         ((jobs[j]->flags & J_NOTIFIED) != 0)
 #define IS_JOBCONTROL(j)       ((jobs[j]->flags & J_JOBCONTROL) != 0)
 #define IS_ASYNC(j)            ((jobs[j]->flags & J_ASYNC) != 0)
+#define IS_WAITING(j)          ((jobs[j]->flags & J_WAITING) != 0)
 
 typedef struct job {
   char *wd;       /* The working directory at time of invocation. */
index 9f9929f7af413a3dbfebdf9a3047a45fba17ec9d..c4675bd7339ded0c8ff72aa5e11a9d53331d88d5 100644 (file)
@@ -1375,9 +1375,12 @@ bind_bracketed_paste_prefix (void)
 
   _rl_keymap = emacs_standard_keymap;
   rl_bind_keyseq_if_unbound (BRACK_PASTE_PREF, rl_bracketed_paste_begin);
-  
+
+#if defined (VI_MODE)
   _rl_keymap = vi_insertion_keymap;
   rl_bind_keyseq_if_unbound (BRACK_PASTE_PREF, rl_bracketed_paste_begin);
+  /* XXX - is there a reason to do this in the vi command keymap? */
+#endif
 
   _rl_keymap = xkeymap;
 }
index 0b06381072414283266cf5d055a42ac14b9b6da6..c8bef8dd12533217b1b65fc20d00f3d1cc1b81e7 100755 (executable)
@@ -1,4 +1,4 @@
-BUILD_DIR=/usr/local/build/chet/bash/bash-current
+BUILD_DIR=/usr/local/build/bash/bash-current
 THIS_SH=$BUILD_DIR/bash
 PATH=$PATH:$BUILD_DIR
 
index 01b267d2f9e9d57cad4c7f7500de13b94ce027df..283ca17439a0cbe91dae137d892cfafd54c3c68a 100644 (file)
@@ -27,6 +27,10 @@ i killed it
 12
 [1]-  Running                 sleep 20 &
 [3]+  Running                 sleep 20 &
+5: ok 1
+./jobs5.sub: line 40: wait: %8: no such job
+2: ok 2
+2: ok 3
 child1 exit status 0
 0
 ./jobs.tests: line 38: wait: %1: no such job
index 35d398167004dc64efa52423241ad4e588041b40..e6ffb44e6a945a3983256596e9e61dac31dc35eb 100644 (file)
@@ -1,12 +1,61 @@
+#   This program is free software: you can redistribute it and/or modify
+#   it under the terms of the GNU General Public License as published by
+#   the Free Software Foundation, either version 3 of the License, or
+#   (at your option) any later version.
+#
+#   This program is distributed in the hope that it will be useful,
+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#   GNU General Public License for more details.
+#
+#   You should have received a copy of the GNU General Public License
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
 # framework to test new `wait -n' option that waits for any job to finish
 
 set -m
 
 sleep 20 &
-{ sleep 5; exit 12; } &
+{ sleep 2; exit 12; } &
 sleep 20 &
 
 wait -n
 echo $?
 
 jobs
+disown -a
+
+{ sleep 1 ; exit 4; } &
+{ sleep 2 ; exit 5; } & bgpid1=$!
+{ sleep 4 ; exit 6; } &
+
+wait -p wvar -n %2 %3
+case "$wvar" in
+$bgpid1)       echo $?: ok 1;;
+*)             echo bad 1;;
+esac
+
+{ sleep 1 ; exit 2; } & bgpid2=$!
+wait -p wvar -n %8 $!
+case $wvar in
+$bgpid2)       echo $?: ok 2;;
+*)             echo bad 2;;
+esac
+
+disown -a
+
+{ sleep 3; exit 1; } & { sleep 1; exit 2; } & bgpid3=$!
+{ sleep 3; exit 3; } & { sleep 3; exit 4; } &
+
+wait -n -p wpid %1 %2 %3 %4
+
+case $wpid in
+$bgpid3)       echo $?: ok 3;;
+*)             echo bad 3 ;;
+esac
+
+disown -a
+
+unset bgpid1 bgpid2 bgpid3
+unset wpid