diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 2d2f7fcb..b8436d64 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -12988,12 +12988,42 @@ lib/glob/glob.c lib/glob/glob_loop.c - CHAR -> GCHAR (unsigned char); change uses of CHAR to GCHAR - - extglob_skipname: move here from gmisc.c, generalize for regular - and wide-char versions lib/glob/glob.c - wchkname -> wskipname - wskipname: now takes a third `flags' argument, like the other variants of skipname + 1/17 + ---- +redir.c + - here_document_to_fd: set the file descriptor open for writing to the + here document to be close-on-exec. Fixes bug reported by + Siteshwar Vashisht + 1/18 + ---- +{gmisc,gm_loop}.c + - match_pattern_char,match_pattern_wchar: moved to gm_loop.c (new file), + compile twice for single and wide characters as with the rest of + the functions + - umatchlen,wmatchlen: ditto + - extglob_pattern_p: move to gm_loop.c, generalize for regular and + wide-char versions + + 1/19 + ---- +lib/readline/complete.c + - stat_char: fix small memory leak if stat/lstat returns -1 + +bashline.c + - bash_filename_stat_hook,bash_directory_completion_hook: make sure + expand_prompt_string is caled wth W_NOPROCSUB flag + - directory_exists: don't dequote the filename passed as an argument; + this function should never get quoted pathnames + +subst.c + - expand_word_internal: when calling expand_word_internal recursively + after reading a double-quoted string, make sure the W_NOCOMSUB and + W_NOPROCSUB flags make it to the recursive invocation. Fixes bug + reported by Jens Heyens diff --git a/MANIFEST b/MANIFEST index 2fd33306..13c2fd61 100644 --- a/MANIFEST +++ b/MANIFEST @@ -239,6 +239,7 @@ lib/glob/glob.c f lib/glob/glob.h f lib/glob/glob_loop.c f lib/glob/gmisc.c f +lib/glob/gm_loop.c f lib/glob/xmbsrtowcs.c f lib/glob/collsyms.h f lib/glob/doc/Makefile f diff --git a/bashline.c b/bashline.c index caf60c64..908a47c3 100644 --- a/bashline.c +++ b/bashline.c @@ -143,7 +143,7 @@ static int executable_completion __P((const char *, int)); static rl_icppfunc_t *save_directory_hook __P((void)); static void restore_directory_hook __P((rl_icppfunc_t)); -static int directory_exists __P((const char *)); +static int directory_exists __P((const char *, int)); static void cleanup_expansion_error __P((void)); static void maybe_make_readline_line __P((char *)); @@ -1157,7 +1157,7 @@ bash_backward_shellword (count, key) size_t slen; int sindex, c, p; DECLARE_MBSTATE; - + if (count < 0) return (bash_forward_shellword (-count, key)); @@ -3106,18 +3106,20 @@ restore_directory_hook (hookf) rl_directory_rewrite_hook = hookf; } -/* Check whether not the (dequoted) version of DIRNAME, with any trailing slash - removed, exists. */ +/* Check whether not DIRNAME, with any trailing slash removed, exists. If + SHOULD_DEQUOTE is non-zero, we dequote the directory name first. */ static int -directory_exists (dirname) +directory_exists (dirname, should_dequote) const char *dirname; + int should_dequote; { char *new_dirname; int dirlen, r; struct stat sb; - /* First, dequote the directory name */ - new_dirname = bash_dequote_filename ((char *)dirname, rl_completion_quote_character); + /* We save the string and chop the trailing slash because stat/lstat behave + inconsistently if one is present. */ + new_dirname = should_dequote ? bash_dequote_filename ((char *)dirname, rl_completion_quote_character) : savestring (dirname); dirlen = STRLEN (new_dirname); if (new_dirname[dirlen - 1] == '/') new_dirname[dirlen - 1] = '\0'; @@ -3149,7 +3151,7 @@ bash_filename_stat_hook (dirname) else if (t = mbschr (local_dirname, '`')) /* XXX */ should_expand_dirname = '`'; - if (should_expand_dirname && directory_exists (local_dirname)) + if (should_expand_dirname && directory_exists (local_dirname, 0)) should_expand_dirname = 0; if (should_expand_dirname) @@ -3159,7 +3161,7 @@ bash_filename_stat_hook (dirname) have to worry about restoring this setting. */ global_nounset = unbound_vars_is_error; unbound_vars_is_error = 0; - wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB|W_COMPLETE); /* does the right thing */ + wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB|W_NOPROCSUB|W_COMPLETE); /* does the right thing */ unbound_vars_is_error = global_nounset; if (wl) { @@ -3259,13 +3261,13 @@ bash_directory_completion_hook (dirname) should_expand_dirname = '`'; } - if (should_expand_dirname && directory_exists (local_dirname)) + if (should_expand_dirname && directory_exists (local_dirname, 1)) should_expand_dirname = 0; if (should_expand_dirname) { new_dirname = savestring (local_dirname); - wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB|W_COMPLETE); /* does the right thing */ + wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB|W_NOPROCSUB|W_COMPLETE); /* does the right thing */ if (wl) { *dirname = string_list (wl); diff --git a/general.c b/general.c index 338b53c8..f3cc1fb8 100644 --- a/general.c +++ b/general.c @@ -445,6 +445,14 @@ sh_unset_nodelay_mode (fd) return 0; } +/* Just a wrapper for the define in include/filecntl.h */ +int +sh_setclexec (fd) + int fd; +{ + return (SET_CLOSE_ON_EXEC (fd)); +} + /* Return 1 if file descriptor FD is valid; 0 otherwise. */ int sh_validfd (fd) diff --git a/general.h b/general.h index 819634ce..d55f26bf 100644 --- a/general.h +++ b/general.h @@ -295,6 +295,7 @@ extern int legal_alias_name __P((const char *, int)); extern int assignment __P((const char *, int)); extern int sh_unset_nodelay_mode __P((int)); +extern int sh_setclexec __P((int)); extern int sh_validfd __P((int)); extern int fd_ispipe __P((int)); extern void check_dev_tty __P((void)); diff --git a/lib/glob/Makefile.in b/lib/glob/Makefile.in index 23bf8c8b..7ce5d733 100644 --- a/lib/glob/Makefile.in +++ b/lib/glob/Makefile.in @@ -164,4 +164,5 @@ xmbsrtowcs.o: xmbsrtowcs.c # dependencies for C files that include other C files glob.o: glob_loop.c +gmisc.o: gm_loop.c smatch.o: sm_loop.c diff --git a/lib/glob/glob.c b/lib/glob/glob.c index 1451afaa..356857be 100644 --- a/lib/glob/glob.c +++ b/lib/glob/glob.c @@ -1,6 +1,6 @@ /* glob.c -- file-name wildcard pattern matching for Bash. - Copyright (C) 1985-2009 Free Software Foundation, Inc. + Copyright (C) 1985-2017 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne-Again SHell. @@ -123,6 +123,9 @@ static char **glob_dir_to_array __P((char *, char **, int)); extern char *glob_patscan __P((char *, char *, int)); extern wchar_t *glob_patscan_wc __P((wchar_t *, wchar_t *, int)); +/* And this from gmisc.c/gm_loop.c */ +extern int wextglob_pattern_p __P((wchar_t *)); + extern char *glob_dirscan __P((char *, int)); /* Compile `glob_loop.c' for single-byte characters. */ @@ -131,7 +134,6 @@ extern char *glob_dirscan __P((char *, int)); #define INT int #define L(CS) CS #define INTERNAL_GLOB_PATTERN_P internal_glob_pattern_p -#define EXTGLOB_PATTERN_P extglob_pattern_p #include "glob_loop.c" /* Compile `glob_loop.c' again for multibyte characters. */ @@ -142,7 +144,6 @@ extern char *glob_dirscan __P((char *, int)); #define INT wint_t #define L(CS) L##CS #define INTERNAL_GLOB_PATTERN_P internal_glob_wpattern_p -#define EXTGLOB_PATTERN_P wextglob_pattern_p #include "glob_loop.c" #endif /* HANDLE_MULTIBYTE */ @@ -275,23 +276,23 @@ skipname (pat, dname, flags) #if HANDLE_MULTIBYTE static int -wskipname (pat_wc, dn_wc, flags) - wchar_t *pat_wc, *dn_wc; +wskipname (pat, dname, flags) + wchar_t *pat, *dname; int flags; { /* If a leading dot need not be explicitly matched, and the pattern doesn't start with a `.', don't match `.' or `..' */ - if (noglob_dot_filenames == 0 && pat_wc[0] != L'.' && - (pat_wc[0] != L'\\' || pat_wc[1] != L'.') && - (dn_wc[0] == L'.' && - (dn_wc[1] == L'\0' || (dn_wc[1] == L'.' && dn_wc[2] == L'\0')))) + if (noglob_dot_filenames == 0 && pat[0] != L'.' && + (pat[0] != L'\\' || pat[1] != L'.') && + (dname[0] == L'.' && + (dname[1] == L'\0' || (dname[1] == L'.' && dname[2] == L'\0')))) return 1; /* If a leading dot must be explicitly matched, check to see if the pattern and dirname both have one. */ - else if (noglob_dot_filenames && dn_wc[0] == L'.' && - pat_wc[0] != L'.' && - (pat_wc[0] != L'\\' || pat_wc[1] != L'.')) + else if (noglob_dot_filenames && dname[0] == L'.' && + pat[0] != L'.' && + (pat[0] != L'\\' || pat[1] != L'.')) return 1; return 0; diff --git a/lib/glob/glob_loop.c b/lib/glob/glob_loop.c index 9529ccb6..95029591 100644 --- a/lib/glob/glob_loop.c +++ b/lib/glob/glob_loop.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-2005 Free Software Foundation, Inc. +/* Copyright (C) 1991-2017 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne Again SHell. @@ -61,28 +61,6 @@ INTERNAL_GLOB_PATTERN_P (pattern) return 0; } -#if EXTENDED_GLOB -int -EXTGLOB_PATTERN_P (pat) - const CHAR *pat; -{ - switch (pat[0]) - { - case L('*'): - case L('+'): - case L('!'): - case L('@'): - case L('?'): - return (pat[1] == L('(')); /* ) */ - default: - return 0; - } - - return 0; -} -#endif - -#undef EXTGLOB_PATTERN_P #undef INTERNAL_GLOB_PATTERN_P #undef L #undef INT diff --git a/lib/glob/gm_loop.c b/lib/glob/gm_loop.c new file mode 100644 index 00000000..ac516f82 --- /dev/null +++ b/lib/glob/gm_loop.c @@ -0,0 +1,208 @@ +/* Copyright (C) 1991-2017 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash 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. + + Bash 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 Bash. If not, see . +*/ + +#if EXTENDED_GLOB +int +EXTGLOB_PATTERN_P (pat) + const CHAR *pat; +{ + switch (pat[0]) + { + case L('*'): + case L('+'): + case L('!'): + case L('@'): + case L('?'): + return (pat[1] == L('(')); /* ) */ + default: + return 0; + } + + return 0; +} +#endif + +/* Return 1 of the first character of STRING could match the first + character of pattern PAT. Compiled to both single and wiide character + versions. FLAGS is a subset of strmatch flags; used to do case-insensitive + matching for now. */ +int +MATCH_PATTERN_CHAR (pat, string, flags) + CHAR *pat, *string; + int flags; +{ + CHAR c; + + if (*string == 0) + return (*pat == L('*')); /* XXX - allow only * to match empty string */ + + switch (c = *pat++) + { + default: + return (FOLD(*string) == FOLD(c)); + case L('\\'): + return (FOLD(*string) == FOLD(*pat)); + case L('?'): + return (*pat == L('(') ? 1 : (*string != L'\0')); + case L('*'): + return (1); + case L('+'): + case L('!'): + case L('@'): + return (*pat == L('(') ? 1 : (FOLD(*string) == FOLD(c))); + case L('['): + return (*string != L('\0')); + } +} + +int +MATCHLEN (pat, max) + CHAR *pat; + size_t max; +{ + CHAR c; + int matlen, bracklen, t, in_cclass, in_collsym, in_equiv; + + if (*pat == 0) + return (0); + + matlen = in_cclass = in_collsym = in_equiv = 0; + while (c = *pat++) + { + switch (c) + { + default: + matlen++; + break; + case L('\\'): + if (*pat == 0) + return ++matlen; + else + { + matlen++; + pat++; + } + break; + case L('?'): + if (*pat == LPAREN) + return (matlen = -1); /* XXX for now */ + else + matlen++; + break; + case L('*'): + return (matlen = -1); + case L('+'): + case L('!'): + case L('@'): + if (*pat == LPAREN) + return (matlen = -1); /* XXX for now */ + else + matlen++; + break; + case L('['): + /* scan for ending `]', skipping over embedded [:...:] */ + bracklen = 1; + c = *pat++; + do + { + if (c == 0) + { + pat--; /* back up to NUL */ + matlen += bracklen; + goto bad_bracket; + } + else if (c == L('\\')) + { + /* *pat == backslash-escaped character */ + bracklen++; + /* If the backslash or backslash-escape ends the string, + bail. The ++pat skips over the backslash escape */ + if (*pat == 0 || *++pat == 0) + { + matlen += bracklen; + goto bad_bracket; + } + } + else if (c == L('[') && *pat == L(':')) /* character class */ + { + pat++; + bracklen++; + in_cclass = 1; + } + else if (in_cclass && c == L(':') && *pat == L(']')) + { + pat++; + bracklen++; + in_cclass = 0; + } + else if (c == L('[') && *pat == L('.')) /* collating symbol */ + { + pat++; + bracklen++; + if (*pat == L(']')) /* right bracket can appear as collating symbol */ + { + pat++; + bracklen++; + } + in_collsym = 1; + } + else if (in_collsym && c == L('.') && *pat == L(']')) + { + pat++; + bracklen++; + in_collsym = 0; + } + else if (c == L('[') && *pat == L('=')) /* equivalence class */ + { + pat++; + bracklen++; + if (*pat == L(']')) /* right bracket can appear as equivalence class */ + { + pat++; + bracklen++; + } + in_equiv = 1; + } + else if (in_equiv && c == L('=') && *pat == L(']')) + { + pat++; + bracklen++; + in_equiv = 0; + } + else + bracklen++; + } + while ((c = *pat++) != L(']')); + matlen++; /* bracket expression can only match one char */ +bad_bracket: + break; + } + } + + return matlen; +} + +#undef EXTGLOB_PATTERN_P +#undef MATCH_PATTERN_CHAR +#undef MATCHLEN +#undef FOLD +#undef L +#undef LPAREN +#undef RPAREN +#undef INT +#undef CHAR diff --git a/lib/glob/gmisc.c b/lib/glob/gmisc.c index 19065fb9..a2bca965 100644 --- a/lib/glob/gmisc.c +++ b/lib/glob/gmisc.c @@ -1,6 +1,6 @@ /* gmisc.c -- miscellaneous pattern matching utility functions for Bash. - Copyright (C) 2010 Free Software Foundation, Inc. + Copyright (C) 2010-2017 Free Software Foundation, Inc. This file is part of GNU Bash, the Bourne-Again SHell. @@ -35,348 +35,44 @@ #ifndef FNM_CASEFOLD # include "strmatch.h" #endif - -#ifndef LPAREN -# define LPAREN '(' -#endif -#ifndef RPAREN -# define RPAREN ')' -#endif - -#if defined (HANDLE_MULTIBYTE) -#define WLPAREN L'(' -#define WRPAREN L')' +#include "glob.h" /* Make sure these names continue to agree with what's in smatch.c */ extern char *glob_patscan __P((char *, char *, int)); -extern wchar_t *glob_patscan_wc __P((wchar_t *, wchar_t *, int)); -#define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c)) - -/* Return 1 of the first character of WSTRING could match the first - character of pattern WPAT. Wide character version. FLAGS is a - subset of strmatch flags; used to do case-insensitive matching for now. */ -int -match_pattern_wchar (wpat, wstring, flags) - wchar_t *wpat, *wstring; - int flags; -{ - wchar_t wc; - - if (*wstring == 0) - return (*wpat == L'*'); /* XXX - allow only * to match empty string */ - - switch (wc = *wpat++) - { - default: - return (FOLD(*wstring) == FOLD(wc)); - case L'\\': - return (FOLD(*wstring) == FOLD(*wpat)); - case L'?': - return (*wpat == WLPAREN ? 1 : (*wstring != L'\0')); - case L'*': - return (1); - case L'+': - case L'!': - case L'@': - return (*wpat == WLPAREN ? 1 : (FOLD(*wstring) == FOLD(wc))); - case L'[': - return (*wstring != L'\0'); - } -} - -int -wmatchlen (wpat, wmax) - wchar_t *wpat; - size_t wmax; -{ - wchar_t wc; - int matlen, bracklen, t, in_cclass, in_collsym, in_equiv; - - if (*wpat == 0) - return (0); - - matlen = in_cclass = in_collsym = in_equiv = 0; - while (wc = *wpat++) - { - switch (wc) - { - default: - matlen++; - break; - case L'\\': - if (*wpat == 0) - return ++matlen; - else - { - matlen++; - wpat++; - } - break; - case L'?': - if (*wpat == WLPAREN) - return (matlen = -1); /* XXX for now */ - else - matlen++; - break; - case L'*': - return (matlen = -1); - case L'+': - case L'!': - case L'@': - if (*wpat == WLPAREN) - return (matlen = -1); /* XXX for now */ - else - matlen++; - break; - case L'[': - /* scan for ending `]', skipping over embedded [:...:] */ - bracklen = 1; - wc = *wpat++; - do - { - if (wc == 0) - { - wpat--; /* back up to NUL */ - matlen += bracklen; - goto bad_bracket; - } - else if (wc == L'\\') - { - /* *wpat == backslash-escaped character */ - bracklen++; - /* If the backslash or backslash-escape ends the string, - bail. The ++wpat skips over the backslash escape */ - if (*wpat == 0 || *++wpat == 0) - { - matlen += bracklen; - goto bad_bracket; - } - } - else if (wc == L'[' && *wpat == L':') /* character class */ - { - wpat++; - bracklen++; - in_cclass = 1; - } - else if (in_cclass && wc == L':' && *wpat == L']') - { - wpat++; - bracklen++; - in_cclass = 0; - } - else if (wc == L'[' && *wpat == L'.') /* collating symbol */ - { - wpat++; - bracklen++; - if (*wpat == L']') /* right bracket can appear as collating symbol */ - { - wpat++; - bracklen++; - } - in_collsym = 1; - } - else if (in_collsym && wc == L'.' && *wpat == L']') - { - wpat++; - bracklen++; - in_collsym = 0; - } - else if (wc == L'[' && *wpat == L'=') /* equivalence class */ - { - wpat++; - bracklen++; - if (*wpat == L']') /* right bracket can appear as equivalence class */ - { - wpat++; - bracklen++; - } - in_equiv = 1; - } - else if (in_equiv && wc == L'=' && *wpat == L']') - { - wpat++; - bracklen++; - in_equiv = 0; - } - else - bracklen++; - } - while ((wc = *wpat++) != L']'); - matlen++; /* bracket expression can only match one char */ -bad_bracket: - break; - } - } - - return matlen; -} -#endif - -#undef FOLD +/* Compile `gm_loop.c' for single-byte characters. */ +#define CHAR char +#define INT int +#define L(CS) CS +#define EXTGLOB_PATTERN_P extglob_pattern_p +#define MATCH_PATTERN_CHAR match_pattern_char +#define MATCHLEN umatchlen #define FOLD(c) ((flags & FNM_CASEFOLD) \ ? TOLOWER ((unsigned char)c) \ : ((unsigned char)c)) +#ifndef LPAREN +#define LPAREN '(' +#define RPAREN ')' +#endif +#include "gm_loop.c" -/* Return 1 of the first character of STRING could match the first - character of pattern PAT. Used to avoid n2 calls to strmatch(). - FLAGS is a subset of strmatch flags; used to do case-insensitive - matching for now. */ -int -match_pattern_char (pat, string, flags) - char *pat, *string; - int flags; -{ - char c; +/* Compile `gm_loop.c' again for multibyte characters. */ +#if HANDLE_MULTIBYTE - if (*string == 0) - return (*pat == '*'); /* XXX - allow only * to match empty string */ +#define CHAR wchar_t +#define INT wint_t +#define L(CS) L##CS +#define EXTGLOB_PATTERN_P wextglob_pattern_p +#define MATCH_PATTERN_CHAR match_pattern_wchar +#define MATCHLEN wmatchlen - switch (c = *pat++) - { - default: - return (FOLD(*string) == FOLD(c)); - case '\\': - return (FOLD(*string) == FOLD(*pat)); - case '?': - return (*pat == LPAREN ? 1 : (*string != '\0')); - case '*': - return (1); - case '+': - case '!': - case '@': - return (*pat == LPAREN ? 1 : (FOLD(*string) == FOLD(c))); - case '[': - return (*string != '\0'); - } -} +#define FOLD(c) ((flags & FNM_CASEFOLD) && iswupper (c) ? towlower (c) : (c)) +#define LPAREN L'(' +#define RPAREN L')' +#include "gm_loop.c" -int -umatchlen (pat, max) - char *pat; - size_t max; -{ - char c; - int matlen, bracklen, t, in_cclass, in_collsym, in_equiv; +#endif /* HANDLE_MULTIBYTE */ - if (*pat == 0) - return (0); - - matlen = in_cclass = in_collsym = in_equiv = 0; - while (c = *pat++) - { - switch (c) - { - default: - matlen++; - break; - case '\\': - if (*pat == 0) - return ++matlen; - else - { - matlen++; - pat++; - } - break; - case '?': - if (*pat == LPAREN) - return (matlen = -1); /* XXX for now */ - else - matlen++; - break; - case '*': - return (matlen = -1); - case '+': - case '!': - case '@': - if (*pat == LPAREN) - return (matlen = -1); /* XXX for now */ - else - matlen++; - break; - case '[': - /* scan for ending `]', skipping over embedded [:...:] */ - bracklen = 1; - c = *pat++; - do - { - if (c == 0) - { - pat--; /* back up to NUL */ - matlen += bracklen; - goto bad_bracket; - } - else if (c == '\\') - { - /* *pat == backslash-escaped character */ - bracklen++; - /* If the backslash or backslash-escape ends the string, - bail. The ++pat skips over the backslash escape */ - if (*pat == 0 || *++pat == 0) - { - matlen += bracklen; - goto bad_bracket; - } - } - else if (c == '[' && *pat == ':') /* character class */ - { - pat++; - bracklen++; - in_cclass = 1; - } - else if (in_cclass && c == ':' && *pat == ']') - { - pat++; - bracklen++; - in_cclass = 0; - } - else if (c == '[' && *pat == '.') /* collating symbol */ - { - pat++; - bracklen++; - if (*pat == ']') /* right bracket can appear as collating symbol */ - { - pat++; - bracklen++; - } - in_collsym = 1; - } - else if (in_collsym && c == '.' && *pat == ']') - { - pat++; - bracklen++; - in_collsym = 0; - } - else if (c == '[' && *pat == '=') /* equivalence class */ - { - pat++; - bracklen++; - if (*pat == ']') /* right bracket can appear as equivalence class */ - { - pat++; - bracklen++; - } - in_equiv = 1; - } - else if (in_equiv && c == '=' && *pat == ']') - { - pat++; - bracklen++; - in_equiv = 0; - } - else - bracklen++; - } - while ((c = *pat++) != ']'); - matlen++; /* bracket expression can only match one char */ -bad_bracket: - break; - } - } - - return matlen; -} #if defined (EXTENDED_GLOB) /* Skip characters in PAT and return the final occurrence of DIRSEP. This diff --git a/lib/readline/complete.c b/lib/readline/complete.c index 0a81129b..1d79dcb3 100644 --- a/lib/readline/complete.c +++ b/lib/readline/complete.c @@ -625,7 +625,10 @@ stat_char (filename) #endif if (r == -1) - return (0); + { + xfree (f); + return (0); + } character = 0; if (S_ISDIR (finfo.st_mode)) diff --git a/redir.c b/redir.c index 1f4ce41a..68741dbb 100644 --- a/redir.c +++ b/redir.c @@ -466,6 +466,8 @@ here_document_to_fd (redirectee, ri) return (fd); } + SET_CLOSE_ON_EXEC (fd); + errno = r = 0; /* XXX */ /* write_here_document returns 0 on success, errno on failure. */ if (redirectee->word) diff --git a/subst.c b/subst.c index 03656d70..21c3c729 100644 --- a/subst.c +++ b/subst.c @@ -9612,6 +9612,10 @@ add_twochars: tword->flags |= word->flags & (W_ASSIGNARG|W_ASSIGNRHS); /* affects $@ */ if (word->flags & W_COMPLETE) tword->flags |= W_COMPLETE; /* for command substitutions */ + if (word->flags & W_NOCOMSUB) + tword->flags |= W_NOCOMSUB; + if (word->flags & W_NOPROCSUB) + tword->flags |= W_NOPROCSUB; temp = (char *)NULL; diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 554f3d6e..58c375b7 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/bash/bash-current +BUILD_DIR=/usr/local/build/chet/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/tests/run-all b/tests/run-all index e5499943..68fd2a5f 100644 --- a/tests/run-all +++ b/tests/run-all @@ -16,8 +16,14 @@ export PATH # unset BASH_ENV only if it is set [ "${BASH_ENV+set}" = "set" ] && unset BASH_ENV -# ditto for SHELLOPTS -[ "${SHELLOPTS+set}" = "set" ] && unset SHELLOPTS +# can't reliably do it for SHELLOPTS; SHELLOPTS is readonly in bash +if [ "${BASH_VERSION+set}" = "set" ]; then + export -n SHELLOPTS # just make sure its not exported + set +o posix + typeset -p SHELLOPTS +else + [ "${SHELLOPTS+set}" = "set" ] && unset SHELLOPTS 2>/dev/null +fi : ${THIS_SH:=../bash} export THIS_SH