]> git.ipfire.org Git - thirdparty/bash.git/commitdiff
fixes for bracket expressions in pathname expansion; changes for select/pselect;...
authorChet Ramey <chet.ramey@case.edu>
Fri, 18 Nov 2022 16:01:00 +0000 (11:01 -0500)
committerChet Ramey <chet.ramey@case.edu>
Fri, 18 Nov 2022 16:01:00 +0000 (11:01 -0500)
12 files changed:
CWRU/CWRU.chlog
bashline.c
builtins/jobs.def
lib/glob/sm_loop.c
lib/readline/display.c
lib/readline/input.c
lib/readline/rltty.c
lib/sh/input_avail.c
lib/sh/timers.c
lib/sh/ufuncs.c
test.c
trap.c

index 12ce5edad4c7558d6f9d8d208b325cbba1a4c691..94ed6c46f7b3d627deee5c20017d29438cce0ad8 100644 (file)
@@ -4407,3 +4407,62 @@ parse.y
        - [grammar]: changed check to decrement WORD_TOP to >= 0 since we
          start at -1 and we want to decrement back to -1 when all loops are
          closed
+
+builtins/jobs.def
+       - jobs_builtin: call notify_and_cleanup after displaying the status of
+         jobs to implement POSIX requirement that `jobs' remove terminated
+         jobs from the jobs list
+         https://pubs.opengroup.org/onlinepubs/9699919799/utilities/jobs.html#tag_20_62
+
+                                  11/15
+                                  -----
+lib/sh/input_avail.c
+       - include signal.h unconditionally, we need it for HAVE_SELECT and
+         HAVE_PSELECT
+       - nchars_avail: make sure we declare and use readfds and exceptfds if
+         we have pselect or select available
+
+lib/readline/input.c
+       - rl_gather_tyi,rl_getc: need to declare and use readfds and exceptfds
+         if HAVE_PSELECT or HAVE_SELECT is set. Report from
+         Henry Bent <henry.r.bent@gmail.com>, fixes from
+         Koichi Murase <myoga.murase@gmail.com>
+
+                                  11/16
+                                  -----
+lib/sh/ufuncs.c
+       - quit.h: include unconditionally for declaration of sigemptyset even
+         if HAVE_SELECT is not defined
+
+lib/sh/timers.c
+       - USEC_PER_SEC: make sure it's defined even if HAVE_SELECT is not
+
+lib/glob/sm_loop.c
+       - BRACKMATCH: if an equivalence class does not match, and the next
+         character following the class is a `]', treat that as the end of
+         the bracket expression.
+         Report and fix from Koichi Murase <myoga.murase@gmail.com>
+       - GMATCH: if the current character in the string is a `/' and the
+         current element in the pattern is a bracket expresion, and the FLAGS
+         include FNM_PATHNAME, return FNM_NOMATCH immediately. A bracket
+         expression can never match a slash.
+         Report and fix from Koichi Murase <myoga.murase@gmail.com>
+       - BRACKMATCH: if we encounter a <slash> in a bracket expression, either
+         individually or as part of an equivalence class, nullify the bracket
+         expression and force the `[' to be matched as an ordinary
+         character
+
+                                  11/17
+                                  -----
+lib/glob/sm_loop.c
+       - BRACKMATCH: if a slash character appears as the first character
+         after a non-matching character class or equivalence class, treat
+         the bracket as an ordinary character that must be matched literally
+       - BRACKMATCH: if a slash character appears as the second character
+         of a range expression, treat the bracket as an ordinary character
+       - BRACKMATCH: if a slash character appears in the portion of a
+         bracket expression that already matched, treat the bracket as an
+         ordinary character
+         Updates from Koichi Murase <myoga.murase@gmail.com>
+       - BRACKMATCH: if a range expression is incomplete (no end char),
+         treat the bracket as an ordinary character
index 2eaeb72a0246785ffeb4d01982804541f114f5eb..5660283c9dad87e043c1c5a87e1a3596a2251152 100644 (file)
@@ -1877,7 +1877,13 @@ bash_default_completion (text, start, end, qc, compflags)
              rl_completion_suppress_append = 1;
              rl_filename_completion_desired = 0;
            }
