c-bash输入重定向中断stdin



我有一个程序,看起来像这样:

#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做了一些事情,所以它在程序中冻结了。

有什么办法解决这个问题吗?

errno25="设备"的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 ;
}

最新更新