[英]Non canonical terminal mode buffer stdout in c program
I am working a school project (building a very basic shell).我正在做一个学校项目(构建一个非常基本的外壳)。
The idea is to be able to do line edition like in bash.这个想法是能够像在 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'.
它为“c”清除屏幕,为“b”输出字符,为“q”中断并恢复原始终端模式。
Whenever I type anything, it seems to be buffered because nothing happens until I break the loop with 'q'.每当我输入任何东西时,它似乎都被缓冲了,因为在我用 '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.
此时,输出显示在屏幕上,如果我输入 5 次 b,我将得到 5 个 b,如果我输入“c”,屏幕将被清除。 BUT, only after typing 'q'.
但是,只有在输入“q”之后。 The behaviour is the same while restoring or not the original terminal mode.
恢复或不恢复原始终端模式时的行为是相同的。 (the last line before
return
) (
return
前的最后一行)
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.我为
tcsetattr
函数尝试使用标志TCSAFLUSH
和TCSADRAIN
,结果相同。
Thanks !谢谢 ! :)
:)
Ok so for anyone who encounter this situation, it's quite interesting because it made me learn many stuffs (well it's a school project so...).好吧,对于遇到这种情况的人来说,这很有趣,因为它让我学到了很多东西(嗯,这是一个学校项目,所以......)。
Using putchar
in the tputs
parameters was the issue, because putchar is buffered, juste like printf.在
tputs
参数中使用putchar
是问题所在,因为 putchar 是缓冲的,就像 printf 一样。 I ended up trying two things that led me to the realisation: fflush()
after the tputs
function call would work so obviously the issue was buffer related.我最终尝试了两件让我意识到的事情:在
tputs
函数调用之后的fflush()
会起作用,所以显然问题与缓冲区有关。 Then tried to output to STDERR_FILENO and it kinda solved it too, and in fact the stderr is the only one _IONBF
, so not buffered.然后尝试输出到 STDERR_FILENO 并且它也解决了它,实际上 stderr 是唯一的
_IONBF
,因此没有缓冲。
So I ended up creating a putchar function with only write
in it, and that was it.所以我最终创建了一个只有
write
的 putchar 函数,就是这样。
Here are more info about the three buffer modes:以下是有关三种缓冲模式的更多信息:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.