mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-30 17:09:50 +02:00
fixes for bracket expressions in pathname expansion; changes for select/pselect; jobs builtin now removes terminated jobs from the jobs table after notifying
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+46
-9
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -729,7 +729,7 @@ rl_tty_set_echoing (int u)
|
||||
_rl_echoing_p = u;
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* Bogus Flow Control */
|
||||
|
||||
@@ -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);
|
||||
|
||||
+5
-1
@@ -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 *);
|
||||
|
||||
+3
-2
@@ -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.
|
||||
|
||||
@@ -33,9 +33,10 @@
|
||||
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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user