我正在做一个学校项目(构建一个非常基本的外壳)。
这个想法是能够像在 bash 中一样进行行编辑。为此,我将终端模式更改为非规范并停止回显。
我做了一个非常简单的代码来暴露我的问题(请注意,我确实检查函数返回等......我只是为了这篇文章尽可能短)
#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);
}
所以基本上它是一个读取循环来捕获用户条目。它为“c”清除屏幕,为“b”输出字符,为“q”中断并恢复原始终端模式。
问题是:
每当我输入任何内容时,它似乎都会被缓冲,因为在我用“q”中断循环之前什么都没有发生。此时,屏幕上显示输出,如果我输入 5 次 b,我将得到 5 个 b,如果我输入 'c',屏幕将被清除。但是,只有在输入“q”之后。恢复或不恢复原始终端模式时行为相同。(之前的最后一行return
)
我怀疑的是:
在使代码非常短并检查所有返回之后,我倾向于认为我更改终端模式的方式可能存在问题?我尝试使用标志TCSAFLUSH
和具有相同结果TCSADRAIN
的函数。tcsetattr
谢谢 !:)