有没有办法在TTY驱动程序遇到换行符或EOF之前读取用户输入,但没有使用/dev/input/event*
我尝试在循环中使用write(3)
但是需要等待TTY驱动程序将数据发送到进程的标准输入。此外,如果我理解正确,使用/dev/input/event*
将捕获所有键击。我只对在遇到stdin
或EOF
之前从\n
进行阅读感兴趣。
答案 0 :(得分:4)
您需要将stdin
置于非规范模式,如果stdin
是终端或伪终端,您可以执行此操作。请参阅man tcgetattr
或man termios
(可能是相同的联机帮助页)。是的,这是很多阅读:)
您很可能拥有库函数cfmakeraw
,这是将stdin
置于原始模式的最简单方法。只要您定义_BSD_SOURCE
特征测试宏,GNU C库就可以使用它。 cfmakeraw
将执行原始模式的所有常规设置,包括关闭回显,因此您必须自己回显键入stdout
的字符。您还必须处理解释退格和箭头字符,以及烹饪(逐行或规范)输入的所有其他细节。
此外,即使程序崩溃,也要确保将终端重置为正常模式。 (您需要使用atexit
。)
对于它的价值,您可能会发现使用ncurses
库更加简单。
答案 1 :(得分:2)
更改终端设置以禁用一次一行输入。确保在程序退出时恢复终端设置。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <termios.h>
#include <unistd.h>
#define CNTL_D 4
static struct termios oldtty, newtty;
void kbcleanup( void )
{
tcsetattr( 0, TCSAFLUSH, &oldtty ); /* restore old settings */
}
int kbsetup( void )
{
tcgetattr( 0, &oldtty );
newtty = oldtty;
newtty.c_lflag &= ~ICANON; /* disable line-at-a-time input */
newtty.c_lflag &= ~ECHO; /* disable echo */
if ( tcsetattr( 0, TCSAFLUSH, &newtty ) == 0 ){
atexit( kbcleanup ); /* restore the terminal settings when the program exits */
return( 1 );
} else {
return( 0 );
}
}
int main( void )
{
int c;
if ( !kbsetup() )
{
fprintf( stderr, "Unable to set terminal mode\n" );
exit( 1 );
}
while ( (c = getchar()) != CNTL_D )
{
printf( " -- got char 0x%02x" , c );
if ( isprint(c) )
printf( " '%c'\n", c );
else
printf( "\n" );
}
}