--- bashline.c 2015-02-06 17:12:55.823275600 -0700 +++ bashline.c 2015-02-06 17:14:11.000103800 -0700 @@ -71,6 +71,16 @@ # include "pcomplete.h" #endif +#if __CYGWIN__ +# ifdef __x86_64__ +# define IMP(x) __imp_##x +# else +# define IMP(x) _imp__##x +# endif +#else +# define IMP(x) x +#endif + /* These should agree with the defines for emacs_mode and vi_mode in rldefs.h, even though that's not a public readline header file. */ #ifndef EMACS_EDITING_MODE @@ -264,6 +274,11 @@ int no_empty_command_completion; are the only possible matches, even if FIGNORE says to. */ int force_fignore = 1; +#if __CYGWIN__ +/* If set, shorten "foo.exe" to "foo" when they are the same file. */ +int completion_strip_exe; +#endif /* __CYGWIN__ */ + /* Perform spelling correction on directory names during word completion */ int dircomplete_spelling = 0; @@ -491,11 +506,12 @@ initialize_readline () kseq[0] = CTRL('J'); kseq[1] = '\0'; func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL); - if (func == rl_vi_editing_mode) + extern rl_command_func_t *IMP(rl_vi_editing_mode); + if (func == rl_vi_editing_mode || func == IMP(rl_vi_editing_mode)) rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap); kseq[0] = CTRL('M'); func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL); - if (func == rl_vi_editing_mode) + if (func == rl_vi_editing_mode || func == IMP(rl_vi_editing_mode)) rl_unbind_key_in_map (CTRL('M'), emacs_meta_keymap); #if defined (VI_MODE) rl_unbind_key_in_map (CTRL('E'), vi_movement_keymap); @@ -514,7 +530,8 @@ initialize_readline () kseq[0] = '~'; kseq[1] = '\0'; func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL); - if (func == 0 || func == rl_tilde_expand) + extern rl_command_func_t *IMP(rl_tilde_expand); + if (func == 0 || func == rl_tilde_expand || func == IMP(rl_tilde_expand)) rl_bind_keyseq_in_map (kseq, bash_complete_username, emacs_meta_keymap); rl_bind_key_if_unbound_in_map ('~', bash_possible_username_completions, emacs_ctlx_keymap); @@ -537,7 +554,8 @@ initialize_readline () kseq[0] = TAB; kseq[1] = '\0'; func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL); - if (func == 0 || func == rl_tab_insert) + extern rl_command_func_t *IMP(rl_tab_insert); + if (func == 0 || func == rl_tab_insert || func == IMP(rl_tab_insert)) rl_bind_key_in_map (TAB, dynamic_complete_history, emacs_meta_keymap); /* Tell the completer that we want a crack first. */ @@ -2109,6 +2127,21 @@ globword: if (match && executable_completion ((searching_path ? val : cval), searching_path)) { +#if __CYGWIN__ + if (completion_strip_exe) + { + size_t val_len = strlen (val); + char *candidate; + if (val_len > 4 && !strcasecmp (&val[val_len - 4], ".exe") + && (candidate = strdup (val))) + { + candidate[val_len - 4] = '\0'; + if (same_file (val, candidate, NULL, NULL)) + temp[strlen (temp) - 4] = '\0'; + free (candidate); + } + } +#endif if (cval != val) free (cval); free (val); @@ -2844,6 +2877,17 @@ test_for_directory (name) int r; fn = bash_tilde_expand (name, 0); +#if __CYGWIN__ + /* stat("//server") can only be successful as a directory, but takes + a several-second timeout to fail. It is much faster to assume + that //server is a valid name than it is to wait for the stat, + even though it gives false positives on bad names. */ + if (fn[0] == '/' && fn[1] == '/' && ! strchr (&fn[2], '/')) + { + free (fn); + return 1; + } +#endif /* __CYGWIN__ */ r = file_isdir (fn); free (fn); --- builtins/evalstring.c 2015-02-06 17:12:55.682776800 -0700 +++ builtins/evalstring.c 2015-02-06 17:14:11.015662800 -0700 @@ -195,7 +195,7 @@ parse_and_execute (string, from_file, fl int code, lreset; volatile int should_jump_to_top_level, last_result; COMMAND *volatile command; - volatile sigset_t pe_sigmask; + sigset_t pe_sigmask; parse_prologue (string, flags, PE_TAG); @@ -451,7 +451,7 @@ parse_string (string, from_file, flags, volatile int should_jump_to_top_level; COMMAND *volatile command, *oglobal; char *ostring; - volatile sigset_t ps_sigmask; + sigset_t ps_sigmask; parse_prologue (string, flags, PS_TAG); --- builtins/set.def 2013-04-19 05:20:34.000000000 -0600 +++ builtins/set.def 2015-02-06 17:14:11.015662800 -0700 @@ -56,6 +56,13 @@ extern int dont_save_function_defs; #if defined (READLINE) extern int no_line_editing; #endif /* READLINE */ +#if __CYGWIN__ +extern int igncr; +static int set_minus_o_option_maybe (int, const char *, int); +# define INTERACTIVE_ONLY ,1 +#else /* ! __CYGWIN__ */ +# define INTERACTIVE_ONLY +#endif $BUILTIN set $FUNCTION set_builtin @@ -92,6 +99,9 @@ Options: #if defined (HISTORY) history enable command history #endif +#if __CYGWIN__ + igncr on cygwin, ignore \r in line endings +#endif ignoreeof the shell will not exit upon reading EOF interactive-comments allow comments to appear in interactive commands @@ -188,29 +198,41 @@ const struct { int *variable; setopt_set_func_t *set_func; setopt_get_func_t *get_func; +#if __CYGWIN__ + /* Cygwin users have taken to exporting SHELLOPTS for the + cygwin-specific igncr. As a result, we need to make sure + SHELLOPTS parsing does not turn on interactive options when + exported from an interactive shell, but parsed in a + non-interactive setting, since some interactive options violate + POSIX /bin/sh rules. */ + int interactive_only; +#endif /* __CYGWIN__ */ } o_options[] = { { "allexport", 'a', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, #if defined (BRACE_EXPANSION) { "braceexpand",'B', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, #endif #if defined (READLINE) - { "emacs", '\0', (int *)NULL, set_edit_mode, get_edit_mode }, + { "emacs", '\0', (int *)NULL, set_edit_mode, get_edit_mode INTERACTIVE_ONLY}, #endif { "errexit", 'e', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, { "errtrace", 'E', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, { "functrace", 'T', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, { "hashall", 'h', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, #if defined (BANG_HISTORY) - { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, + { "histexpand", 'H', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL INTERACTIVE_ONLY}, #endif /* BANG_HISTORY */ #if defined (HISTORY) - { "history", '\0', &enable_history_list, bash_set_history, (setopt_get_func_t *)NULL }, + { "history", '\0', &enable_history_list, bash_set_history, (setopt_get_func_t *)NULL INTERACTIVE_ONLY}, +#endif +#if __CYGWIN__ + { "igncr", '\0', &igncr, NULL, (setopt_get_func_t *)NULL }, #endif { "ignoreeof", '\0', &ignoreeof, set_ignoreeof, (setopt_get_func_t *)NULL }, { "interactive-comments", '\0', &interactive_comments, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, { "keyword", 'k', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, #if defined (JOB_CONTROL) - { "monitor", 'm', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, + { "monitor", 'm', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL INTERACTIVE_ONLY}, #endif { "noclobber", 'C', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, { "noexec", 'n', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, @@ -229,7 +251,7 @@ const struct { { "privileged", 'p', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, { "verbose", 'v', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, #if defined (READLINE) - { "vi", '\0', (int *)NULL, set_edit_mode, get_edit_mode }, + { "vi", '\0', (int *)NULL, set_edit_mode, get_edit_mode INTERACTIVE_ONLY}, #endif { "xtrace", 'x', (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, {(char *)NULL, 0 , (int *)NULL, (setopt_set_func_t *)NULL, (setopt_get_func_t *)NULL }, @@ -416,6 +438,15 @@ int set_minus_o_option (on_or_off, option_name) int on_or_off; char *option_name; +#if __CYGWIN__ +{ + /* See cygwin comments above. */ + return set_minus_o_option_maybe (on_or_off, option_name, 0); +} +static int +set_minus_o_option_maybe (int on_or_off, const char *option_name, + int avoid_interactive) +#endif /* __CYGWIN__ */ { register int i; @@ -423,6 +454,10 @@ set_minus_o_option (on_or_off, option_na { if (STREQ (option_name, o_options[i].name)) { +#if __CYGWIN__ + if (o_options[i].interactive_only && avoid_interactive) + return EXECUTION_SUCCESS; +#endif /* __CYGWIN__ */ if (o_options[i].letter == 0) { SET_BINARY_O_OPTION_VALUE (i, on_or_off, option_name); @@ -548,7 +583,11 @@ parse_shellopts (value) vptr = 0; while (vname = extract_colon_unit (value, &vptr)) { +#if __CYGWIN__ + set_minus_o_option_maybe (FLAG_ON, vname, !interactive_shell); +#else /* !__CYGWIN__ */ set_minus_o_option (FLAG_ON, vname); +#endif free (vname); } } --- builtins/shopt.def 2013-02-27 07:43:20.000000000 -0700 +++ builtins/shopt.def 2015-02-06 17:14:11.015662800 -0700 @@ -91,6 +91,11 @@ extern int glob_star; extern int glob_asciirange; extern int lastpipe_opt; +#if __CYGWIN__ +extern int completion_strip_exe; +#endif + + #if defined (EXTENDED_GLOB) extern int extended_glob; #endif @@ -161,6 +166,9 @@ static struct { { "compat40", &shopt_compat40, set_compatibility_level }, { "compat41", &shopt_compat41, set_compatibility_level }, { "compat42", &shopt_compat41, set_compatibility_level }, +#if __CYGWIN__ + { "completion_strip_exe", &completion_strip_exe, NULL }, +#endif #if defined (READLINE) { "complete_fullquote", &complete_fullquote, (shopt_set_func_t *)NULL}, { "direxpand", &dircomplete_expand, shopt_set_complete_direxpand }, --- config-top.h 2012-08-18 18:51:30.000000000 -0600 +++ config-top.h 2015-02-06 17:14:11.015662800 -0700 @@ -80,10 +80,10 @@ #define KSH_COMPATIBLE_SELECT /* System-wide .bashrc file for interactive shells. */ -/* #define SYS_BASHRC "/etc/bash.bashrc" */ +#define SYS_BASHRC "/etc/bash.bashrc" /* System-wide .bash_logout for login shells. */ -/* #define SYS_BASH_LOGOUT "/etc/bash.bash_logout" */ +#define SYS_BASH_LOGOUT "/etc/bash.bash_logout" /* Define this to make non-interactive shells begun with argv[0][0] == '-' run the startup files when not in posix mode. */ @@ -93,7 +93,7 @@ sshd and source the .bashrc if so (like the rshd behavior). This checks for the presence of SSH_CLIENT or SSH2_CLIENT in the initial environment, which can be fooled under certain not-uncommon circumstances. */ -/* #define SSH_SOURCE_BASHRC */ +#define SSH_SOURCE_BASHRC /* Define if you want the case-capitalizing operators (~[~]) and the `capcase' variable attribute (declare -c). */ --- doc/Makefile.in 2013-10-30 14:18:12.000000000 -0600 +++ doc/Makefile.in 2015-02-06 17:14:11.015662800 -0700 @@ -176,7 +176,7 @@ bashref.html: $(BASHREF_FILES) $(HSUSER) $(TEXI2HTML) -menu -monolithic -I $(TEXINPUTDIR) $(srcdir)/bashref.texi bash.info: bashref.info - ${SHELL} ${INFOPOST} < $(srcdir)/bashref.info > $@ ; \ + ${SHELL} ${INFOPOST} < bashref.info > $@ ; \ bash.txt: bash.1 bash.ps: bash.1 @@ -237,9 +237,9 @@ install: info installdirs bash.info -$(INSTALL_DATA) $(srcdir)/bashbug.1 $(DESTDIR)$(man1dir)/bashbug${man1ext} -$(INSTALL_DATA) $(OTHER_DOCS) $(DESTDIR)$(docdir) # uncomment the next lines to install the builtins man page -# sed 's:bash\.1:man1/&:' $(srcdir)/builtins.1 > $${TMPDIR:-/var/tmp}/builtins.1 -# -$(INSTALL_DATA) $${TMPDIR:-/var/tmp}/builtins.1 $(DESTDIR)$(man1dir)/bash_builtins${man1ext} -# -$(RM) $${TMPDIR:-/var/tmp}/builtins.1 + sed 's:bash\.1:man1/&:' $(srcdir)/builtins.1 > $${TMPDIR:-/var/tmp}/builtins.1 + -$(INSTALL_DATA) $${TMPDIR:-/var/tmp}/builtins.1 $(DESTDIR)$(man1dir)/bash_builtins${man1ext} + -$(RM) $${TMPDIR:-/var/tmp}/builtins.1 -if test -f bash.info; then d=.; else d=$(srcdir); fi; \ $(INSTALL_DATA) $$d/bash.info $(DESTDIR)$(infodir)/bash.info # run install-info if it is present to update the info directory --- doc/bash.1 2014-02-06 07:03:52.000000000 -0700 +++ doc/bash.1 2015-02-06 17:14:11.015662800 -0700 @@ -1658,6 +1658,14 @@ subsequently reset. Expands to the effective user ID of the current user, initialized at shell startup. This variable is readonly. .TP +.B EXECIGNORE +A colon-separated list of extended glob (see \fBPattern Matching\fP) +patterns. Files with full paths matching one of these patterns are +not considered executable for the purposes of completion and PATH +searching, but the \fB[\fP, \fB[[\fP, and \fBtest\fP builtins are not +affected. Use this variable to deal with systems that set the +executable bit on files that are not actually executable. +.TP .B FUNCNAME An array variable containing the names of all shell functions currently in the execution call stack. @@ -3308,6 +3316,10 @@ the character .B ``.'' at the start of a name or immediately following a slash must be matched explicitly, unless the shell option +.B completion_strip_exe +If set, whenever bash sees `foo.exe' during completion, it checks if +`foo' is the same file and strips the suffix. +.TP 8 .B dotglob is set. When matching a pathname, the slash character must always be --- doc/bashref.texi 2014-02-22 11:20:36.000000000 -0700 +++ doc/bashref.texi 2015-02-06 17:14:11.015662800 -0700 @@ -4992,6 +4992,10 @@ filenames. This variable is set by default, which is the default Bash behavior in versions through 4.2. +@item completion_strip_exe +If set, whenever bash sees `foo.exe' during completion, it checks if +`foo' is the same file and strips the suffix. + @item direxpand If set, Bash replaces directory names with the results of word expansion when performing @@ -5578,6 +5582,14 @@ Similar to @code{BASH_ENV}; used when th The numeric effective user id of the current user. This variable is readonly. +@item EXECIGNORE +A colon-separated list of extended glob ((@pxref{Pattern Matching}) +patterns. Files with full paths matching one of these patterns are +not considered executable for the purposes of completion and PATH +searching, but the @code{[}, @code{[[}, and @code{test} builtins are +not affected. Use this variable to deal with systems that set the +executable bit on files that are not actually executable. + @item FCEDIT The editor used as a default by the @option{-e} option to the @code{fc} builtin command. --- doc/builtins.1 2012-02-21 12:32:05.000000000 -0700 +++ doc/builtins.1 2015-02-06 17:14:11.031260100 -0700 @@ -19,6 +19,6 @@ shift, shopt, source, suspend, test, tim ulimit, umask, unalias, unset, wait \- bash built-in commands, see \fBbash\fR(1) .SH BASH BUILTIN COMMANDS .nr zZ 1 -.so bash.1 +.so man1/bash.1 .SH SEE ALSO bash(1), sh(1) --- execute_cmd.c 2015-02-06 17:12:55.261573700 -0700 +++ execute_cmd.c 2015-02-06 17:14:11.031260100 -0700 @@ -58,6 +58,7 @@ extern int errno; #endif #define NEED_FPURGE_DECL +#define NEED_SH_SETLINEBUF_DECL /* used in externs.h */ #include "bashansi.h" #include "bashintl.h" --- expr.c 2014-01-03 06:55:00.000000000 -0700 +++ expr.c 2015-02-06 17:14:11.031260100 -0700 @@ -83,6 +83,7 @@ #include "shell.h" #include "typemax.h" /* INTMAX_MAX, INTMAX_MIN */ +#define exp2 exp2_ /* Because of the $((...)) construct, expressions may include newlines. Here is a macro which accepts newlines, tabs and spaces as whitespace. */ --- findcmd.c 2012-10-15 05:45:04.000000000 -0600 +++ findcmd.c 2015-02-06 17:14:11.031260100 -0700 @@ -48,6 +48,8 @@ extern int errno; #endif +#include + extern int posixly_correct; extern int last_command_exit_value; @@ -77,6 +79,38 @@ int check_hashed_filenames; containing the file of interest. */ int dot_found_in_search = 0; +static struct ignorevar execignore = +{ + "EXECIGNORE", + (struct ign *)0, + 0, + (char *)0, + (sh_iv_item_func_t *)0, +}; + +void +setup_exec_ignore (char *varname) +{ + setup_ignore_patterns (&execignore); +} + +/* Return whether we should never consider file executable + * even if the system tells us it is. */ +static int +is_on_exec_blacklist (char *name) +{ + struct ign *p; + int flags = FNM_EXTMATCH | FNM_CASEFOLD; + + for (p = execignore.ignores; p && p->val; p++) + { + if (strmatch (p->val, (char *)name, flags) != FNM_NOMATCH) + return (1); + } + + return (0); +} + /* Return some flags based on information about this file. The EXISTS bit is non-zero if the file is found. The EXECABLE bit is non-zero the file is executble. @@ -104,7 +138,7 @@ file_status (name) file access mechanisms into account. eaccess uses the effective user and group IDs, not the real ones. We could use sh_eaccess, but we don't want any special treatment for /dev/fd. */ - if (eaccess (name, X_OK) == 0) + if (!is_on_exec_blacklist (name) && eaccess (name, X_OK) == 0) r |= FS_EXECABLE; if (eaccess (name, R_OK) == 0) r |= FS_READABLE; --- findcmd.h 2012-01-14 16:56:25.000000000 -0700 +++ findcmd.h 2015-02-06 17:14:11.031260100 -0700 @@ -31,5 +31,6 @@ extern char *find_user_command __P((cons extern char *find_path_file __P((const char *)); extern char *search_for_command __P((const char *, int)); extern char *user_command_matches __P((const char *, int, int)); +extern void setup_exec_ignore __P((char *)); #endif /* _FINDCMD_H_ */ --- general.c 2014-01-30 14:46:15.000000000 -0700 +++ general.c 2015-02-06 17:14:11.031260100 -0700 @@ -44,6 +44,10 @@ #include +#ifdef __CYGWIN__ +# include +#endif + #if !defined (errno) extern int errno; #endif /* !errno */ @@ -632,7 +636,8 @@ make_absolute (string, dot_path) { char pathbuf[PATH_MAX + 1]; - cygwin_conv_to_full_posix_path (string, pathbuf); + cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, string, pathbuf, + sizeof pathbuf); result = savestring (pathbuf); } #else --- include/chartypes.h 2011-04-11 12:30:52.000000000 -0600 +++ include/chartypes.h 2015-02-06 17:14:11.031260100 -0700 @@ -40,6 +40,7 @@ #else # define IN_CTYPE_DOMAIN(c) isascii(c) #endif +#define to_uchar(c) ((unsigned char)(c)) #if !defined (isspace) && !defined (HAVE_ISSPACE) # define isspace(c) ((c) == ' ' || (c) == '\t' || (c) == '\n' || (c) == '\f') @@ -67,16 +68,16 @@ #undef ISPRINT -#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c)) -#define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) -#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c)) -#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) -#define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (c)) -#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c)) -#define ISPUNCT(c) (IN_CTYPE_DOMAIN (c) && ispunct (c)) -#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (c)) -#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) -#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c)) +#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (to_uchar (c))) +#define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (to_uchar (c))) +#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (to_uchar (c))) +#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (to_uchar (c))) +#define ISCNTRL(c) (IN_CTYPE_DOMAIN (c) && iscntrl (to_uchar (c))) +#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (to_uchar (c))) +#define ISPUNCT(c) (IN_CTYPE_DOMAIN (c) && ispunct (to_uchar (c))) +#define ISSPACE(c) (IN_CTYPE_DOMAIN (c) && isspace (to_uchar (c))) +#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (to_uchar (c))) +#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (to_uchar (c))) #define ISLETTER(c) (ISALPHA(c)) --- include/posixjmp.h 2012-12-23 20:20:50.000000000 -0700 +++ include/posixjmp.h 2015-02-06 17:14:11.031260100 -0700 @@ -27,13 +27,13 @@ #if defined (HAVE_POSIX_SIGSETJMP) # define procenv_t sigjmp_buf -# if !defined (__OPENNT) +# if !defined (__OPENNT) && !defined __CYGWIN__ # undef setjmp # define setjmp(x) sigsetjmp((x), 1) -# define setjmp_nosigs(x) sigsetjmp((x), 0) # undef longjmp # define longjmp(x, n) siglongjmp((x), (n)) # endif /* !__OPENNT */ +# define setjmp_nosigs(x) sigsetjmp((x), 0) #else # define procenv_t jmp_buf # define setjmp_nosigs setjmp --- input.c 2014-02-07 07:13:08.000000000 -0700 +++ input.c 2015-02-06 17:14:11.031260100 -0700 @@ -44,6 +44,10 @@ #include "quit.h" #include "trap.h" +#if __CYGWIN__ +int igncr; +#endif + #if !defined (errno) extern int errno; #endif /* !errno */ @@ -561,6 +565,19 @@ buffered_getchar () { CHECK_TERMSIG; +#if __CYGWIN__ + /* shopt igncr means to discard carriage returns from input stream. + If cr is the only character in the buffer, then recurse to pick + up the next character; otherwise flatten the buffer. */ + if (igncr) + { + int ch; + while ((ch = bufstream_getc (buffers[bash_input.location.buffered_fd])) + == '\r') + ; + return ch; + } +#endif /* __CYGWIN__ */ #if !defined (DJGPP) return (bufstream_getc (buffers[bash_input.location.buffered_fd])); #else --- lib/readline/bind.c 2013-04-06 15:46:38.000000000 -0600 +++ lib/readline/bind.c 2015-02-06 17:14:11.031260100 -0700 @@ -452,7 +452,7 @@ rl_translate_keyseq (seq, array, len) { register int i, c, l, temp; - for (i = l = 0; c = seq[i]; i++) + for (i = l = 0; (c = seq[i]); i++) { if (c == '\\') { @@ -1210,7 +1210,7 @@ _rl_skip_to_delim (string, start, delim) { int i, c, passc; - for (i = start,passc = 0; c = string[i]; i++) + for (i = start,passc = 0; (c = string[i]); i++) { if (passc) { @@ -1297,7 +1297,6 @@ rl_parse_and_bind (string) if (_rl_stricmp (string, "set") == 0) { char *var, *value, *e; - int s; var = string + i; /* Make VAR point to start of variable name. */ @@ -2198,7 +2197,7 @@ rl_function_dumper (print_readably) fprintf (rl_outstream, "\n"); - for (i = 0; name = names[i]; i++) + for (i = 0; (name = names[i]); i++) { rl_command_func_t *function; char **invokers; --- lib/readline/chardefs.h 2011-07-25 19:47:56.000000000 -0600 +++ lib/readline/chardefs.h 2015-02-06 17:14:11.046889800 -0700 @@ -71,6 +71,7 @@ #else # define IN_CTYPE_DOMAIN(c) isascii(c) #endif +#define to_uchar(c) ((unsigned char)(c)) #if !defined (isxdigit) && !defined (HAVE_ISXDIGIT) && !defined (__cplusplus) # define isxdigit(c) (isdigit((c)) || ((c) >= 'a' && (c) <= 'f') || ((c) >= 'A' && (c) <= 'F')) @@ -87,13 +88,13 @@ /* Beware: these only work with single-byte ASCII characters. */ -#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (c)) -#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (c)) -#define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (c)) -#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (c)) -#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (c)) -#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (c)) -#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (c)) +#define ISALNUM(c) (IN_CTYPE_DOMAIN (c) && isalnum (to_uchar (c))) +#define ISALPHA(c) (IN_CTYPE_DOMAIN (c) && isalpha (to_uchar (c))) +#define ISDIGIT(c) (IN_CTYPE_DOMAIN (c) && isdigit (to_uchar (c))) +#define ISLOWER(c) (IN_CTYPE_DOMAIN (c) && islower (to_uchar (c))) +#define ISPRINT(c) (IN_CTYPE_DOMAIN (c) && isprint (to_uchar (c))) +#define ISUPPER(c) (IN_CTYPE_DOMAIN (c) && isupper (to_uchar (c))) +#define ISXDIGIT(c) (IN_CTYPE_DOMAIN (c) && isxdigit (to_uchar (c))) #define _rl_lowercase_p(c) (NON_NEGATIVE(c) && ISLOWER(c)) #define _rl_uppercase_p(c) (NON_NEGATIVE(c) && ISUPPER(c)) --- lib/readline/complete.c 2013-10-14 07:27:10.000000000 -0600 +++ lib/readline/complete.c 2015-02-06 17:14:11.046889800 -0700 @@ -1082,7 +1082,7 @@ _rl_find_completion_word (fp, dp) /* We didn't find an unclosed quoted substring upon which to do completion, so use the word break characters to find the substring on which to complete. */ - while (rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_ANY)) + while ((rl_point = MB_PREVCHAR (rl_line_buffer, rl_point, MB_FIND_ANY))) { scan = rl_line_buffer[rl_point]; @@ -2116,7 +2116,7 @@ rl_completion_matches (text, entry_funct match_list = (char **)xmalloc ((match_list_size + 1) * sizeof (char *)); match_list[1] = (char *)NULL; - while (string = (*entry_function) (text, matches)) + while ((string = (*entry_function) (text, matches))) { if (RL_SIG_RECEIVED ()) { @@ -2190,7 +2190,7 @@ rl_username_completion_function (text, s } #if defined (HAVE_GETPWENT) - while (entry = getpwent ()) + while ((entry = getpwent ())) { /* Null usernames should result in all users as possible completions. */ if (namelen == 0 || (STREQN (username, entry->pw_name, namelen))) @@ -2723,7 +2723,7 @@ rl_menu_complete (count, ignore) static int full_completion = 0; /* set to 1 if menu completion should reinitialize on next call */ static int orig_start, orig_end; static char quote_char; - static int delimiter, cstate; + static int delimiter; /* The first time through, we generate the list of matches and set things up to insert them. */ --- lib/readline/display.c 2015-02-06 17:12:54.793574600 -0700 +++ lib/readline/display.c 2015-02-06 17:14:11.046889800 -0700 @@ -66,7 +66,6 @@ extern char *strchr (), *strrchr (); static void update_line PARAMS((char *, char *, int, int, int, int)); static void space_to_eol PARAMS((int)); static void delete_chars PARAMS((int)); -static void insert_some_chars PARAMS((char *, int, int)); static void open_some_spaces PARAMS((int)); static void cr PARAMS((void)); @@ -1314,7 +1313,7 @@ update_line (old, new, current_line, oma int current_line, omax, nmax, inv_botlin; { register char *ofd, *ols, *oe, *nfd, *nls, *ne; - int temp, lendiff, wsatend, od, nd, twidth, o_cpos; + int temp, lendiff, wsatend, od, nd, o_cpos; int current_invis_chars; int col_lendiff, col_temp; int bytes_to_insert; @@ -2485,6 +2484,7 @@ _rl_clear_screen () #endif /* __DJGPP__ */ } +#if 0 /* Insert COUNT characters from STRING to the output stream at column COL. */ static void insert_some_chars (string, count, col) @@ -2494,6 +2494,7 @@ insert_some_chars (string, count, col) open_some_spaces (col); _rl_output_some_chars (string, count); } +#endif /* Insert COL spaces, keeping the cursor at the same position. We follow the ncurses documentation and use either im/ei with explicit spaces, or IC/ic --- lib/readline/histexpand.c 2013-12-02 07:22:30.000000000 -0700 +++ lib/readline/histexpand.c 2015-02-06 17:14:11.046889800 -0700 @@ -204,7 +204,7 @@ get_history_event (string, caller_index, } /* Only a closing `?' or a newline delimit a substring search string. */ - for (local_index = i; c = string[i]; i++) + for (local_index = i; (c = string[i]); i++) { #if defined (HANDLE_MULTIBYTE) if (MB_CUR_MAX > 1 && rl_byte_oriented == 0) @@ -677,7 +677,7 @@ history_expand_internal (string, start, case 's': { char *new_event; - int delimiter, failed, si, l_temp, ws, we; + int delimiter, failed, si, l_temp, we; if (c == 's') { @@ -776,7 +776,6 @@ history_expand_internal (string, start, { for (; temp[si] && whitespace (temp[si]); si++) ; - ws = si; we = history_tokenize_word (temp, si); } --- lib/readline/histfile.c 2013-07-19 06:17:17.000000000 -0600 +++ lib/readline/histfile.c 2015-02-06 17:14:11.046889800 -0700 @@ -104,7 +104,7 @@ int history_write_timestamps = 0; /* Does S look like the beginning of a history timestamp entry? Placeholder for more extensive tests. */ -#define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char && isdigit ((s)[1]) ) +#define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char && isdigit ((unsigned char) (s)[1]) ) /* Return the string that should be used in the place of this filename. This only matters when you don't specify the --- lib/readline/input.c 2015-02-06 17:12:55.027577800 -0700 +++ lib/readline/input.c 2015-02-06 17:14:11.046889800 -0700 @@ -431,7 +431,7 @@ rl_read_key () else { /* If input is coming from a macro, then use that. */ - if (c = _rl_next_macro_key ()) + if ((c = _rl_next_macro_key ())) return (c); /* If the user has an event function, then call it periodically. */ --- lib/readline/isearch.c 2013-10-14 07:08:40.000000000 -0600 +++ lib/readline/isearch.c 2015-02-06 17:14:11.046889800 -0700 @@ -740,7 +740,7 @@ rl_search_history (direction, invoking_k int direction, invoking_key; { _rl_search_cxt *cxt; /* local for now, but saved globally */ - int c, r; + int r; RL_SETSTATE(RL_STATE_ISEARCH); cxt = _rl_isearch_init (direction); @@ -755,7 +755,7 @@ rl_search_history (direction, invoking_k r = -1; for (;;) { - c = _rl_search_getchar (cxt); + _rl_search_getchar (cxt); /* We might want to handle EOF here (c == 0) */ r = _rl_isearch_dispatch (cxt, cxt->lastc); if (r <= 0) @@ -778,9 +778,9 @@ int _rl_isearch_callback (cxt) _rl_search_cxt *cxt; { - int c, r; + int r; - c = _rl_search_getchar (cxt); + _rl_search_getchar (cxt); /* We might want to handle EOF here */ r = _rl_isearch_dispatch (cxt, cxt->lastc); --- lib/readline/misc.c 2015-02-06 17:12:55.230384200 -0700 +++ lib/readline/misc.c 2015-02-06 17:14:11.046889800 -0700 @@ -455,7 +455,7 @@ _rl_revert_all_lines () entry = (hpos == history_length) ? previous_history () : current_history (); while (entry) { - if (ul = (UNDO_LIST *)entry->data) + if ((ul = (UNDO_LIST *)entry->data)) { if (ul == saved_undo_list) saved_undo_list = 0; @@ -502,7 +502,7 @@ rl_clear_history () for (i = 0; i < history_length; i++) { hent = hlist[i]; - if (ul = (UNDO_LIST *)hent->data) + if ((ul = (UNDO_LIST *)hent->data)) { if (ul == saved_undo_list) saved_undo_list = 0; --- lib/readline/nls.c 2013-03-09 12:51:10.000000000 -0700 +++ lib/readline/nls.c 2015-02-06 17:14:11.046889800 -0700 @@ -80,7 +80,7 @@ static char *legal_lang_values[] = static char *normalize_codeset PARAMS((char *)); #endif /* !HAVE_SETLOCALE */ -static char *find_codeset PARAMS((char *, size_t *)); +static char *find_codeset PARAMS((char *, size_t *)) __attribute__ ((__unused__)); static char *_rl_get_locale_var PARAMS((const char *)); @@ -104,12 +104,13 @@ utf8locale (lspec) char *lspec; { char *cp; - size_t len; #if HAVE_LANGINFO_CODESET cp = nl_langinfo (CODESET); return (STREQ (cp, "UTF-8") || STREQ (cp, "utf8")); #else + size_t len; + cp = find_codeset (lspec, &len); if (cp == 0 || len < 4 || len > 5) --- lib/readline/parens.c 2009-04-19 11:12:06.000000000 -0600 +++ lib/readline/parens.c 2015-02-06 17:14:11.046889800 -0700 @@ -106,7 +106,7 @@ rl_insert_close (count, invoking_key) else { #if defined (HAVE_SELECT) - int orig_point, match_point, ready; + int orig_point, match_point; struct timeval timer; fd_set readfds; @@ -126,7 +126,7 @@ rl_insert_close (count, invoking_key) orig_point = rl_point; rl_point = match_point; (*rl_redisplay_function) (); - ready = select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); + select (1, &readfds, (fd_set *)NULL, (fd_set *)NULL, &timer); rl_point = orig_point; #else /* !HAVE_SELECT */ _rl_insert_char (count, invoking_key); --- lib/readline/posixjmp.h 2012-12-23 20:20:50.000000000 -0700 +++ lib/readline/posixjmp.h 2015-02-06 17:14:11.046889800 -0700 @@ -27,13 +27,13 @@ #if defined (HAVE_POSIX_SIGSETJMP) # define procenv_t sigjmp_buf -# if !defined (__OPENNT) +# if !defined (__OPENNT) && !defined __CYGWIN__ # undef setjmp # define setjmp(x) sigsetjmp((x), 1) -# define setjmp_nosigs(x) sigsetjmp((x), 0) # undef longjmp # define longjmp(x, n) siglongjmp((x), (n)) # endif /* !__OPENNT */ +# define setjmp_nosigs(x) sigsetjmp((x), 0) #else # define procenv_t jmp_buf # define setjmp_nosigs setjmp --- lib/readline/readline.c 2015-02-06 17:12:54.310964200 -0700 +++ lib/readline/readline.c 2015-02-06 17:14:11.046889800 -0700 @@ -95,7 +95,7 @@ static void bind_arrow_keys_internal PAR static void bind_arrow_keys PARAMS((void)); static void readline_default_bindings PARAMS((void)); -static void reset_default_bindings PARAMS((void)); +//static void reset_default_bindings PARAMS((void)); static int _rl_subseq_result PARAMS((int, Keymap, int, int)); static int _rl_subseq_getchar PARAMS((int)); @@ -522,7 +522,7 @@ readline_internal_char () readline_internal_charloop () #endif { - static int lastc, eof_found; + static int lastc, eof_found __attribute__((unused)); int c, code, lk; lastc = -1; @@ -1204,6 +1204,7 @@ readline_default_bindings () rl_tty_set_default_bindings (_rl_keymap); } +#if 0 /* Reset the default bindings for the terminal special characters we're interested in back to rl_insert and read the new ones. */ static void @@ -1215,6 +1216,7 @@ reset_default_bindings () rl_tty_set_default_bindings (_rl_keymap); } } +#endif /* Bind some common arrow key sequences in MAP. */ static void --- lib/readline/rltty.c 2013-08-25 14:57:05.000000000 -0600 +++ lib/readline/rltty.c 2015-02-06 17:14:11.062454900 -0700 @@ -30,6 +30,7 @@ #include #include #include +#include #if defined (HAVE_UNISTD_H) # include --- lib/readline/shell.c 2013-03-13 08:17:00.000000000 -0600 +++ lib/readline/shell.c 2015-02-06 17:14:11.062454900 -0700 @@ -123,8 +123,10 @@ sh_single_quote (string) /* Set the environment variables LINES and COLUMNS to lines and cols, respectively. */ static char setenv_buf[INT_STRLEN_BOUND (int) + 1]; +# if !defined (HAVE_SETENV) && defined (HAVE_PUTENV) static char putenv_buf1[INT_STRLEN_BOUND (int) + 6 + 1]; /* sizeof("LINES=") == 6 */ static char putenv_buf2[INT_STRLEN_BOUND (int) + 8 + 1]; /* sizeof("COLUMNS=") == 8 */ +# endif void sh_set_lines_and_columns (lines, cols) --- lib/readline/signals.c 2014-01-10 13:06:48.000000000 -0700 +++ lib/readline/signals.c 2015-02-06 17:14:11.062454900 -0700 @@ -576,7 +576,6 @@ rl_free_line_state () /* **************************************************************** */ #if defined (HAVE_POSIX_SIGNALS) -static sigset_t sigint_set, sigint_oset; static sigset_t sigwinch_set, sigwinch_oset; #else /* !HAVE_POSIX_SIGNALS */ # if defined (HAVE_BSD_SIGNALS) --- lib/readline/terminal.c 2013-09-18 07:12:01.000000000 -0600 +++ lib/readline/terminal.c 2015-02-06 17:14:11.062454900 -0700 @@ -31,6 +31,7 @@ #if defined (HAVE_SYS_FILE_H) # include #endif /* HAVE_SYS_FILE_H */ +#include #if defined (HAVE_UNISTD_H) # include --- lib/readline/text.c 2013-10-14 07:25:05.000000000 -0600 +++ lib/readline/text.c 2015-02-06 17:14:11.062454900 -0700 @@ -859,11 +859,10 @@ _rl_overwrite_char (count, c) int i; #if defined (HANDLE_MULTIBYTE) char mbkey[MB_LEN_MAX]; - int k; /* Read an entire multibyte character sequence to insert COUNT times. */ if (count > 0 && MB_CUR_MAX > 1 && rl_byte_oriented == 0) - k = _rl_read_mbstring (c, mbkey, MB_LEN_MAX); + _rl_read_mbstring (c, mbkey, MB_LEN_MAX); #endif rl_begin_undo_group (); --- lib/readline/tilde.c 2010-07-25 15:42:13.000000000 -0600 +++ lib/readline/tilde.c 2015-02-06 17:14:11.062454900 -0700 @@ -196,7 +196,7 @@ tilde_expand (string) int result_size, result_index; result_index = result_size = 0; - if (result = strchr (string, '~')) + if ((result = strchr (string, '~'))) result = (char *)xmalloc (result_size = (strlen (string) + 16)); else result = (char *)xmalloc (result_size = (strlen (string) + 1)); --- lib/readline/undo.c 2014-02-02 13:47:46.000000000 -0700 +++ lib/readline/undo.c 2015-02-06 17:14:11.062454900 -0700 @@ -124,7 +124,7 @@ _rl_free_undo_list (ul) void rl_free_undo_list () { - UNDO_LIST *release, *orig_list; + UNDO_LIST *orig_list; orig_list = rl_undo_list; _rl_free_undo_list (rl_undo_list); --- lib/readline/vi_mode.c 2012-09-01 16:55:30.000000000 -0600 +++ lib/readline/vi_mode.c 2015-02-06 17:14:11.062454900 -0700 @@ -1089,7 +1089,7 @@ static int rl_domove_motion_callback (m) _rl_vimotion_cxt *m; { - int c, save, r; + int c, r; int old_end; _rl_vi_last_motion = c = m->motion; @@ -1257,7 +1257,6 @@ int rl_vi_domove (x, ignore) int x, *ignore; { - int r; _rl_vimotion_cxt *m; m = _rl_vimvcxt; --- lib/sh/pathphys.c 2013-05-28 13:33:58.000000000 -0600 +++ lib/sh/pathphys.c 2015-02-06 17:14:11.062454900 -0700 @@ -35,6 +35,7 @@ #include #include #include +#include #include "shell.h" @@ -76,6 +77,10 @@ sh_physpath (path, flags) char *path; int flags; { +#if __CYGWIN__ + /* realpath does this correctly without all the hassle */ + return realpath (path, NULL); +#else char tbuf[PATH_MAX+1], linkbuf[PATH_MAX+1]; char *result, *p, *q, *qsave, *qbase, *workpath; int double_slash_path, linklen, nlink; @@ -214,11 +219,7 @@ error: { q = result; /* Duplicating some code here... */ -#if defined (__CYGWIN__) - qbase = (ISALPHA((unsigned char)workpath[0]) && workpath[1] == ':') ? workpath + 3 : workpath + 1; -#else qbase = workpath + 1; -#endif double_slash_path = DOUBLE_SLASH (workpath); qbase += double_slash_path; @@ -249,6 +250,7 @@ error: } return (result); +#endif /* ! __CYGWIN__ */ } char * --- lib/sh/tmpfile.c 2013-12-18 15:50:13.000000000 -0700 +++ lib/sh/tmpfile.c 2015-02-06 17:14:11.062454900 -0700 @@ -96,7 +96,7 @@ get_tmpdir (flags) if (tdir && (file_iswdir (tdir) == 0 || strlen (tdir) > PATH_MAX)) tdir = 0; - if (tdir == 0) + if (tdir == 0 || !file_iswdir (tdir)) tdir = get_sys_tmpdir (); #if defined (HAVE_PATHCONF) && defined (_PC_NAME_MAX) @@ -118,14 +118,15 @@ sh_mktmpname (nameroot, flags) struct stat sb; int r, tdlen; - filename = (char *)xmalloc (PATH_MAX + 1); + filename = NULL; tdir = get_tmpdir (flags); tdlen = strlen (tdir); lroot = nameroot ? nameroot : DEFAULT_NAMEROOT; #ifdef USE_MKTEMP - sprintf (filename, "%s/%s.XXXXXX", tdir, lroot); + if (asprintf (&filename, "%s/%s.XXXXXX", tdir, lroot) < 0) + return NULL; if (mktemp (filename) == 0) { free (filename); @@ -138,7 +139,9 @@ sh_mktmpname (nameroot, flags) (unsigned long) time ((time_t *)0) ^ (unsigned long) dollar_dollar_pid ^ (unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++); - sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum); + free (filename); + if (asprintf (&filename, "%s/%s-%lu", tdir, lroot, filenum) < 0) + return NULL; if (tmpnamelen > 0 && tmpnamelen < 32) filename[tdlen + 1 + tmpnamelen] = '\0'; # ifdef HAVE_LSTAT @@ -163,14 +166,19 @@ sh_mktmpfd (nameroot, flags, namep) char *filename, *tdir, *lroot; int fd, tdlen; - filename = (char *)xmalloc (PATH_MAX + 1); + filename = NULL; tdir = get_tmpdir (flags); tdlen = strlen (tdir); lroot = nameroot ? nameroot : DEFAULT_NAMEROOT; #ifdef USE_MKSTEMP - sprintf (filename, "%s/%s.XXXXXX", tdir, lroot); + if (asprintf (&filename, "%s/%s.XXXXXX", tdir, lroot) < 0) + { + if (namep) + *namep = NULL; + return -1; + } fd = mkstemp (filename); if (fd < 0 || namep == 0) { @@ -187,7 +195,13 @@ sh_mktmpfd (nameroot, flags, namep) (unsigned long) time ((time_t *)0) ^ (unsigned long) dollar_dollar_pid ^ (unsigned long) ((flags & MT_USERANDOM) ? random () : ntmpfiles++); - sprintf (filename, "%s/%s-%lu", tdir, lroot, filenum); + free (filename); + if (asprintf (&filename, "%s/%s-%lu", tdir, lroot, filenum) < 0) + { + if (namep) + *namep = NULL; + return -1; + } if (tmpnamelen > 0 && tmpnamelen < 32) filename[tdlen + 1 + tmpnamelen] = '\0'; fd = open (filename, BASEOPENFLAGS | ((flags & MT_READWRITE) ? O_RDWR : O_WRONLY), 0600); --- mksyntax.c 2012-07-29 17:48:38.000000000 -0600 +++ mksyntax.c 2015-02-06 17:14:11.062454900 -0700 @@ -29,13 +29,13 @@ #ifdef HAVE_UNISTD_H # include +#else +extern int optind; +extern char *optarg; #endif #include "syntax.h" -extern int optind; -extern char *optarg; - #ifndef errno extern int errno; #endif --- parse.y 2015-02-06 17:12:55.682776800 -0700 +++ parse.y 2015-02-06 17:14:11.062454900 -0700 @@ -1531,14 +1531,20 @@ yy_string_get () string = bash_input.location.string; /* If the string doesn't exist, or is empty, EOF found. */ - if (string && *string) + while (string && *string) { c = *string++; bash_input.location.string = string; +#if __CYGWIN__ + { + extern int igncr; + if (igncr && c == '\r') + continue; + } +#endif return (c); } - else - return (EOF); + return (EOF); } static int @@ -2305,7 +2311,7 @@ shell_getc (remove_quoted_newline) if (n <= 2) /* we have to save 1 for the newline added below */ { if (truncating == 0) - internal_warning("shell_getc: shell_input_line_size (%zu) exceeds SIZE_MAX (%llu): line truncated", shell_input_line_size, SIZE_MAX); + internal_warning("shell_getc: shell_input_line_size (%zu) exceeds SIZE_MAX (%zu): line truncated", shell_input_line_size, SIZE_MAX); shell_input_line[i] = '\0'; truncating = 1; } @@ -3582,7 +3588,6 @@ parse_comsub (qc, open, close, lenp, fla while (count) { -comsub_readchar: ch = shell_getc (qc != '\'' && (tflags & (LEX_INCOMMENT|LEX_PASSNEXT)) == 0); if (ch == EOF) --- pathexp.h 2009-01-04 12:32:40.000000000 -0700 +++ pathexp.h 2015-02-06 17:14:11.062454900 -0700 @@ -86,7 +86,7 @@ struct ign { typedef int sh_iv_item_func_t __P((struct ign *)); struct ignorevar { - char *varname; /* FIGNORE or GLOBIGNORE */ + char *varname; /* FIGNORE or GLOBIGNORE or EXECIGNORE */ struct ign *ignores; /* Store the ignore strings here */ int num_ignores; /* How many are there? */ char *last_ignoreval; /* Last value of variable - cached for speed */ --- redir.c 2013-10-14 07:19:59.000000000 -0600 +++ redir.c 2015-02-06 17:14:11.078059300 -0700 @@ -156,7 +156,6 @@ redirection_error (temp, error) #endif else if (expandable_redirection_filename (temp)) { -expandable_filename: oflags = temp->redirectee.filename->flags; if (posixly_correct && interactive_shell == 0) temp->redirectee.filename->flags |= W_NOGLOB; --- subst.c 2015-02-06 17:12:55.370841100 -0700 +++ subst.c 2015-02-06 17:14:11.078059300 -0700 @@ -41,6 +41,7 @@ #include "posixstat.h" #include "bashintl.h" +#define NEED_SH_SETLINEBUF_DECL /* used in externs.h */ #include "shell.h" #include "parser.h" #include "flags.h" @@ -5268,6 +5269,13 @@ read_comsub (fd, quoted, rflag) #endif continue; } +#if __CYGWIN__ + { + extern int igncr; + if (igncr && c == '\r') + continue; + } +#endif /* __CYGWIN__ */ /* Add the character to ISTRING, possibly after resizing it. */ RESIZE_MALLOCED_BUFFER (istring, istring_index, 2, istring_size, DEFAULT_ARRAY_SIZE); @@ -5385,6 +5393,28 @@ command_substitute (string, quoted) goto error_exit; } +#if __CYGWIN__ + /* Passing a pipe through std fds can cause hangs when talking to a + non-cygwin child. Move it. */ + if (fildes[0] < 3) + { + int fd = fcntl (fildes[0], F_DUPFD, 3); + close (fildes[0]); + fildes[0] = fd; + } + if (fildes[1] < 3) + { + int fd = fcntl (fildes[1], F_DUPFD, 3); + close (fildes[1]); + fildes[1] = fd; + } + if (fildes[0] < 0 || fildes[1] < 0) + { + sys_error (_("cannot make pipe for command substitution")); + goto error_exit; + } +#endif /* __CYGWIN__ */ + old_pid = last_made_pid; #if defined (JOB_CONTROL) old_pipeline_pgrp = pipeline_pgrp; --- support/bashversion.c 2008-09-09 07:31:53.000000000 -0600 +++ support/bashversion.c 2015-02-06 17:14:11.078059300 -0700 @@ -26,6 +26,9 @@ #if defined (HAVE_UNISTD_H) # include +#else +extern int optind; +extern char *optarg; #endif #include "bashansi.h" @@ -41,9 +44,6 @@ #define LFLAG 0x0020 #define XFLAG 0x0040 -extern int optind; -extern char *optarg; - extern char *dist_version; extern int patch_level; @@ -65,7 +65,7 @@ main (argc, argv) char **argv; { int opt, oflags; - char dv[128], *rv; + char dv[128], *rv = NULL; if (progname = strrchr (argv[0], '/')) progname++; --- support/mkversion.sh 2008-08-13 06:25:57.000000000 -0600 +++ support/mkversion.sh 2015-02-06 17:14:11.078059300 -0700 @@ -29,7 +29,7 @@ source_dir="." while [ $# -gt 0 ]; do case "$1" in -o) shift; OUTFILE=$1; shift ;; - -b) shift; inc_build=yes ;; + -b) shift; ;;# inc_build=yes ;; # hacked out for cygport -s) shift; rel_status=$1; shift ;; -p) shift; patch_level=$1; shift ;; -d) shift; dist_version=$1; shift ;; --- variables.c 2015-02-06 17:12:55.729569600 -0700 +++ variables.c 2015-02-06 17:14:11.078059300 -0700 @@ -2526,9 +2526,9 @@ bind_variable_internal (name, value, tab newname = 0; #if defined (ARRAY_VARS) - if ((aflags & ASS_FROMREF) && (hflags & HASH_NOSRCH) == 0 && valid_array_reference (name)) + if ((aflags & ASS_FROMREF) && (hflags & HASH_NOSRCH) == 0 && valid_array_reference ((char *)name)) { - newname = array_variable_name (name, &subp, &sublen); + newname = array_variable_name ((char*)name, &subp, &sublen); if (newname == 0) return (SHELL_VAR *)NULL; /* XXX */ entry = hash_lookup (newname, table); @@ -2573,13 +2573,13 @@ bind_variable_internal (name, value, tab entry = make_new_array_variable (newname); /* indexed array by default */ if (entry == 0) return entry; - ind = array_expand_index (name, subp, sublen); + ind = array_expand_index (entry, subp, sublen); bind_array_element (entry, ind, value, aflags); } #endif else if (entry == 0) { - entry = make_new_variable (name, table); + entry = make_new_variable ((char*)name, table); var_setvalue (entry, make_variable_value (entry, value, 0)); /* XXX */ } else if (entry->assign_func) /* array vars have assign functions now */ @@ -4679,6 +4679,8 @@ static struct name_and_function special_ { "COMP_WORDBREAKS", sv_comp_wordbreaks }, #endif + { "EXECIGNORE", sv_execignore }, + { "FUNCNEST", sv_funcnest }, { "GLOBIGNORE", sv_globignore }, @@ -4877,6 +4879,13 @@ sv_globignore (name) setup_glob_ignore (name); } +/* What to do when EXECIGNORE changes. */ +void +sv_execignore (char *name) +{ + setup_exec_ignore (name); +} + #if defined (READLINE) void sv_comp_wordbreaks (name) @@ -4950,7 +4959,7 @@ sv_winsize (name) /* Update the value of HOME in the export environment so tilde expansion will work on cygwin. */ #if defined (__CYGWIN__) -sv_home (name) +void sv_home (name) char *name; { array_needs_making = 1; --- variables.h 2014-01-08 13:33:29.000000000 -0700 +++ variables.h 2015-02-06 17:14:11.078059300 -0700 @@ -372,6 +372,7 @@ extern void sv_ifs __P((char *)); extern void sv_path __P((char *)); extern void sv_mail __P((char *)); extern void sv_funcnest __P((char *)); +extern void sv_execignore __P((char *)); extern void sv_globignore __P((char *)); extern void sv_ignoreeof __P((char *)); extern void sv_strict_posix __P((char *));