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); }