C-код, чтобы проверить, перенаправлена ли командная строка в /dev/null
Я пишу программу на C, которая выводит на stdout
и ошибки в stderr
, Программа принимает команду, такую как:
./myprogram function_to_run file_to_read
Моя программа может либо выводить на stdout
или быть направлены на вывод файла, но он не должен быть перенаправлен на /dev/null
, Например:
./myprogram function_to_run file_to_read //OK
./myprogram function_to_run file_to_read > file.txt //OK
./myprogram function_to_run file_to_read > /dev/null // NOT OK, should produce error in stderr
Я пытался использовать isatty(1)
, но он может только обнаружить, если stdout
выводит на терминал. Следовательно, это не подходит для случая, когда stdout
перенаправляется в файл, что приемлемо в моем случае
Есть ли способ проверить это в C? Если нет, какие-либо предложения, как я мог бы проверить для сценария /dev/null?
2 ответа
Если вас интересуют только системы *nix, то одним из решений является проверка того, что /proc/self/fd/1
связан с. Ниже приведен пример программы, которая делает это (проверка ошибок для краткости опущена).
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
int main (void)
{
char link[256];
ssize_t rval;
rval = readlink("/proc/self/fd/1", link, sizeof(link));
link[rval] = '\0';
if (!strcmp(link, "/dev/null")) {
assert(!"Redirect to /dev/null not allowed!");
} else {
printf("All OK\n");
}
return 0;
}
Образцы тестовых прогонов:
$ ./a.out
All OK
$ ./a.out > some_file
$ cat some_file
All OK
$ ./a.out > /dev/null
a.out: test.c:14: main: Assertion `!"Redirect to /dev/null not allowed!"' failed.
Aborted (core dumped)
$
Быстрый способ проверить, что стандартный вывод перенаправлен на /dev/null
это проверить, что STDOUT_FILENO
а также /dev/null
оба устройства с одним и тем же индексом:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
int main()
{
struct stat std_out;
struct stat dev_null;
if (fstat(STDOUT_FILENO, &std_out) == 0 &&
S_ISCHR(std_out.st_mode) &&
stat("/dev/null", &dev_null) == 0 &&
std_out.st_dev == dev_null.st_dev &&
std_out.st_ino == dev_null.st_ino)
{
fprintf(stderr, "Redirect to /dev/null not allowed!\n");
exit(EXIT_FAILURE);
}
fprintf(stderr, "All OK\n");
return 0;
}
Проверка inodes переносима на все Unix-подобные системы:
$ ./a.out
All OK
$ ./a.out | cat
All OK
$ ./a.out > /dev/null
Redirect to /dev/null not allowed!
Мы не должны полагаться на /proc/self/fd/1
. Он не поддерживается всеми Unix-подобными системами, особенно Mac OS X Darwin и некоторыми вариантами BSD.
Есть ли способ проверить это в C?
Нет, нет Файл где stderr
перенаправляется контролируется оболочкой, которая запускает программу. Программа C не знает об этом.
Если нет, какие-либо предложения, как я мог бы проверить для сценария /dev/null?
Вы можете изменить свою программу так, чтобы она принимала второй аргумент и использовала его как пункт назначения stderr
с помощью freopen
, Если второй аргумент /dev/null
Вы могли бы ошибиться.
if ( strcmp(argv[2], "/dev/null") == 0 )
{
// Deal with error.
return EXIT_FAILURE;
}
if (freopen(argv[2], "w", stderr) == NULL)
{
perror("freopen() failed");
return EXIT_FAILURE;
}