summaryrefslogtreecommitdiffstats
path: root/patches/bash-4.3.30/0003-Bash-4.3-patch-33.patch
blob: cda1797354c7b70b431ebfb37be86c635264e7d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
From: Chet Ramey <chet.ramey@case.edu>
Date: Thu, 15 Jan 2015 10:21:08 -0500
Subject: [PATCH] Bash-4.3 patch 33

---
 bashline.c        |  6 ++++--
 builtins/common.h |  4 ++++
 builtins/read.def | 31 ++++++++++++++++++++++++++++---
 patchlevel.h      |  2 +-
 shell.c           |  9 +++++++++
 sig.c             |  6 ++++--
 6 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/bashline.c b/bashline.c
index 77ca033f2cc8..c87415171a4a 100644
--- a/bashline.c
+++ b/bashline.c
@@ -202,6 +202,7 @@ extern int current_command_line_count, saved_command_line_count;
 extern int last_command_exit_value;
 extern int array_needs_making;
 extern int posixly_correct, no_symbolic_links;
+extern int sigalrm_seen;
 extern char *current_prompt_string, *ps1_prompt;
 extern STRING_INT_ALIST word_token_alist[];
 extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
@@ -4208,8 +4209,9 @@ bash_event_hook ()
 {
   /* If we're going to longjmp to top_level, make sure we clean up readline.
      check_signals will call QUIT, which will eventually longjmp to top_level,
-     calling run_interrupt_trap along the way. */
-  if (interrupt_state)
+     calling run_interrupt_trap along the way.  The check for sigalrm_seen is
+     to clean up the read builtin's state. */
+  if (terminating_signal || interrupt_state || sigalrm_seen)
     rl_cleanup_after_signal ();
   bashline_reset_event_hook ();
   check_signals_and_traps ();	/* XXX */
diff --git a/builtins/common.h b/builtins/common.h
index cae16b10fb65..a1298cb9c84a 100644
--- a/builtins/common.h
+++ b/builtins/common.h
@@ -122,6 +122,10 @@ extern void bash_logout __P((void));
 /* Functions from getopts.def */
 extern void getopts_reset __P((int));
 
+/* Functions from read.def */
+extern void read_tty_cleanup __P((void));
+extern int read_tty_modified __P((void));
+
 /* Functions from set.def */
 extern int minus_o_option_value __P((char *));
 extern void list_minus_o_opts __P((int, int));
diff --git a/builtins/read.def b/builtins/read.def
index 43971544d081..56c23010bbe8 100644
--- a/builtins/read.def
+++ b/builtins/read.def
@@ -140,10 +140,12 @@ static void reset_alarm __P((void));
 procenv_t alrmbuf;
 int sigalrm_seen;
 
-static int reading;
+static int reading, tty_modified;
 static SigHandler *old_alrm;
 static unsigned char delim;
 
+static struct ttsave termsave;
+
 /* In all cases, SIGALRM just sets a flag that we check periodically.  This
    avoids problems with the semi-tricky stuff we do with the xfree of
    input_string at the top of the unwind-protect list (see below). */
@@ -188,7 +190,6 @@ read_builtin (list)
   struct stat tsb;
   SHELL_VAR *var;
   TTYSTRUCT ttattrs, ttset;
-  struct ttsave termsave;
 #if defined (ARRAY_VARS)
   WORD_LIST *alist;
 #endif
@@ -221,7 +222,7 @@ read_builtin (list)
   USE_VAR(ps2);
   USE_VAR(lastsig);
 
-  sigalrm_seen = reading = 0;
+  sigalrm_seen = reading = tty_modified = 0;
 
   i = 0;		/* Index into the string that we are reading. */
   raw = edit = 0;	/* Not reading raw input by default. */
@@ -438,6 +439,8 @@ read_builtin (list)
 	  retval = 128+SIGALRM;
 	  goto assign_vars;
 	}
