检测NUL文件描述符(isatty是伪造的)

时间:2010-09-06 02:29:15

标签: c windows terminal

当NUL通过管道输出时,以下C文件会出现虚假结果:

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进行比较,但这对我来说感觉不太理想。还有更好的方法吗?

P.S。这有助于解决this GHC bug

3 个答案:

答案 0 :(得分:4)

来自msdn

  如果描述符与a关联,则

_isatty返回非零值   角色设备。否则,_isatty   返回0。

NUL就像Unix上的/ dev / null,它是一个char设备。

请注意,在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");

答案 1 :(得分:0)

这是一个可能的解决方案,但我不相信它一直有效。我相信它适用于NUL文件描述符的特定情况:

int real_isatty(int fd) {
    DWORD st;
    HANDLE h;
    if (!_isatty(fd)) {
        /* TTY must be a character device */
        return 0;
    }
    h = (HANDLE)_get_osfhandle(fd);
    if (h == INVALID_HANDLE_VALUE) {
        /* Broken handle can't be terminal */
        return 0;
    }
    if (!GetConsoleMode(h, &st)) {
        /* GetConsoleMode appears to fail when it's not a TTY. */
        return 0;
    }
    return 1;
}

答案 2 :(得分:-2)

您可以在文件描述符上使用fstat,并将生成的stat结构的设备成员与/dev/null结构进行比较,看看它们是否匹配。