检测 NUL 文件描述符(isatty 是假的)
Posted
技术标签:
【中文标题】检测 NUL 文件描述符(isatty 是假的)【英文标题】:Detect NUL file descriptor (isatty is bogus) 【发布时间】:2011-04-08 14:27:14 【问题描述】:以下 C 文件在通过管道传递 NUL 时会给出虚假结果:
int main()
printf("_isatty = %d\n", _isatty(0));
结果是:
C:\Users\Edward\Dev\nulltest> test.exe < NUL
_isatty = 64
我很确定 NUL(又名 /dev/null)不是终端设备!所以我需要以另一种方式检测文件描述符是否对应于NUL。该数字没有任何特定含义;当我确实连接了终端时,我会看到它。
我该怎么办? This question 建议使用粗略的未记录函数来获取底层名称,大概将其与 NUL 进行比较,但这对我来说感觉不太理想。有没有更好的办法?
附:这将有助于解决this GHC bug。
【问题讨论】:
只是出于兴趣(我并不是说您所做的事情是错误的):您为什么关心输入的来源? 有许多应用程序在检测到终端时会执行不同的操作。例如,如果你输入'python',它会进入交互模式,但是'echo "print \"bar\"" | python' 不会显示任何初始化屏幕。 好吧,在这种情况下,我只是在调试它,因为它会导致测试套件失败,我讨厌失败的测试套件 :-) 【参考方案1】:来自msdn:
_isatty 如果描述符与 字符设备。否则,_isatty 返回 0。
NUL 就像 Unix 上的 /dev/null,它是一个字符设备。
注意,在 Linux 上,isatty 是不同的:
isatty() 函数测试 fd 是否 是一个打开的文件描述符,引用 到终端。
您可以尝试将 STDIN_FILENO (0) 与 $cwd/NUL 进行比较(使用 stat 或 stat)。
更新:
int ret = GetFileType(GetStdHandle(STD_INPUT_HANDLE));
它将为 NUL 或 tty 返回 FILE_TYPE_CHAR。
有关其他值,请参阅 GetFileType 文档。您可以检测文件/字符设备/管道。
最终更新:
使用GetConsoleMode 输入,GetConsoleScreenBufferInfo 输出。
CONSOLE_SCREEN_BUFFER_INFO sbi;
DWORD mode;
if (!GetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), &mode))
fprintf(stderr, "not console\n");
else
fprintf(stderr, "console\n");
if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &sbi))
fprintf(stderr, "not console\n");
else
fprintf(stderr, "console\n");
【讨论】:
有趣!这意味着我们实际上不应该使用 isatty 来检测是否有终端。 Windows 上是否有等效功能? _isatty 有问题,它应该检测您是否使用终端,而不是 fd 是否是字符设备。我不确定在 Windows 上最好的方法是什么。您可以尝试检查 cygwin/mingway isatty 的实现。您还可以创建一个将 $(CWD)/NUL 列入黑名单的包装器,因为它可能是您可以在 Windows 上轻松使用的唯一字符设备。 但是......这不区分 NUL 或 tty。 (我有点困惑。) 嗯嗯嗯..我想我失去了真正的问题..我修正了我的答案。【参考方案2】:这是一个可能的解决方案,但我不相信它始终有效。我相信它适用于 NUL 文件描述符的特定情况:
int real_isatty(int fd) DWORD st; 处理 h; 如果(!_isatty(fd)) /* TTY 必须是字符设备 */ 返回0; h = (句柄)_get_osfhandle(fd); 如果(h == INVALID_HANDLE_VALUE) /* 损坏的句柄不能是终端 */ 返回0; if (!GetConsoleMode(h, &st)) /* GetConsoleMode 在不是 TTY 时似乎失败。 */ 返回0; 返回 1;【讨论】:
【参考方案3】:您可以在文件描述符上使用fstat
,并将生成的stat
结构的设备成员与/dev/null
的设备成员进行比较,看看它们是否匹配。
【讨论】:
不起作用。 _stat 总是返回 2,而 _fstat 总是返回 0。以上是关于检测 NUL 文件描述符(isatty 是假的)的主要内容,如果未能解决你的问题,请参考以下文章
为啥 Object.prototype instanceof Object 是假的?