I am working a school project (building a very basic shell).
The idea is to be able to do line edition like in bash. For this, I change the terminal mode to non canonical and I stop echo.
I made a very simple code to expose my issue (please note, I do check for functions returns etc... I just made it as short as possible for this post)
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
int ret;
char buff;
char *term_name;
char *termcap;
struct termios termios_new;
struct termios termios_backup;
/*
** Init termcap library
*/
term_name = getenv("TERM");
tgetent(NULL, term_name);
/*
** Get the terminal mode to non canonical and shut down echo
*/
bzero(&termios_new, sizeof(struct termios));
tcgetattr(STDIN_FILENO, &termios_backup);
termios_new = termios_backup;
termios_new.c_lflag &= ~(ICANON);
termios_new.c_lflag &= ~(ECHO);
termios_new.c_cc[VMIN] = 1;
termios_new.c_cc[VTIME] = 0;
/*
** Set the change
*/
tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios_new);
/*
** Get the termcap for clearing screen on the particular terminal
*/
termcap = tgetstr("cl", NULL);
/*
** Loop read to get user entries and clear screen for 'c', output char for 'b', break for 'q'
*/
while((ret = read(STDIN_FILENO, &buff, 1)) > 0)
{
if (buff == 'c')
tputs(termcap, 1, putchar);
else if (buff == 'b')
putchar(buff);
else if (buff == 'q')
break ;
buff = 0;
}
/*
** Put back the terminal mode as found before
*/
tcsetattr(STDIN_FILENO, TCSAFLUSH, &termios_backup);
return (0);
}
So basically it's a loop on read to catch user entries. It clears the screen for 'c', output char for 'b', break and restore the original terminal mode for 'q'.
Issue is :
Whenever I type anything, it seems to be buffered because nothing happens until I break the loop with 'q'.
At this moment, the output show on screen, if I typed 5 times b, I'll get the 5 b's and if I types 'c', the screen will be cleared.
BUT, only after typing 'q'.
The behaviour is the same while restoring or not the original terminal mode. (the last line before return)
What I suspect :
After making the code very short and checking all returns, I tend to think there could only be an issue with the way I change the terminal mode ?
I tries with the flags TCSAFLUSH and TCSADRAIN for the tcsetattr function with same result.
Thanks ! :)