+#if 0
+         /* TAG:bash-5.3 jidanni@jidanni.org 11/11/2022 */
+         else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) &&
+                  matches[2] && STREQ (matches[1], matches[2]) && CMD_IS_DIR (matches[0]))
+#else
          else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) && CMD_IS_DIR (matches[0]))
+#endif
            /* There are multiple instances of the same match (duplicate
               completions haven't yet been removed).  In this case, all of
               the matches will be the same, and the duplicate removal code
index 1ce098d08be2b1a72b1f89284bcad48021778df0..e2f2ff797b1b43050288062c82138288b1054a62 100644 (file)
@@ -136,6 +136,9 @@ jobs_builtin (list)
        {
        case JSTATE_ANY:
          list_all_jobs (form);
+         /* POSIX says to remove terminated jobs from the list after the jobs
+            builtin reports their status. */
+         notify_and_cleanup ();        /* the notify part will be a no-op */
          break;
        case JSTATE_RUNNING:
          list_running_jobs (form);
@@ -163,6 +166,10 @@ jobs_builtin (list)
       UNBLOCK_CHILD (oset);
       list = list->next;
     }
+  /* POSIX says to remove terminated jobs from the list after the jobs
+     builtin reports their status. */
+  notify_and_cleanup ();
+
   return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS);
 }
 
index 592a78db73199ff48c1d51e6b96fef2c39451abd..fa350daa893b6bf91670ee1a41a7d9a414a9bc89 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-2021 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2022 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
    
@@ -343,6 +343,11 @@ fprintf(stderr, "gmatch: pattern = %s; pe = %s\n", pattern, pe);
                (n == string || ((flags & FNM_PATHNAME) && n[-1] == L('/'))))
              return (FNM_NOMATCH);
 
+           /* If we are matching pathnames, we can't match a slash with a
+              bracket expression. */
+           if (sc == L('/') && (flags & FNM_PATHNAME))
+             return (FNM_NOMATCH);
+
            /* `?' cannot match `.' or `..' if it is the first character of the
               string or if it is the first character following a slash and
               we are matching a pathname. */
@@ -403,6 +408,8 @@ PARSE_COLLSYM (p, vp)
    return (p + pc + 2);
 }
 
+#define SLASH_PATHNAME(c)      (c == L('/') && (flags & FNM_PATHNAME))
+
 /* Use prototype definition here because of type promotion. */
 static CHAR *
 #if defined (PROTOTYPES)
