Основы программирования в Linux - Страница 82
$ ./menu2Choice: Please select an actiona — add new recordd — delete recordq — quitqYou have chosen: q $ ./menu2 > fileYou are not a terminal! $Как это работает
В новом фрагменте программного кода функция
isattystdoutstderr$ ./menu2 >file 2>file.error$или объединить оба выводных потока в одном файле:
$ ./menu2 >file 2>&1$(Если вы не знакомы с перенаправлением вывода, прочтите еще раз главу 2, в которой мы более подробно рассматриваем синтаксические правила, связанные с ним.) В данном случае вам нужно отправить сообщение непосредственно на терминал пользователя.
Диалог с терминалом
Если нужно защитить части вашей программы, взаимодействующие с пользователем, от перенаправления, но разрешить его для других входных и выходных данных, вы должны отделить общение с пользователем от потоков
stdoutstderrК счастью, Linux и UNIX облегчают жизнь, предоставляя специальное устройство /dev/tty, которое всегда является текущим терминалом или сеансом работы в системе (login session). Поскольку ОС Linux все интерпретирует как файлы, вы можете выполнять обычные файловые операции для чтения с устройства /dev/tty и записи на него.
В упражнении 5.3 вы исправите программу выбора пункта меню так, чтобы можно было передавать параметры в подпрограмму
getchoiceЗагрузите файл menu2.c и измените программный код так, чтобы входные и выходные данные приходили с устройства /dev/tty и направлялись на это устройство.
#include <stdio.h>#include <unistd.h>#include <stdlib.h>char *menu[] = { "a — add new record", "d — delete record", "q - quit", NULL,};int getchoice(char* greet, char* choices[], FILE* in, FILE* out);int main() { int choice = 0; FILE* input; FILE* output; if (!isatty(fileno(stdout))) { fprintf(stderr, "You are not a terminal, OK.n"); } input = fopen("/dev/tty", "r"); output = fopen("/dev/tty", "w"); if (!input || !output) { fprintf(stderr, "Unable to open /dev/ttyn"); exit(1); } do { choice = getchoice("Please select an action", menu, input, output); printf("You have chosen: %cn", choice); } while (choice != 'q'); exit(0);}int getchoice(char* greet, char *choices[], FILE* in, FILE *out) { int chosen = 0; int selected; char **option; do { fprintf(out, "Choice: %sn", greet); option = choices; while (*option) { fprintf(out, "%sn", *option); option++; } do { selected = fgetc(in); } while(selected == 'n'); option = choices; while (*option) { if (selected == *option[0]) { chosen = 1; break; } option++; } if (!chosen) { fprintf(out, "Incorrect choice, select againn"); } } while (!chosen); return selected;}Теперь, когда вы выполните программу с перенаправленным выводом, вы сможете увидеть строки приглашения, а стандартный вывод программы (обозначающий выбранные пункты меню) перенаправляется в файл, который можно просмотреть позже: