Is there a way to prevent a process changing the terminal?
Not really. The terminal state is global to the terminal and can be
changed by any process that has permission to do so.
$ tty
/dev/ttys007
$ stty -a | grep ' erase'
eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
$ stty erase '#'
$ stty -a | grep ' erase'
eol2 = <undef>; erase = #; intr = ^C; kill = ^U; lnext = ^V;
As an exercise you can figure out how to undo that change. Another
exercise is to see what shells or programs honor erase
being the
traditional #
(as seen in "The UNIX Programming Environment" (1984)).
Interactive programs are otherwise not designed to run in the background
and even if they do not alter the terminal state their output may be
interleaved with output from other programs and hard to read, or they
may forever be being hit with SIGTTIN or SIGTTOU signals as they try to
interact with the terminal from the background. Stair-stepping is a
common problem where the terminal state (or a line printer) is out of
sync with what a process expects it to be; there are various flags that
influence CR/NL handling documented in the termios
manual page
(INLCR
, IGNCR
, etc). If your background process expects setting X
but the shell changes it back to Y, well, then you have a conflict.
Some operating systems might have security frameworks that might let you
prevent a program from changing the terminal settings. In this case the
interactive program may not run or may fail to operate as designed, and
you may end up spending quite a lot of time fiddling around with the
security framework to get the configuration just right.
Another option may be to run the process under a unique pty (e.g. under tmux
)
where it should not interfere with other programs being run in other
windows.
stty -g
(if supported) will let you save (some of) the terminal
settings to be restored at some later time, but this will not work if a
process in the background is forever fiddling with the terminal state,
or if the settings the background program needs conflict with the restored values.
Most programs only make terminal state changes at startup or at other
specific events (reacting to control+z and then
when being brought into the foreground, for example). A program could
use tcsetattr(3)
to fiddle with the terminal state directly.
Some shells are better than others at restoring the terminal state after
a program exits. Compare ZSH with, say, the Heirloom Bourne Shell.
Various programs will ignore certain terminal settings, e.g. ZSH will
ignore erase
being set to #
, while under other programs (cat
, for
example) #
should erase the previous character.
Exercise hint: lnext
short for "literal next" is usually
control+v, or whatever stty -a
says it is.
Programs may not honor this...
watch
) that is designed to be run as an interactive process in the foreground that takes over and uses the entire terminal screenwatch
was an example for a process who changes the terminal. This is a reproducible example that one can take and modify -> in case this issue is solvable. Are reproducible examples wrong?watch
is one example.vi[m]
would be another except that it cleanly refuses to run at all if pushed the background.nethack
might be another but I don't have it installed.