Основы программирования в Linux
Для установки атрибутов применяется действие
для очистки буфера клавиатуры, символов, которые пользователи вводили до того, как программа подготовилась к их считыванию. Это хороший способ заставить пользователей не начинать ввод своего пароля, пока не отключено отображение. Перед завершением программы вы также восстанавливаете первоначальные установки.TCSAFLUSHДругой распространенный пример использования структуры
— перевод терминала в состояние, позволяющее вам считывать каждый набранный символ (упражнение 5.5). Для этого отключается канонический режим и используются параметрыtermiosиMIN.TIMEУпражнение 5.5. Считывание каждого символаПрименяя только что полученные знания, вы можете изменить программу menu. Приведенная далее программа menu4.c базируется на программе menu3.c и использует большую часть кода из файла password.с, включенного в нее. Внесенные изменения выделены цветом и объясняются в пунктах описания.
1. Прежде всего, вам следует, включить новый заголовочный файл в начало программы:
#include <stdio.h>#include <unistd.h>#include <stdlib.h><i>#include <termios.h></i>char *menu[] = {"a — add new record","d — delete record","q - quit",NULL,};2. Затем нужно объявить пару новых переменных в функции
:mainint getchoice(char *greet, char *choices[], FILE *in, FILE *out);int main() {int choice = 0;FILE *input;FILE *output;<i> struct termios initial_settengs, new_settings;</i>3. Перед вызовом функции
вам следует изменить характеристики терминала, этим определяется место следующих строк:getchoiceif (!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/tty\n");exit(1);}<i> tcgetattr(fileno(input), &initial_settings);</i><i> new_settings = initial_settings;</i><i> new_settings.c_lfag &= ~ICANON;</i><i> new_settings.c_lflag &= ~ECHO;</i><i> new_settings.c_cc[VMIN] = 1;</i><i> new_settings.c_cc[VTIME] = 0;</i><i> new_settings.c_lflag &= ~ISIG;</i><i> if (tcsetattr(fileno(input), TCSANOW, &new_settings) != 0) {</i><i> fprintf(stderr, "could not set attributes\n");</i><i> }</i>4. Перед завершением вы также должны вернуть первоначальные значения:
do {choice = getchoice("Please select an action", menu, input, output);printf("You have chosen: %c\n", 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: %s\n", greet);option = choices;while (*option) {fprintf(but, "%s\n", *option);option++;}do {selected = fgetc(in);<i> } while (selected == '\n' || selected == '\r');</i>option = choices;while (*option) {if (selected == *option[0]) {chosen = 1;break;}option++;}if (!chosen) {fprintf(out, "Incorrect choice, select again\n");}} while(!chosen);return selected;}Пока вы не устроите все иначе, теперь, если пользователь нажмет в вашей программе комбинацию клавиш <Ctrl>+<C>, программа завершится. Вы можете отключить обработку этих специальных символов, очистив флаг
в локальных режимах. Для этого в функциюISIGвключается следующая строка:main<i>new_settings.c_lflag &= ~ISIG;</i>Если вы внесете эти изменения в вашу программу меню, то будете получать немедленный отклик, и вводимый вами символ не будет отображаться на экране.