我有一个程序,看起来像这样:
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
int enable_keyboard() {
struct termios new_term_attr;
tcgetattr(fileno(stdin), &new_term_attr);
new_term_attr.c_lflag &= ~(ECHO|ICANON);
new_term_attr.c_cc[VTIME] = 0;
new_term_attr.c_cc[VMIN] = 0;
return tcsetattr(fileno(stdin), TCSANOW, &new_term_attr);
}
int main() {
errno = 0;
unsigned char field[H][W];
fill (field);
char c = enable_keyboard();;
while(1) {
read(0, &c, 1);
printf("%d ", c);
}
}
它从stdin中读取一个字符并无限显示(以检查enable_keybord是否正常工作(
问题是,当我使用输入重定向(行./a.out < test.txt
(运行此程序时,它会中断所有输入,并且errno
设置为25。
当tcsetattr
应该返回0或-1时,它也会返回-201。
我试图在tcsetattr
之前用scanf
清除stdin
,并完全禁用tcsetattr
,但结果是输入重定向完全挂起了所有输入。
在没有输入重定向的情况下,一切都很好,所以我想bash可能对stdin做了一些事情,所以它在程序中冻结了。
有什么办法解决这个问题吗?
errno
25="设备"的ioctl不合适;;您正在对文件执行终端操作。您不检查来自tcgetattr()
的退货。出错时,它设置errno
,如果文件描述符不表示终端,则设置为ENOTTY
。因此:
int enable_keyboard()
{
struct termios new_term_attr;
int status = -1 ;
if( tcgetattr(fileno(stdin), &new_term_attr) == 0 )
{
new_term_attr.c_lflag &= ~(ECHO|ICANON);
new_term_attr.c_cc[VTIME] = 0;
new_term_attr.c_cc[VMIN] = 0;
status = tcsetattr(fileno(stdin), TCSANOW, &new_term_attr);
}
return status ;
}
这不会解决你的";悬挂;然而,正如您所提到的,您的程序会无限期地循环,while循环不会在EOF时终止。问题是,EOF不是由read()
明确表示的,而是返回零,这对于终端输入来说只是意味着没有字符。在这种情况下:
char c = 0 ;
bool is_file = enable_keyboard() != 0 ;
bool terminate = false ;
while( !terminate )
{
terminate = read(0, &c, 1) == 0 && is_file ;
printf("%d ", c);
}
综合来看:
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <stdbool.h>
int enable_keyboard()
{
struct termios new_term_attr;
int status = -1 ;
if( tcgetattr(fileno(stdin), &new_term_attr) == 0 )
{
new_term_attr.c_lflag &= ~(ECHO|ICANON);
new_term_attr.c_cc[VTIME] = 0;
new_term_attr.c_cc[VMIN] = 0;
status = tcsetattr(fileno(stdin), TCSANOW, &new_term_attr);
}
return status ;
}
int main()
{
errno = 0;
char c = 0 ;
bool is_file = enable_keyboard() != 0 ;
bool terminate = false ;
while( !terminate )
{
terminate = read(0, &c, 1) == 0 && is_file ;
printf("%d ", c);
}
return 0 ;
}