On Thu, Nov 24, 2016 at 12:05:20AM -0800, Eric Pruitt wrote:
> In my Bash configuration, I have things setup so Ctrl+Z is no longer
> translated into a signal at the Bash prompt so it can be remapped. Most
> recently, I decided to modify the Bash source to implement this change
> in the interpreter because the stty invocations introduced a perceptible
> amount of lag on a virtualized OpenBSD host I use. I think this feature
> would be a useful default since it usually does not make sense to send
> SIGTSTP to a prompt. Here's an accompanying snippet from my inputrc:
>
>     # Allows Ctrl+Z to be used to bring programs back into the
>     # foreground. The cursor is moved to the beginning of the line
>     # before typing so a specific job can be resumed by typing its
>     # identifier (e.g. a number) then hitting Ctrl+Z. This depends on
>     # Ctrl+Z being a literal sequence i.e. "stty susp undef".
>     "\C-z": "\C-afg \C-m"

This patch had a bug that I recently fixed, and I've attached an updated
version. Under certain conditions, ^Z for SIGTSTP would not be
re-enabled after executing a command. For example, if "cat /dev/zero >
/dev/null" was interrupted by pressing Ctrl+C, pressing Ctrl+Z would not
generate a literal ^Z control character at the next prompt. Some
debugging revealed that I did not fully understand the control flow of
the prompt handling when writing the original patch; control may be
resumed at the top of the "reader_loop" function by way of a long lump
which bypassed the vsusp toggling code. The bug has been fixed by moving
the vsusp toggle logic after the aforementioned long-jump destination.

I'm not requesting that this patch be accepted upstream, just posting an
updated version for anyone that might interested in this feature.

Eric
When running commands interactively, modify the terminal attributes so the
suspend character is interpreted as literal sequence at the prompt but produces
a SIGTSTP signal during command execution. This makes it possible to bind ^Z in
readline. For example, adding `"\C-z": "\C-afg \C-m"` to "~/.inputrc" would
make it possible to suspend a program using ^Z then pressing ^Z again to bring
the program back to the foreground.

--- eval.c	2016-06-02 15:49:27.000000000 -0700
+++ eval.c	2016-11-20 15:02:23.681680378 -0800
@@ -31,6 +31,7 @@
 #include <stdio.h>
 
 #include <signal.h>
+#include <termios.h>
 
 #include "bashintl.h"
 
@@ -69,6 +70,8 @@
 int
 reader_loop ()
 {
+  struct termios ttyattr;
+  cc_t vsusp = 0;
   int our_indirection_level;
   COMMAND * volatile current_command;
 
@@ -84,6 +87,13 @@
 
       code = setjmp_nosigs (top_level);
 
+      if (!vsusp && indirection_level == 1 && interactive &&
+       !tcgetattr(STDERR_FILENO, &ttyattr)) {
+	vsusp = ttyattr.c_cc[VSUSP];
+	ttyattr.c_cc[VSUSP] = 0;
+	tcsetattr(STDERR_FILENO, TCSADRAIN, &ttyattr);
+      }
+
 #if defined (PROCESS_SUBSTITUTION)
       unlink_fifo_list ();
 #endif /* PROCESS_SUBSTITUTION */
@@ -177,6 +187,13 @@
 		  free (ps0_string);
 		}
 
+	      if (vsusp) {
+		ttyattr.c_cc[VSUSP] = vsusp;
+		if (!tcsetattr(STDERR_FILENO, TCSADRAIN, &ttyattr)) {
+		  vsusp = 0;
+		}
+	      }
+
 	      execute_command (current_command);
 
 	    exec_done:
@@ -199,6 +216,11 @@
 	EOF_Reached = EOF;
     }
   indirection_level--;
+
+  if (vsusp) {
+    ttyattr.c_cc[VSUSP] = vsusp;
+    tcsetattr(STDERR_FILENO, TCSADRAIN, &ttyattr);
+  }
   return (last_command_exit_value);
 }
 

Reply via email to