+      if (interactive_shell == 0)
+	initialize_terminating_signals ();
       old_alrm = set_signal_handler (SIGALRM, sigalrm);
       add_unwind_protect (reset_alarm, (char *)NULL);
 #if defined (READLINE)
@@ -482,7 +485,10 @@ read_builtin (list)
 	  i = silent ? ttfd_cbreak (fd, &ttset) : ttfd_onechar (fd, &ttset);
 	  if (i < 0)
 	    sh_ttyerror (1);
+	  tty_modified = 1;
 	  add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
+	  if (interactive_shell == 0)
+	    initialize_terminating_signals ();
 	}
     }
   else if (silent)	/* turn off echo but leave term in canonical mode */
@@ -497,7 +503,10 @@ read_builtin (list)
       if (i < 0)
 	sh_ttyerror (1);
 
+      tty_modified = 1;
       add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
+      if (interactive_shell == 0)
+	initialize_terminating_signals ();
     }
 
   /* This *must* be the top unwind-protect on the stack, so the manipulation
@@ -588,6 +597,8 @@ read_builtin (list)
 	    }
 	  else
 	    lastsig = 0;
+	  if (terminating_signal && tty_modified)
+	    ttyrestore (&termsave);	/* fix terminal before exiting */
 	  CHECK_TERMSIG;
 	  eof = 1;
 	  break;
@@ -978,6 +989,20 @@ ttyrestore (ttp)
      struct ttsave *ttp;
 {
   ttsetattr (ttp->fd, ttp->attrs);
+  tty_modified = 0;
+}
+
+void
+read_tty_cleanup ()
+{
+  if (tty_modified)
+    ttyrestore (&termsave);
+}
+
+int
+read_tty_modified ()
+{
+  return (tty_modified);
 }
 
 #if defined (READLINE)
diff --git a/patchlevel.h b/patchlevel.h
index b8bf38704ed2..cefe6bdd3a13 100644
--- a/patchlevel.h
+++ b/patchlevel.h
@@ -25,6 +25,6 @@
    regexp `^#define[ 	]*PATCHLEVEL', since that's what support/mkversion.sh
    looks for to find the patch level (for the sccs version string). */
 
-#define PATCHLEVEL 32
+#define PATCHLEVEL 33
 
 #endif /* _PATCHLEVEL_H_ */
diff --git a/shell.c b/shell.c
index bbc8a66cc2eb..2fd8179ba10d 100644
--- a/shell.c
+++ b/shell.c
@@ -73,6 +73,7 @@
 #endif
 
 #if defined (READLINE)
+#  include <readline/readline.h>
 #  include "bashline.h"
 #endif
 
@@ -909,6 +910,14 @@ exit_shell (s)
   fflush (stdout);		/* XXX */
   fflush (stderr);
 
+  /* Clean up the terminal if we are in a state where it's been modified. */
+#if defined (READLINE)
+  if (RL_ISSTATE (RL_STATE_TERMPREPPED) && rl_deprep_term_function)
+    (*rl_deprep_term_function) ();
+#endif
+  if (read_tty_modified ())
+    read_tty_cleanup ();
+
   /* Do trap[0] if defined.  Allow it to override the exit status
      passed to us. */
   if (signal_is_trapped (0))
diff --git a/sig.c b/sig.c
index 3b62ea5d7c5d..8bc45c17f478 100644
--- a/sig.c
+++ b/sig.c
@@ -532,8 +532,10 @@ termsig_sighandler (sig)
 #if defined (READLINE)
   /* Set the event hook so readline will call it after the signal handlers
      finish executing, so if this interrupted character input we can get
-     quick response. */
-  if (interactive_shell && interactive && no_line_editing == 0)
+     quick response.  If readline is active or has modified the terminal we
+     need to set this no matter what the signal is, though the check for
+     RL_STATE_TERMPREPPED is possibly redundant. */
+  if (RL_ISSTATE (RL_STATE_SIGHANDLER) || RL_ISSTATE (RL_STATE_TERMPREPPED))
     bashline_set_event_hook ();
 #endif