From: Godmar Back <godmar@gmail.com>
To: zsh-workers@zsh.org
Subject: support for POSIX job control terminal management in zsh
Date: Mon, 22 Jun 2020 21:39:40 -0400 [thread overview]
Message-ID: <CAB4+JYJft=Cc7nEvqsyTJwix-1HCc0jooBDvDy8N2MT_x2hecQ@mail.gmail.com> (raw)
Hi,
I noticed that zsh does not implement POSIX.1 when it comes to
saving/restoring the terminal state of processes suspended with
SIGTSTP. (The same applies to bash, btw, but not to ksh.) Shells
like tcsh or ash/dash also do not implement it.
POSIX.1 asks that:
"When a foreground (not background) job stops, the shell must sample
and remember the current terminal settings so that it can restore them
later when it continues the stopped job in the foreground (via the
tcgetattr( ) and tcsetattr( ) functions)."
Consequently, a program such as the one attached below should not fail
any assertions.
However, it does not appear to work when run under zsh.
I've had an illuminating discussion with Chet Ramey, the author of
bash, regarding bash's behavior. He pointed out that applications
historically could never rely on the shell provided job control in a
manner that they could be oblivious to being suspended/resumed, and
therefore always had to handle the saving/restoring of the terminal
state upon suspend/restore themselves, rather than relying on the job
control shell as POSIX asks.
Still, at least one shell (ksh) does appear to implement it.
Hence my question, out of curiosity, is: why does zsh not follow
POSIX.1 semantics in this regard?
Thanks.
- Godmar
// ts_test.c
/* Test that terminal state is properly restored when a process is
stopped and restored. */
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <assert.h>
#include <signal.h>
#define CTRL_D 4
#define CTRL_E 5
int
main()
{
int terminal_fd = open(ctermid(NULL), O_RDWR);
assert (terminal_fd != -1);
// Step 1. make a change to the terminal state:
// change VEOF from Ctrl-D to Ctrl-E
struct termios saved_tty_state;
int rc = tcgetattr(terminal_fd, &saved_tty_state);
assert (rc == 0);
assert (saved_tty_state.c_cc[VEOF] == CTRL_D); // ^D
saved_tty_state.c_cc[VEOF] = CTRL_E; // ^E
rc = tcsetattr(terminal_fd, TCSANOW, &saved_tty_state);
assert (rc == 0);
// Step 2. Suspend and let user resume
printf("This job should now stop, please run 'fg' to continue it\n");
raise(SIGTSTP);
printf("Job now continuing...\n");
// Step 3.
// Expect that job control shell saved the terminal state
rc = tcgetattr(terminal_fd, &saved_tty_state);
assert (rc == 0);
if (saved_tty_state.c_cc[VEOF] != CTRL_E) {
printf("I expected a POSIX job control shell to preserve my
terminal settings\n");
printf("VEOF was not saved, it is %d...\n", saved_tty_state.c_cc[VEOF]);
}
assert (saved_tty_state.c_cc[VEOF] == CTRL_E); // ^E
}
next reply other threads:[~2020-06-23 1:40 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-23 1:39 Godmar Back [this message]
2020-06-23 1:53 ` Bart Schaefer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='CAB4+JYJft=Cc7nEvqsyTJwix-1HCc0jooBDvDy8N2MT_x2hecQ@mail.gmail.com' \
--to=godmar@gmail.com \
--cc=zsh-workers@zsh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).