subst.c
- glob_expand_word_list: call shell_glob_filename with QGLOB_CTLESC
because quote removal hasn't been performed yet
+
+ 10/7
+ ----
+pathexp.c
+ - quote_string_for_globbing: if we have an unquoted backslash followed
+ by a CTLESC-quoted character (not CTLESC-CTLESC), just perform the
+ usual CTLESC-to-backslash conversion instead of skipping over it.
+ Fixes issue raised in austin-group discussion about globbing by
+ Geoff Clare <gwc@opengroup.org> (austin-group issue 1234), though
+ it's still inherently ambiguous
+
+ 10/8
+ ----
+include/shmbutil.h
+ - xwcsrtombs: extern declaration, to match other functions in that file
+
+lib/glob/glob.c
+ - wcdequote_pathname: new function, actual backslash quote removal code
+ from wdequote_pathname; wdequote_pathname calls it
+
+lib/glob/glob.c
+ - {udequote,wcdequote}_pathname: now public void functions
+
+lib/glob/smatch.c
+ - DEQUOTE_PATHNAME: defined appropriately to udequote_pathname or
+ wcdequote_pathname
+
+lib/glob/sm_loop.c
+ - DEQUOTE_PATHNAME: appropriate extern declaration
+ - BRACKMATCH: call DEQUOTE_PATHNAME to dequote a character class name
+ in a bracket expression. This is the result of a discussion on the
+ austin-group mailing list, from Geoff Clare <gwc@opengroup.org> and
+ Robert Elz <kre@bmunnari.oz.au>
+
+ 10/10
+ -----
+execute_cmd.[ch]
+ - async_redirect_stdin: now a global function
+
+subst.c
+ - process_substitute: call async_redirect_stdin in the child to keep
+ it from having stdin connected to the terminal, since it's not a
+ job control process
+
+ 10/11
+ -----
+subst.c
+ - process_substitute: in the child process, set interactive = 0, since
+ an asynchronous process substitution process is not interactive.
+ Seems to fix issue reported by Grisha Levit <grishalevit@gmail.com>
+
+lib/sh/shmatch.c
+ - sh_regmatch: implement a suggestion from Grisha Levit
+ <grishalevit@gmail.com> and don't allow nocaseglob to enable case-
+ insensitive regexp matching. It hasn't been documented that way
+ in years
static int restore_signal_mask PARAMS((sigset_t *));
#endif
-static void async_redirect_stdin PARAMS((void));
-
static int builtin_status PARAMS((int));
static int execute_for_command PARAMS((FOR_COM *));
}
#endif
-static void
+void
async_redirect_stdin ()
{
int fd;
extern int execute_command_internal __P((COMMAND *, int, int, int, struct fd_bitmap *));
extern int shell_execve __P((char *, char **, char **));
extern void setup_async_signals __P((void));
+extern void async_redirect_stdin __P((void));
extern void undo_partial_redirects __P((void));
extern void dispose_partial_redirects __P((void));
/* shmbutil.h -- utility functions for multibyte characters. */
-/* Copyright (C) 2002-2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002-2019 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
#if defined (HANDLE_MULTIBYTE)
#include "shmbchar.h"
-extern size_t xmbsrtowcs __P((wchar_t *, const char **, size_t, mbstate_t *));
-extern size_t xdupmbstowcs __P((wchar_t **, char ***, const char *));
+extern size_t xwcsrtombs PARAMS((char *, const wchar_t **, size_t, mbstate_t *));
+extern size_t xmbsrtowcs PARAMS((wchar_t *, const char **, size_t, mbstate_t *));
+extern size_t xdupmbstowcs PARAMS((wchar_t **, char ***, const char *));
-extern size_t mbstrlen __P((const char *));
+extern size_t mbstrlen PARAMS((const char *));
-extern char *xstrchr __P((const char *, int));
+extern char *xstrchr PARAMS((const char *, int));
extern int locale_mb_cur_max; /* XXX */
extern int locale_utf8locale; /* XXX */
#if HANDLE_MULTIBYTE
static int mbskipname __P((char *, char *, int));
#endif
+void udequote_pathname __P((char *));
#if HANDLE_MULTIBYTE
-static void udequote_pathname __P((char *));
+void wcdequote_pathname __P((wchar_t *));
static void wdequote_pathname __P((char *));
#else
# define dequote_pathname udequote_pathname
#endif /* HANDLE_MULTIBYTE */
/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
-static void
+void
udequote_pathname (pathname)
char *pathname;
{
#if HANDLE_MULTIBYTE
/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
+void
+wcdequote_pathname (wpathname)
+ wchar_t *wpathname;
+{
+ int i, j;
+
+ for (i = j = 0; wpathname && wpathname[i]; )
+ {
+ if (wpathname[i] == L'\\')
+ i++;
+
+ wpathname[j++] = wpathname[i++];
+
+ if (wpathname[i - 1] == L'\0')
+ break;
+ }
+ if (wpathname)
+ wpathname[j] = L'\0';
+}
+
static void
wdequote_pathname (pathname)
char *pathname;
}
orig_wpathname = wpathname;
- for (i = j = 0; wpathname && wpathname[i]; )
- {
- if (wpathname[i] == L'\\')
- i++;
-
- wpathname[j++] = wpathname[i++];
-
- if (wpathname[i - 1] == L'\0')
- break;
- }
- if (wpathname)
- wpathname[j] = L'\0';
+ wcdequote_pathname (wpathname);
/* Convert the wide character string into unibyte character set. */
memset (&ps, '\0', sizeof(mbstate_t));
a filename `DIR/PAT'. If there is, and we can access it, just make the
vector to return and bail immediately. */
hasglob = 0;
- if (skip == 0 && (hasglob = glob_pattern_p (pat)) == 0 || hasglob == 2)
+ if (skip == 0 && ((hasglob = glob_pattern_p (pat)) == 0 || hasglob == 2))
{
int dirlen;
struct stat finfo;
static CHAR *BRACKMATCH __P((CHAR *, U_CHAR, int));
static int EXTMATCH __P((INT, CHAR *, CHAR *, CHAR *, CHAR *, int));
+extern void DEQUOTE_PATHNAME __P((CHAR *));
+
/*static*/ CHAR *PATSCAN __P((CHAR *, CHAR *, INT));
int
{
bcopy (p + 1, ccname, (close - p - 1) * sizeof (CHAR));
*(ccname + (close - p - 1)) = L('\0');
+ /* As a result of a POSIX discussion, char class names are
+ allowed to be quoted (?) */
+ DEQUOTE_PATHNAME (ccname);
pc = IS_CCLASS (orig_test, (XCHAR *)ccname);
}
if (pc == -1)
#undef PATSCAN
#undef STRCOMPARE
#undef EXTMATCH
+#undef DEQUOTE_PATHNAME
#undef STRUCT
#undef BRACKMATCH
#undef STRCHR
#define PATSCAN glob_patscan
#define STRCOMPARE strcompare
#define EXTMATCH extmatch
+#define DEQUOTE_PATHNAME udequote_pathname
#define STRUCT smat_struct
#define STRCHR(S, C) strchr((S), (C))
#define MEMCHR(S, C, N) memchr((S), (C), (N))
#define PATSCAN glob_patscan_wc
#define STRCOMPARE wscompare
#define EXTMATCH extmatch_wc
+#define DEQUOTE_PATHNAME wcdequote_pathname
#define STRUCT wcsmat_struct
#define STRCHR(S, C) wcschr((S), (C))
#define MEMCHR(S, C, N) wmemchr((S), (C), (N))
#endif
rflags = REG_EXTENDED;
- if (glob_ignore_case || match_ignore_case)
+ if (match_ignore_case)
rflags |= REG_ICASE;
#if !defined (ARRAY_VARS)
rflags |= REG_NOSUB;
}
else if (pathname[i] == CTLESC)
{
+convert_to_backslash:
if ((qflags & QGLOB_FILENAME) && pathname[i+1] == '/')
continue;
/* What to do if preceding char is backslash? */
even when the first CTLESC is preceded by a backslash. */
if ((qflags & QGLOB_CTLESC) && pathname[i] == CTLESC && (pathname[i+1] == CTLESC || pathname[i+1] == CTLNUL))
i++; /* skip over the CTLESC */
+ else if ((qflags & QGLOB_CTLESC) && pathname[i] == CTLESC)
+ /* A little more general: if there is an unquoted backslash in the
+ pattern and we are handling quoted characters in the pattern,
+ convert the CTLESC to backslash and add the next character on
+ the theory that the backslash will quote the next character
+ but it would be inconsistent not to replace the CTLESC with
+ another backslash here. We can't tell at this point whether the
+ CTLESC comes from a backslash or other form of quoting in the
+ original pattern. */
+ goto convert_to_backslash;
}
else if (pathname[i] == '\\' && (qflags & QGLOB_REGEXP))
last_was_backslash = 1;
pid = make_child ((char *)NULL, 1);
if (pid == 0)
{
+interactive = 0;
reset_terminating_signals (); /* XXX */
free_pushed_string_input ();
/* Cancel traps, in trap.c. */
restore_original_signals (); /* XXX - what about special builtins? bash-4.2 */
QUIT; /* catch any interrupts we got post-fork */
setup_async_signals ();
+ if (open_for_read_in_child == 0)
+ async_redirect_stdin ();
subshell_environment |= SUBSHELL_COMSUB|SUBSHELL_PROCSUB;
/* We don't inherit the verbose option for command substitutions now, so
[a
[[:alpha:]
ok 2
+ok 2.1
ok 3
+ok 4
== LANG=en_US.UTF-8 ==
[[:alpha:]
ok 1
[a
[[:alpha:]
ok 2
+ok 2.1
ok 3
+ok 4
invalid character class
== LANG=C ==
+p
+p
ok 1
ok 2
ok 3
ok 5
ok 6
== LANG=en_US.UTF-8 ==
+p
+p
ok 1
ok 2
ok 3
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
: ${TMPDIR:=/var/tmp}
-cd $TMPDIR
+
+TESTDIR=${TMPDIR}/glob-test-$$
+mkdir ${TESTDIR}
+cd $TESTDIR || {
+ echo "$TESTDIR: cannot cd" >&2
+ exit 1
+}
matchfunc()
{
*) echo bad 2;;
esac
+ case x in
+ [[:aeioux:]) echo bad 2.1 ;;
+ *) echo ok 2.1 ;;
+ esac
+
case [x in
[[:alpha:]) echo bad 3;;
*) echo ok 3;;
esac
+
+ # unclosed bracket char class expression just matches against ":alpha"
+ case a in
+ [[:alpha]) echo ok 4;;
+ *) echo bad 4;;
+ esac
}
echo invalid bracket expression
{
echo == LANG=$LANG ==
+ touch p
+ # quoted character classes work as if they were unquoted now
+ echo [[:alpha:]]
+ echo [[:"alpha":]]
+ rm -f p
+
case a] in
[[:aleph:]]) echo bad 1;;
*) echo ok 1;;
*) echo ok 3;;
esac
- case a in
- [[:"alpha":]]) echo bad 4;;
- *) echo ok 4;;
+ # Posix says quoted character class names work now
+ case x in
+ [[:"alpha":]]) echo ok 4;;
+ *) echo bad 4;;
esac
case a in
export LANG=en_US.UTF-8
matchfunc
+
+cd $OLDPWD
+rm -rf $TESTDIR