755 lines
25 KiB
Diff
755 lines
25 KiB
Diff
diff -Naur a/bashline.c b/bashline.c
|
|
--- a/bashline.c 2014-02-10 04:56:58.000000000 +0400
|
|
+++ b/bashline.c 2014-03-13 16:36:05.375000000 +0400
|
|
@@ -263,6 +263,11 @@
|
|
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;
|
|
|
|
@@ -490,11 +495,12 @@
|
|
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);
|
|
@@ -513,7 +519,8 @@
|
|
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);
|
|
@@ -536,7 +543,8 @@
|
|
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. */
|
|
@@ -2105,9 +2113,33 @@
|
|
else
|
|
#endif
|
|
cval = val;
|
|
+#if defined(__CYGWIN__)
|
|
+ /* executable_or_directory will do the right thing on //server,
|
|
+ but calling stat("//server") is an order of magnitude slower
|
|
+ than noting that readdir("//") only returns directories. */
|
|
+ if (match && (searching_path ? executable_file (val)
|
|
+ : ((val[0] == '/' && val[1] == '/'
|
|
+ && ! strchr (&val[2], '/'))
|
|
+ || executable_or_directory (val))))
|
|
+#endif
|
|
|
|
if (match && executable_completion ((searching_path ? val : cval), searching_path))
|
|
{
|
|
+#if __CYGWIN__
|
|
+ if (completion_strip_exe)
|
|
+ {
|
|
+ int 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);
|
|
@@ -2843,6 +2875,17 @@
|
|
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);
|
|
|
|
diff -Naur a/builtins/set.def b/builtins/set.def
|
|
--- a/builtins/set.def 2013-04-19 15:20:34.000000000 +0400
|
|
+++ b/builtins/set.def 2014-03-13 16:36:05.375000000 +0400
|
|
@@ -56,6 +56,13 @@
|
|
#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 @@
|
|
#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 @@
|
|
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 @@
|
|
{ "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 @@
|
|
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 @@
|
|
{
|
|
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 @@
|
|
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);
|
|
}
|
|
}
|
|
diff -Naur a/builtins/shopt.def b/builtins/shopt.def
|
|
--- a/builtins/shopt.def 2013-02-27 18:43:20.000000000 +0400
|
|
+++ b/builtins/shopt.def 2014-03-13 16:36:05.375000000 +0400
|
|
@@ -91,6 +91,10 @@
|
|
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 +165,9 @@
|
|
{ "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 },
|
|
diff -Naur a/config-top.h b/config-top.h
|
|
--- a/config-top.h 2012-08-19 04:51:30.000000000 +0400
|
|
+++ b/config-top.h 2014-03-13 16:36:05.375000000 +0400
|
|
@@ -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). */
|
|
diff -Naur a/doc/bash.1 b/doc/bash.1
|
|
--- a/doc/bash.1 2014-02-06 18:03:52.000000000 +0400
|
|
+++ b/doc/bash.1 2014-03-13 16:36:05.390600000 +0400
|
|
@@ -1658,6 +1658,14 @@
|
|
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.
|
|
@@ -9332,6 +9340,10 @@
|
|
attempts spelling correction on directory names during word completion
|
|
if the directory name initially supplied does not exist.
|
|
.TP 8
|
|
+.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
|
|
If set,
|
|
.B bash
|
|
diff -Naur a/doc/bashref.texi b/doc/bashref.texi
|
|
--- a/doc/bashref.texi 2014-02-22 22:20:36.000000000 +0400
|
|
+++ b/doc/bashref.texi 2014-03-13 16:36:05.390600000 +0400
|
|
@@ -4999,6 +4999,10 @@
|
|
buffer.
|
|
If not set, Bash attempts to preserve what the user typed.
|
|
|
|
+@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 dirspell
|
|
If set, Bash
|
|
attempts spelling correction on directory names during word completion
|
|
@@ -5578,6 +5582,14 @@
|
|
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.
|
|
diff -Naur a/doc/builtins.1 b/doc/builtins.1
|
|
--- a/doc/builtins.1 2012-02-21 23:32:05.000000000 +0400
|
|
+++ b/doc/builtins.1 2014-03-13 16:36:05.390600000 +0400
|
|
@@ -19,6 +19,6 @@
|
|
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)
|
|
diff -Naur a/doc/Makefile.in b/doc/Makefile.in
|
|
--- a/doc/Makefile.in 2013-10-31 00:18:12.000000000 +0400
|
|
+++ b/doc/Makefile.in 2014-03-13 16:36:05.390600000 +0400
|
|
@@ -176,7 +176,7 @@
|
|
$(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_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:-/tmp}/builtins.1
|
|
+ -$(INSTALL_DATA) $${TMPDIR:-/tmp}/builtins.1 $(DESTDIR)$(man1dir)/bash_builtins${man1ext}
|
|
+ -$(RM) $${TMPDIR:-/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
|
|
diff -Naur a/execute_cmd.c b/execute_cmd.c
|
|
--- a/execute_cmd.c 2014-01-31 19:54:52.000000000 +0400
|
|
+++ b/execute_cmd.c 2014-03-13 16:36:05.406200000 +0400
|
|
@@ -5280,6 +5280,13 @@
|
|
internal_error (_("%s: cannot execute binary file: %s"), command, strerror (i));
|
|
return (EX_BINARY_FILE);
|
|
}
|
|
+#if __CYGWIN__
|
|
+ extern int sh_setlinebuf (FILE *);
|
|
+ /* Let stdio know that fd may have changed from text to binary. */
|
|
+ freopen (NULL, "w", stdout);
|
|
+ /* Bash builtins (foolishly) rely on line-buffering. */
|
|
+ sh_setlinebuf (stdout);
|
|
+#endif /* __CYGWIN__ */
|
|
}
|
|
|
|
/* We have committed to attempting to execute the contents of this file
|
|
diff -Naur a/findcmd.c b/findcmd.c
|
|
--- a/findcmd.c 2012-10-15 15:45:04.000000000 +0400
|
|
+++ b/findcmd.c 2014-03-13 16:36:05.406200000 +0400
|
|
@@ -48,6 +48,8 @@
|
|
extern int errno;
|
|
#endif
|
|
|
|
+#include <glob/strmatch.h>
|
|
+
|
|
extern int posixly_correct;
|
|
extern int last_command_exit_value;
|
|
|
|
@@ -77,6 +79,38 @@
|
|
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 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;
|
|
diff -Naur a/findcmd.h b/findcmd.h
|
|
--- a/findcmd.h 2012-01-15 03:56:25.000000000 +0400
|
|
+++ b/findcmd.h 2014-03-13 16:36:05.406200000 +0400
|
|
@@ -31,5 +31,6 @@
|
|
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_ */
|
|
diff -Naur a/input.c b/input.c
|
|
--- a/input.c 2014-02-07 18:13:08.000000000 +0400
|
|
+++ b/input.c 2014-03-13 16:36:05.406200000 +0400
|
|
@@ -44,6 +44,10 @@
|
|
#include "quit.h"
|
|
#include "trap.h"
|
|
|
|
+#if __CYGWIN__
|
|
+int igncr;
|
|
+#endif /* __CYGWIN__ */
|
|
+
|
|
#if !defined (errno)
|
|
extern int errno;
|
|
#endif /* !errno */
|
|
@@ -561,6 +565,19 @@
|
|
{
|
|
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
|
|
diff -Naur a/lib/sh/pathcanon.c b/lib/sh/pathcanon.c
|
|
--- a/lib/sh/pathcanon.c 2012-07-30 03:55:01.000000000 +0400
|
|
+++ b/lib/sh/pathcanon.c 2014-03-13 16:36:05.421800000 +0400
|
|
@@ -194,6 +194,8 @@
|
|
*q++ = DIRSEP;
|
|
while (*p && (ISDIRSEP(*p) == 0))
|
|
*q++ = *p++;
|
|
+ }
|
|
+ }
|
|
/* Check here for a valid directory with _path_isdir. */
|
|
if (flags & PATH_CHECKEXISTS)
|
|
{
|
|
@@ -211,8 +213,7 @@
|
|
}
|
|
*q = c;
|
|
}
|
|
- }
|
|
- }
|
|
+
|
|
|
|
/* Empty string is really ``.'' or `/', depending on what we started with. */
|
|
if (q == result)
|
|
diff -Naur a/lib/sh/pathphys.c b/lib/sh/pathphys.c
|
|
--- a/lib/sh/pathphys.c 2013-05-28 23:33:58.000000000 +0400
|
|
+++ b/lib/sh/pathphys.c 2014-03-13 16:36:05.421800000 +0400
|
|
@@ -35,6 +35,7 @@
|
|
#include <stdio.h>
|
|
#include <chartypes.h>
|
|
#include <errno.h>
|
|
+#include <stdlib.h>
|
|
|
|
#include "shell.h"
|
|
|
|
@@ -76,6 +77,10 @@
|
|
char *path;
|
|
int flags;
|
|
{
|
|
+#if __CYGWIN__
|
|
+ /* realpath does this right 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;
|
|
@@ -249,6 +254,7 @@
|
|
}
|
|
|
|
return (result);
|
|
+#endif /* !__CYGWIN__ */
|
|
}
|
|
|
|
char *
|
|
diff -Naur a/lib/sh/tmpfile.c b/lib/sh/tmpfile.c
|
|
--- a/lib/sh/tmpfile.c 2013-12-19 02:50:13.000000000 +0400
|
|
+++ b/lib/sh/tmpfile.c 2014-03-13 16:36:05.421800000 +0400
|
|
@@ -96,7 +96,7 @@
|
|
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 @@
|
|
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 @@
|
|
(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 @@
|
|
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 @@
|
|
(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);
|
|
diff -Naur a/parse.y b/parse.y
|
|
--- a/parse.y 2014-02-11 18:42:10.000000000 +0400
|
|
+++ b/parse.y 2014-03-13 16:36:05.437400000 +0400
|
|
@@ -1526,14 +1526,20 @@
|
|
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 /* __CYGWIN__ */
|
|
return (c);
|
|
}
|
|
- else
|
|
- return (EOF);
|
|
+ return (EOF);
|
|
}
|
|
|
|
static int
|
|
diff -Naur a/pathexp.h b/pathexp.h
|
|
--- a/pathexp.h 2009-01-04 22:32:40.000000000 +0300
|
|
+++ b/pathexp.h 2014-03-13 16:36:05.437400000 +0400
|
|
@@ -86,7 +86,7 @@
|
|
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 */
|
|
diff -Naur a/shell.c b/shell.c
|
|
--- a/shell.c 2014-01-14 17:04:32.000000000 +0400
|
|
+++ b/shell.c 2014-03-13 16:36:05.437400000 +0400
|
|
@@ -336,7 +336,10 @@
|
|
struct stat sb;
|
|
|
|
if (stat ("/tmp", &sb) < 0)
|
|
- internal_warning (_("could not find /tmp, please create!"));
|
|
+ {
|
|
+ if (mkdir ("/tmp", S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX) != 0)
|
|
+ internal_warning (_("could not find /tmp, please create!"));
|
|
+ }
|
|
else
|
|
{
|
|
if (S_ISDIR (sb.st_mode) == 0)
|
|
diff -Naur a/subst.c b/subst.c
|
|
--- a/subst.c 2014-01-24 01:26:37.000000000 +0400
|
|
+++ b/subst.c 2014-03-13 16:36:05.453000000 +0400
|
|
@@ -5260,7 +5260,13 @@
|
|
#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);
|
|
|
|
@@ -5376,6 +5382,27 @@
|
|
sys_error (_("cannot make pipe for command substitution"));
|
|
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)
|
|
diff -Naur a/variables.c b/variables.c
|
|
--- a/variables.c 2014-02-14 20:55:12.000000000 +0400
|
|
+++ b/variables.c 2014-03-13 16:36:05.453000000 +0400
|
|
@@ -4622,6 +4622,8 @@
|
|
|
|
{ "FUNCNEST", sv_funcnest },
|
|
|
|
+ { "EXECIGNORE", sv_execignore },
|
|
+
|
|
{ "GLOBIGNORE", sv_globignore },
|
|
|
|
#if defined (HISTORY)
|
|
@@ -4818,6 +4820,13 @@
|
|
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)
|
|
diff -Naur a/variables.h b/variables.h
|
|
--- a/variables.h 2014-01-09 00:33:29.000000000 +0400
|
|
+++ b/variables.h 2014-03-13 16:36:05.468600000 +0400
|
|
@@ -373,6 +373,7 @@
|
|
extern void sv_mail __P((char *));
|
|
extern void sv_funcnest __P((char *));
|
|
extern void sv_globignore __P((char *));
|
|
+extern void sv_execignore __P((char *));
|
|
extern void sv_ignoreeof __P((char *));
|
|
extern void sv_strict_posix __P((char *));
|
|
extern void sv_optind __P((char *));
|