/*
* Test that terminal state is properly restored when a process is stopped and restored
* by the shell, the way ksh does it and POSIX recommends (though does not require).
*
* bash and zsh fail this test.
*
* We change one attribute here: the key for EOF from Ctrl-D to Ctrl-E.
*/
#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 the VEOF key 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 now %d...\n", saved_tty_state.c_cc[VEOF]);
}
assert (saved_tty_state.c_cc[VEOF] == CTRL_E); // ^E
// now restore it the way it was
saved_tty_state.c_cc[VEOF] = CTRL_D; // ^D
rc = tcsetattr(terminal_fd, TCSANOW, &saved_tty_state);
assert (rc == 0);
}