我正在做一个学校项目(构建一个非常基本的外壳)。
想法是能够像在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
功能。
谢谢 !:)
好吧,对于遇到这种情况的任何人,这都很有趣,因为它使我学到了很多东西(这是一个学校项目,所以……)。
putchar
在tputs
参数中使用是个问题,因为putchar被缓冲,就像printf一样。我最终尝试了两件事使我意识到这一点:fflush()
在tputs
函数调用可以正常工作之后,很明显问题与缓冲区有关。然后尝试输出到STDERR_FILENO,它也解决了这个问题,实际上stderr是唯一的一个_IONBF
,因此没有缓冲。
因此,我最终只创建了一个putchar函数,仅write
此而已。
以下是有关三种缓冲区模式的更多信息:
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句