I'm writing a shell that tries to simulate bash's behaviour. The problem is that I've read that when Bash gets the user input, it uses a non-canonical mode and turn off the ECHO kind of like this :
(*conf)->newterm.c_lflag &= ~(ICANON | ECHO);
But if it turns ECHO off, how is SIGINT still displayed as ^C on the temrinal ? When I try this, I get the character � which is -1 (if you try to print it).
If we pay enough attention to bash behaviour, control characters are never displayed except for ctrl-c AKA SIGINT. My only theory is that bash hard coded ^C and just print it to the screen when SIGINT is detected. Am I right saying this ? Of not, how does BASH or ZSH display ^C having ECHO and ICANON turned off ? I've looked everywhere and I really can't seem to find an answer to this...
Thank you for your time and your explanation !
EDIT : Here is what I do. First I initialize my shell as this :
tcgetattr(STDIN_FILENO, &(*conf)->oldterm);
(*conf)->newterm = (*conf)->oldterm;
(*conf)->newterm.c_lflag &= ~(ICANON | ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &(*conf)->newterm); // Apply immediately
Then well I press ctrl-c, I get a newline and ^C is not displayed. This is because I'm disabling ECHO so ECHOCTL gets disabled too. Now, What I want to have is if I press ctr-c, have ^C displayed, but also not having ^[[A when I press the upper arrow key. I'm just unsure how to configure termios to do that.
I believe the
^Cis actually being generated by the terminal device interface (tty), as opposed to Bash or Z Shell. For example, and followingstty -echoctlandstty -echo,^Cis no longer displayed. As another example, a simple C program withsleep(1)s in an infinite loop andSIGINTset toSIG_IGN(and withstty echo), still displays^C.This example works for me, the most relevant lines being 17, 19, 20, 36, and 37 (
gcc -Wallcompiled, in macOS and Linux, in Bash and Z Shell, with Terminal [Apple], Terminator, and GNOME Terminal, within and without GNU Screen and/or tmux, and withTERMs ofxterm-256colorandscreen-256color):P.S. Keep in mind that
[ctrl]-c(generally) triggers aSIGINT, thatSIGINTcan be generated without a[ctrl]-c, and that, for example,kill -INT "$pid", should not trigger a tty-driven^Coutput.