Основы программирования в Linux - Страница 88

Изменить размер шрифта:

Для установки атрибутов применяется действие

TCSAFLUSH
для очистки буфера клавиатуры, символов, которые пользователи вводили до того, как программа подготовилась к их считыванию. Это хороший способ заставить пользователей не начинать ввод своего пароля, пока не отключено отображение. Перед завершением программы вы также восстанавливаете первоначальные установки.

Другой распространенный пример использования структуры

termios
— перевод терминала в состояние, позволяющее вам считывать каждый набранный символ (упражнение 5.5). Для этого отключается канонический режим и используются параметры
MIN
и
TIME
.

Упражнение 5.5. Считывание каждого символа

Применяя только что полученные знания, вы можете изменить программу menu. Приведенная далее программа menu4.c базируется на программе menu3.c и использует большую часть кода из файла password.с, включенного в нее. Внесенные изменения выделены цветом и объясняются в пунктах описания.

1. Прежде всего, вам следует, включить новый заголовочный файл в начало программы:

#include <stdio.h>

#include <unistd.h>

#include <stdlib.h>

#include <termios.h>

char *menu[] = {

 "a — add new record",

 "d — delete record",

 "q - quit",

 NULL,

};

2. Затем нужно объявить пару новых переменных в функции

main
:

int getchoice(char *greet, char *choices[], FILE *in, FILE *out);

int main() {

 int choice = 0;

 FILE *input;

 FILE *output;

 struct termios initial_settengs, new_settings;

3. Перед вызовом функции

getchoice
вам следует изменить характеристики терминала, этим определяется место следующих строк:

 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);

 }

 tcgetattr(fileno(input), &initial_settings);

 new_settings = initial_settings;

 new_settings.c_lfag &= ~ICANON;

 new_settings.c_lflag &= ~ECHO;

 new_settings.c_cc[VMIN] = 1;

 new_settings.c_cc[VTIME] = 0;

 new_settings.c_lflag &= ~ISIG;

 if (tcsetattr(fileno(input), TCSANOW, &new_settings) != 0) {

  fprintf(stderr, "could not set attributesn");

 }

4. Перед завершением вы также должны вернуть первоначальные значения:

 do {

  choice = getchoice("Please select an action", menu, input, output);

  printf("You have chosen: %cn", choice);

 } while (choice != 'q');

 tcsetattr(fileno(input), TCSANOW, &initial_settings);

 exit(0);

}

5. Теперь, когда вы в неканоническом режиме, необходимо проверить на соответствие возвраты каретки, поскольку стандартное преобразование CR (возврат каретки) в LF (переход на новую строку) больше не выполняется:

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(but, "%sn", *option);

   option++;

  }

  do {

   selected = fgetc(in);

  } while (selected == 'n' || selected == 'r');

  option = choices;

  while (*option) {

   if (selected == *option[0]) {

    chosen = 1;

    break;

   }

   option++;

  }

  if (!chosen) {

   fprintf(out, "Incorrect choice, select againn");

  }

 } while(!chosen);

 return selected;

}

Пока вы не устроите все иначе, теперь, если пользователь нажмет в вашей программе комбинацию клавиш +, программа завершится. Вы можете отключить обработку этих специальных символов, очистив флаг

ISIG
в локальных режимах. Для этого в функцию
main
включается следующая строка:

new_settings.c_lflag &= ~ISIG;

Если вы внесете эти изменения в вашу программу меню, то будете получать немедленный отклик, и вводимый вами символ не будет отображаться на экране.

Оригинальный текст книги читать онлайн бесплатно в онлайн-библиотеке Knigger.com