customBashShell / tests / advanced / ts_test.c
ts_test.c
Raw
/* 
 * 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);
}