@@ -451,6 +458,12 @@ BRACKMATCH (p, test, flags)
        {
          pc = FOLD (p[1]);
          p += 4;
+
+         /* Finding a slash in a bracket expression means you have to
+            match the bracket as an ordinary character (see below). */
+         if (pc == L('/') && (flags & FNM_PATHNAME))
+           return ((test == L('[')) ? savep : (CHAR *)0); /*]*/
+
          if (COLLEQUIV (test, pc))
            {
 /*[*/        /* Move past the closing `]', since the first thing we do at
@@ -463,6 +476,10 @@ BRACKMATCH (p, test, flags)
              c = *p++;
              if (c == L('\0'))
                return ((test == L('[')) ? savep : (CHAR *)0); /*]*/
+             else if (c == L('/') && (flags & FNM_PATHNAME))
+               return ((test == L('[')) ? savep : (CHAR *)0); /*]*/
+             else if (c == L(']'))
+               break;
              c = FOLD (c);
              continue;
            }
@@ -475,11 +492,11 @@ BRACKMATCH (p, test, flags)
 
          pc = 0;       /* make sure invalid char classes don't match. */
          /* Find end of character class name */
-         for (close = p + 1; *close != '\0'; close++)
+         for (close = p + 1; *close != '\0' && SLASH_PATHNAME(*close) == 0; close++)
            if (*close == L(':') && *(close+1) == L(']'))
              break;
 
-         if (*close != L('\0'))
+         if (*close != L('\0') && SLASH_PATHNAME(*close) == 0)
            {
              ccname = (CHAR *)malloc ((close - p) * sizeof (CHAR));
              if (ccname == 0)
@@ -526,6 +543,8 @@ BRACKMATCH (p, test, flags)
              c = *p++;
              if (c == L('\0'))
                return ((test == L('[')) ? savep : (CHAR *)0);
+             else if (c == L('/') && (flags & FNM_PATHNAME))
+               return ((test == L('[')) ? savep : (CHAR *)0); /*]*/
              else if (c == L(']'))
                break;
              c = FOLD (c);
@@ -565,15 +584,23 @@ BRACKMATCH (p, test, flags)
       if (c == L('\0'))
        return ((test == L('[')) ? savep : (CHAR *)0);
 
+      /* POSIX.2 2.13.3 says: `If a <slash> character is found following an
+         unescaped <left-square-bracket> character before a corresponding
+         <right-square-bracket> is found, the open bracket shall be treated
+         as an ordinary character.' If we find a slash in a bracket
+         expression and the flags indicate we're supposed to be treating the
+         string like a pathname, we have to treat the `[' as just a character
+         to be matched. */
+      if (c == L('/') && (flags & FNM_PATHNAME))
+       return ((test == L('[')) ? savep : (CHAR *)0);
+
       c = *p++;
       c = FOLD (c);
 
       if (c == L('\0'))
        return ((test == L('[')) ? savep : (CHAR *)0);
-
-      if ((flags & FNM_PATHNAME) && c == L('/'))
-       /* [/] can never match when matching a pathname.  */
-       return (CHAR *)0;
+      else if (c == L('/') && (flags & FNM_PATHNAME))
+       return ((test == L('[')) ? savep : (CHAR *)0);
 
       /* This introduces a range, unless the `-' is the last
         character of the class.  Find the end of the range
@@ -584,7 +611,9 @@ BRACKMATCH (p, test, flags)
          if (!(flags & FNM_NOESCAPE) && cend == L('\\'))
            cend = *p++;
          if (cend == L('\0'))
-           return (CHAR *)0;
+           return ((test == L('[')) ? savep : (CHAR *)0);
+         else if (cend == L('/') && (flags & FNM_PATHNAME))
+           return ((test == L('[')) ? savep : (CHAR *)0);
          if (cend == L('[') && *p == L('.'))
            {
              p = PARSE_COLLSYM (p, &pc);
@@ -636,6 +665,8 @@ matched:
       /* A `[' without a matching `]' is just another character to match. */
       if (c == L('\0'))
        return ((test == L('[')) ? savep : (CHAR *)0);
+      else if (c == L('/') && (flags & FNM_PATHNAME))
+       return ((test == L('[')) ? savep : (CHAR *)0);
 
       oc = c;
       c = *p++;
@@ -643,7 +674,10 @@ matched:
        {
          brcnt++;
          brchrp = p++;         /* skip over the char after the left bracket */
-         if ((c = *p) == L('\0'))
+         c = *p;
+         if (c == L('\0'))
+           return ((test == L('[')) ? savep : (CHAR *)0);
+         else if (c == L('/') && (flags & FNM_PATHNAME))
            return ((test == L('[')) ? savep : (CHAR *)0);
          /* If *brchrp == ':' we should check that the rest of the characters
             form a valid character class name. We don't do that yet, but we
@@ -666,6 +700,9 @@ matched:
        {
          if (*p == '\0')
            return (CHAR *)0;
+         /* We don't allow backslash to quote slash if we're matching pathnames */
+         else if (*p == L('/') && (flags & FNM_PATHNAME))
+           return ((test == L('[')) ? savep : (CHAR *)0);
          /* XXX 1003.2d11 is unclear if this is right. */
          ++p;
        }
index 09ecd86459836bcaad52ae5a9547074d73cbd976..d77cc6836003c886a29d389459f1f8ec1685f3ce 100644 (file)
@@ -616,10 +616,8 @@ rl_expand_prompt (char *prompt)
   prompt_visible_length = prompt_physical_chars = 0;
 
   if (local_prompt_invis_chars == 0)
-    {
-      local_prompt_invis_chars = (int *)xmalloc (sizeof (int));
-      local_prompt_invis_chars[0] = 0;
-    }
+    local_prompt_invis_chars = (int *)xmalloc (sizeof (int));
+  local_prompt_invis_chars[0] = 0;
 
   if (prompt == 0 || *prompt == 0)
     return (0);
index da4da45525f4ab80615dcb277b07dc3ff97cd661..9118fed3d6458f782f5fe5fcb3f10aba1e951f7b 100644 (file)
@@ -1,6 +1,6 @@
 /* input.c -- character input functions for readline. */
 
-/* Copyright (C) 1994-2021 Free Software Foundation, Inc.
+/* Copyright (C) 1994-2022 Free Software Foundation, Inc.
 
    This file is part of the GNU Readline Library (Readline), a library
    for reading lines of text with interactive input and history editing.      
@@ -250,7 +250,7 @@ rl_gather_tyi (void)
   register int tem, result;
   int chars_avail, k;
   char input;
-#if defined(HAVE_SELECT)
+#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
   fd_set readfds, exceptfds;
   struct timeval timeout;
 #endif
@@ -807,7 +807,7 @@ rl_getc (FILE *stream)
   int result;
   unsigned char c;
   int fd;
-#if defined (HAVE_PSELECT)
+#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
   sigset_t empty_set;
   fd_set readfds;
 #endif
index 882a3d46b1347f24471c0ccb5708ff7fb662f776..d9b0cd1c1dbf454cc9707404bfb58cfcb8da706b 100644 (file)
@@ -729,7 +729,7 @@ rl_tty_set_echoing (int u)
   _rl_echoing_p = u;
   return o;
 }
-\f
+
 /* **************************************************************** */
 /*                                                                 */
 /*                     Bogus Flow Control                          */
index 2ac446165fb008402e533f105f0b557544ad8b9b..262bc7490c880371d332648d33a7184aa1f28fea 100644 (file)
@@ -1,7 +1,7 @@
 /* input_avail.c -- check whether or not data is available for reading on a
                    specified file descriptor. */
 
-/* Copyright (C) 2008,2009-2019 Free Software Foundation, Inc.
+/* Copyright (C) 2008,2009-2019,2022 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -33,9 +33,7 @@
 #  include <sys/file.h>
 #endif /* HAVE_SYS_FILE_H */
 
-#if defined (HAVE_PSELECT)
-#  include <signal.h>
-#endif
+#include <signal.h>
 
 #if defined (HAVE_UNISTD_H)
 #  include <unistd.h>
@@ -107,10 +105,8 @@ nchars_avail (fd, nchars)
      int nchars;
 {
   int result, chars_avail;
-#if defined(HAVE_SELECT)
-  fd_set readfds, exceptfds;
-#endif
 #if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
+  fd_set readfds, exceptfds;
   sigset_t set, oset;
 #endif
 
@@ -121,7 +117,7 @@ nchars_avail (fd, nchars)
 
   chars_avail = 0;
 
-#if defined (HAVE_SELECT)
+#if defined (HAVE_PSELECT) || defined (HAVE_SELECT)
   FD_ZERO (&readfds);
   FD_ZERO (&exceptfds);
   FD_SET (fd, &readfds);
index 69b754c9734b2bda600c3eb52c5950190fdbac0c..f04af8bdc66d5a95ed3bc776056dcbdee6b1a519 100644 (file)
@@ -1,6 +1,6 @@
 /* timers - functions to manage shell timers */
 
-/* Copyright (C) 2021 Free Software Foundation, Inc.
+/* Copyright (C) 2021,2022 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
@@ -47,6 +47,10 @@ extern int errno;
 #define FREE(s)  do { if (s) free (s); } while (0)
 #endif
 
+#ifndef USEC_PER_SEC
+#  define USEC_PER_SEC 1000000
+#endif
+
 extern unsigned int falarm (unsigned int, unsigned int);
 
 static void shtimer_zero (sh_timer *);
index 4dc4853b10e4392f7f1dd2c39e5339ad16f71330..03243918aa927b103da52dbf49099d15b2a5ff00 100644 (file)
@@ -1,6 +1,6 @@
 /* ufuncs - sleep and alarm functions that understand fractional values */
 
-/* Copyright (C) 2008,2009-2020 Free Software Foundation, Inc.
+/* Copyright (C) 2008,2009-2020,2022 Free Software Foundation, Inc.
 
    This file is part of GNU Bash, the Bourne Again SHell.
 
 extern int errno;
 #endif /* !errno */
 
+#include "quit.h"
+
 #if defined (HAVE_SELECT)
 #  include "posixselect.h"
-#  include "quit.h"
 #  include "trap.h"
 #  include "stat-time.h"
 #endif
diff --git a/test.c b/test.c
index 6e016e362418196190ca3a3a63bd1a40d2742931..fadc33d2aa05ab52315c95badfd6d9fefefc601a 100644 (file)
--- a/test.c
+++ b/test.c
@@ -397,7 +397,7 @@ binary_test (op, arg1, arg2, flags)
   else if ((op[0] == '>' || op[0] == '<') && op[1] == '\0')
     {
 #if defined (HAVE_STRCOLL)
-      if (shell_compatibility_level > 40 && flags & TEST_LOCALE)
+      if (shell_compatibility_level > 40 && (flags & TEST_LOCALE))
        return ((op[0] == '>') ? (strcoll (arg1, arg2) > 0) : (strcoll (arg1, arg2) < 0));
       else
 #endif
@@ -450,7 +450,11 @@ binary_operator ()
       ((w[0] == '>' || w[0] == '<') && w[1] == '\0') ||                /* <, > */
       (w[0] == '!' && w[1] == '=' && w[2] == '\0'))            /* != */
     {
+#if 0  /* TAG: bash-5.3 POSIX interp 375 11/9/2022 */
+      value = binary_test (w, argv[pos], argv[pos + 2], (posixly_correct ? TEST_LOCALE : 0));
+#else
       value = binary_test (w, argv[pos], argv[pos + 2], 0);
+#endif
       pos += 3;
       return (value);
     }
diff --git a/trap.c b/trap.c
index 9cedf7ebb35f5e0db8f526c0001ca27f8c4cbff6..8d94dcd3a81ffa15f80b533b6bb1f4e85ef4e9fe 100644 (file)
--- a/trap.c
+++ b/trap.c
@@ -308,6 +308,7 @@ run_pending_traps ()
   sh_parser_state_t pstate;
   volatile int save_return_catch_flag, function_code;
   procenv_t save_return_catch;
+  char *trap_command, *old_trap;
 #if defined (ARRAY_VARS)
   ARRAY *ps;
 #endif
@@ -425,6 +426,10 @@ run_pending_traps ()
            }
          else
            {
+             /* XXX - why not set SIG_INPROGRESS, clear SIG_CHANGED here? */
+             old_trap = trap_list[sig];
+             trap_command = savestring (old_trap);
+
              save_parser_state (&pstate);
              save_subst_varlist = subst_assign_varlist;
              subst_assign_varlist = 0;
@@ -447,7 +452,8 @@ run_pending_traps ()
                }
 
              if (function_code == 0)
-               x = parse_and_execute (savestring (trap_list[sig]), "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
+               /* XXX is x always last_command_exit_value? */
+               x = parse_and_execute (trap_command, "trap", SEVAL_NONINT|SEVAL_NOHIST|SEVAL_RESETLINE);
              else
                {
                  parse_and_execute_cleanup (sig + 1);  /* XXX - could use -1 */
@@ -1068,7 +1074,7 @@ _run_trap_internal (sig, tag)
 
   old_modes = old_running = old_context = -1;
 
-  trap_exit_value = function_code = 0;
+  trap_exit_value = 0;
   trap_saved_exit_value = last_command_exit_value;
   /* Run the trap only if SIG is trapped and not ignored, and we are not
      currently executing in the trap handler. */
@@ -1112,7 +1118,11 @@ _run_trap_internal (sig, tag)
        save_pipeline (1);      /* XXX only provides one save level */
 #endif
 
+      /* XXX - set pending_traps[sig] = 0 here? */
+      evalnest++;
+
       /* If we're in a function, make sure return longjmps come here, too. */
+      function_code = 0;
       save_return_catch_flag = return_catch_flag;
       if (return_catch_flag)
        {
@@ -1123,7 +1133,6 @@ _run_trap_internal (sig, tag)
       flags = SEVAL_NONINT|SEVAL_NOHIST;
       if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
        flags |= SEVAL_RESETLINE;
-      evalnest++;
       if (function_code == 0)
         {
          parse_and_execute (trap_command, tag, flags);