Как я проверяю, передали ли моей программе данные по каналу в него

Я пишу программу, которая должна считать вход через stdin, таким образом, у меня есть следующая конструкция.

FILE *fp=stdin;

Но это просто зависает, если пользователь ничего не передал по каналу в программу, как я могу проверить, передает ли пользователь на самом деле данные по каналу в мою программу как

gunzip -c file.gz |./a.out #should work
./a.out  #should exit program with nice msg.

спасибо

7
задан monkeyking 2 April 2010 в 00:49
поделиться

6 ответов

Поскольку вы используете указатели на файлы, вам понадобятся как isatty () , так и fileno () для этого:

#include <unistd.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    FILE* fp = stdin;

    if(isatty(fileno(fp)))
    {
        fprintf(stderr, "A nice msg.\n");
        exit(1);
    }

    /* carry on... */
    return 0;
}

На самом деле, это долгий путь. Короткий способ - не использовать указатели файлов:

#include <unistd.h>

int main(int argc, char* argv[])
{
    if(isatty(STDIN_FILENO))
    {
        fprintf(stderr, "A nice msg.\n");
        exit(1);
    }

    /* carry on... */
    return 0;
}

Некоторые стандартные программы Unix выполняют эту проверку, чтобы изменить свое поведение. Например, если вы настроили ls , чтобы дать вам красивые цвета, он отключит цвета, если вы передадите его стандартный вывод другой программе.

8
ответ дан 6 December 2019 в 11:47
поделиться

См. Функцию isatty - если STDIN является терминалом, вы можете пропустить чтение с него. Если это не терминал, вы получаете данные, передаваемые по конвейеру или перенаправленные, и вы можете читать до EOF.

1
ответ дан 6 December 2019 в 11:47
поделиться

Дополнительная опция, которую вы получаете с select (), - это установка тайм-аута для чтения из стандартного ввода (относительно первого чтения из стандартного ввода или последовательных чтений из стандартного ввода).

Для примера кода с использованием select на stdin см .:

Как проверить, открыт ли stdin по-прежнему без блокировки?

0
ответ дан 6 December 2019 в 11:47
поделиться

Попробуйте "man isatty", я думаю, эта функция скажет вам, разговариваете вы с пользователем или нет.

3
ответ дан 6 December 2019 в 11:47
поделиться

Используйте isatty , чтобы определить, что стандартный ввод поступает с терминала, а не с перенаправления.

2
ответ дан 6 December 2019 в 11:47
поделиться

Передача stdin в select () или poll () должна сообщить вам, ожидает ли ввод. Во многих ОС вы также можете определить, является ли stdin терминалом или каналом.

РЕДАКТИРОВАТЬ: Я вижу, что мне придется выделить также часть tty-теста. FIFO не является терминалом, но ввод данных может отсутствовать в течение неопределенного времени.

3
ответ дан 6 December 2019 в 11:47
поделиться