7

In bash I spin up a t/csh shell, which updates the tty input (stty erase ^H) in the .cshrc, but when exit-ing and returning to bash the backspace key no longer works. This is because bash uses readline and I need to reset the erase (stty erase ^?).

If I understand trap correctly, it seems like I could trap the t/csh exit from within the t/csh process, and run commands after it exits. However, my preference would be for the trapping to occur in bash, which ideally would detect a shell was called/exited and then run a script to reset its configurations.

This is preferred because I could call any number of shells (e.g., dash, zsh), which may inadvertently modify bash-specific settings. Instead of maintaining multiple trap commands for each shell, it seems like it would be best to have one for bash.


Is my understanding of trap correct? If so, is it possible for bash to detect a child shell exit and then run a script?

vol7ron
  • 465
  • 1
  • 7
  • 14

1 Answers1

7

You were on the right track with trap. What you want is the following:

trap "stty erase ^?" SIGCHLD

You can add that to .bashrc. Note that this will run when any subprocess ends.

This will only work in interactive sessions. For non-interactive sessions, bash will not enable job control by default, so you will need to run set -o monitor first. But I doubt you'd need backspaces in non-interactive scripts.

SIGCHLD is sent to the parent process whenever a subprocess exits.


An alternative method is to wrap your other shell in a script, such as:

#!/bin/sh
tcsh
stty erase ^?

Then, if you launch your shell through the script, the script will run the stty erase command after the shell exits. This is less likely to have side effects than a global trap handler, but of course it'll only work if you launch through the script every time (or create an alias to do so, e.g. alias 'tcsh' '~/launch-tcsh.sh').

Floofy Fox
  • 86
  • 4
  • I suppose for tty settings, the job/control isn't as big a deal, but everything else that is probably a very important point. My guess is there's a way to detect the child process and only do this trap if it's a different shell, but this is exactly what I was hoping for -- I was skeptical, but I'm glad I asked -- thank you! – vol7ron May 05 '17 at 17:19
  • @vol7ron Unfortunately, there isn't a foolproof way to detect what the child process was, from bash. You can use `jobs -n` to get recently exited jobs and hopefully the last one is correct, but there exists a race condition there. I think you might be better off using the script wrapper alternative instead. – Floofy Fox May 06 '17 at 16:00
  • 1
    I would have thought that the easiest way to enter `^?` is to type the `^` character then the `?` character: `stty` understands that the `^` character is a prefix for a control character. Also, you could use the `Control-V` `Backspace` to tell Vim that you want to insert a literal Backspace character. – Adrian Pronk May 08 '17 at 02:56
  • @AdrianPronk Thanks, didn't know `stty` did that. Had the vim literal one working at one point but then stuffed something up. Anyway, edited. – Floofy Fox May 08 '17 at 04:20