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"

With my changes to Bash and this in my inputrc, Ctrl+Z becomes a toggle.
I have attached the patch I wrote for myself. Since I only use modern
POSIX / UNIX-like systems, it was not written with portability in mind
and cannot be disabled with with "set" or "shopt." Consider it a proof
of concept rather than a pull request. Please let me know what you
think.

Thanks,
Eric
--- 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;
 
@@ -82,6 +85,13 @@
     {
       int code;
 
+      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);
+      }
+
       code = setjmp_nosigs (top_level);
 
 #if defined (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