Книга: Основы программирования в Linux

Диалог с терминалом

Диалог с терминалом

Если нужно защитить части вашей программы, взаимодействующие с пользователем, от перенаправления, но разрешить его для других входных и выходных данных, вы должны отделить общение с пользователем от потоков stdout и stderr. Это можно сделать, непосредственно считывая данные с терминала и прямо записывая данные на терминал. Поскольку ОС Linux с самого начала создавалась, как многопользовательская система, включающая, как правило, множество терминалов, как непосредственно подсоединенных, так и подключенных по сети, как вы сможете определить тот терминал, который следует использовать?

К счастью, Linux и UNIX облегчают жизнь, предоставляя специальное устройство /dev/tty, которое всегда является текущим терминалом или сеансом работы в системе (login session). Поскольку ОС Linux все интерпретирует как файлы, вы можете выполнять обычные файловые операции для чтения с устройства /dev/tty и записи на него.

В упражнении 5.3 вы исправите программу выбора пункта меню так, чтобы можно было передавать параметры в подпрограмму getchoice и благодаря этому лучше управлять выводом. Назовите ее menu3.c.

Упражнение 5.3. Применение /dev/tty

Загрузите файл 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;
}

Теперь, когда вы выполните программу с перенаправленным выводом, вы сможете увидеть строки приглашения, а стандартный вывод программы (обозначающий выбранные пункты меню) перенаправляется в файл, который можно просмотреть позже:

$ ./menu3 > file
You are not a terminal, OK.
Choice: Please select an action
a — add new record
d — delete record
q — quit
d
Choice: Please select an action
a — add new record
d - delete record
q — quit
q
$ cat file
You have chosen: d
You have chosen: q

Оглавление книги


Генерация: 1.101. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз