Эта программа запирает терминал пользователя. Она запрашивает пользователя ввести «ключ». Конечно, пользователю было бы удобнее, чтобы ключ совпадал с его паролем, но в современных Unix-системах хэши паролей доступны только пользователю root, поэтому ключ необходимо вводить при запуске программы. Эхо выключено, поэтому ключ не будет показан на терминале. Этот же ключ должен быть введен, чтобы получить доступ к терминалу. Программа работает так:
9 Объявляет структуру termios для сохранения установок терминала.
10 Объявляет переменную tcflag_t для сохранения текущих значений c_lflag.
11 Объявляет массив символов для сохранения значения первого ключа. Ключ может быть очень длинным, так как BUFSIZ имеет большое значение.
13 Программа получает текущие установки терминала. Первый параметр - дескриптор файла стандартного ввода, полученный макросом fileno, определенным в <stdio.h>. Если stdin переназначен, то программа работать не будет. Второй аргумент - адрес структуры termios.
14 Сохраняется значение поля c_lflag. Это значение затем будет использовано для восстановления состояния терминального интерфейса.
15-16 Запрещается сравнение ввода с управляющими символами INTR, QUIT, SUSP и DSUSP. Эхо выключается. tcsetattr(3C) вызывается с флагом TCSAFLUSH для изменения состояния терминального интерфейса и сброса всех введенных символов.
17 Запоминается ключ, который позднее будет использован для отпирания терминала.
18-25 Для того, чтобы выйти из этого цикла, программа должна получить значение, совпадающее со значением исходного ключа. Если ключи совпадают, терминальный интерфейс возвращается в исходное состояние. Это не делается автоматически при завершении программы. Если программа завершится ненормально, терминал может остаться в странном состоянии.
28 Эта функция возвращает указатель на строку символов, которая содержит ключ, введенный пользователем.
30 Объявляется массив символов для сохранения значения ключа. Он объявлен как static, и указатель на этот массив будет возвращен функцией.
32 Выдается приглашение
33 Первый символ в массиве line[] устанавливается в невозможное значение. Для чего это нужно? Ответ: Если getkey() был вызван во второй раз, и был введен только EOF, не будет считано ни одного символа; содержимое line[] будет тем же, что и раньше, и возвращенная строка совпадет со значением, полученным от первого вызова этой функции, что совершенно неправильно.
34 Строка ввода считывается без эхо. Не делается проверки на совпадение с управляющими символами, такими как INTR, QUIT и т.д. Эти символы обрабатываются так же, как обычные.
Файл: termlock.c
ЗАПИРАНИЕ ТЕРМИНАЛА - ПРИМЕР
1 #include <string.h>
2 #include <unistd.h>
3 #include <stdio.h>
4 #include <termios.h>
5 static char *getkey(void);
7 main() /* lock the terminal */
8 {
9 struct termios tty;
10 tcflag_t savflags;
11 char key[BUFSIZ];
13 tcgetattr(fileno(stdin), &tty);
14 savflags = tty.c_lflag;
15 tty.c_lflag &= ~(ISIG | ECHO);
16 tcsetattr(fileno(stdin), TCSAFLUSH, &tty);
17 strcpy(key, getkey());
18 for (;;) {
19 if (strcmp(key, getkey()) == 0){
20 tty.c_lflag = savflags;
21 tcsetattr(fileno(stdin), TCSAFLUSH, &tty);
22 break;
23 }
24 fprintf(stderr,"incorrect key try again.\n");
25 }
26 }
28 static char *getkey(void) /* prompt user for key */
29 {
30 static char line[BUFSIZ];
32 fputs("Key: ", stderr);
33 line[0] = '\377'; /*change first char for EOF to fgets*/