16.3.1. Пароли

16.3.1. Пароли

Самой распространенной причиной модификации установок termios является чтение пароля без эхо-контроля символов. Для этого следует отключить локальное эхо во время чтения пароля. Ваш код должен выглядеть следующим образом:

struct termios ts, ots;

Первая структура хранит оригинальные установки для восстановления, а вторая является копией для модификации.

tcgetattr(STDIN_FILENO, &ts);

Обычно пароли читаются со стандартного устройства ввода.

ots = ts;

Сохраните копию оригинальных установок termios, чтобы позже восстановить их.

ts.c_lflag &= ~ECHO;

ts.c_lflag |= ECHONL;

tcsetattr(STDIN_FILENO, TCSAFLUSH, fits);

Отключите эхо-контроль символов (кроме символов новой строки) после завершения обработки всех выходных данных. (Первая l в c_lflag означает локальную (local) обработку.)

read_password();

Теперь вы читаете пароль. Это может быть простой вызов fgets() или read(), либо же более сложная обработка, в зависимости от режима tty (неформатируемый режим или режим обработки) и от требований программы.

tcsetattr(STDIN_FILENO, TCSANOW, &ots);

Это немедленно восстанавливает исходные установки termios. (Остальные опции объясняются позже, в справочном разделе далее в главе.)

Полный код программы-примера, readpass, показан ниже.

 1: /* readpass.с */

 2:

 3: #include <stdio.h>

 4: #include <stdlib.h>

 5: #include <termios.h>

 6: #include <unistd.h>

 7:

 8: int main (void) {

 9:  struct termios ts, ots;

10:  char passbuf[1024];

11:

12:  /* получить и сохранить текущие настройки termios */

13:  tcgetattr(STDIN_FILENO, &ts);

14:  ots = ts;

15:

16:  /* изменить и установить новые настройки termios */

17:  ts.c_lflag & = ~ECHO;

18:  ts.c_lflag |= ECHONL;

19:  tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts);

20:

21:  /*хоть это и параноидально, но проверить, возымели ли эффект новые настройки*/

22:  tcgetattr(STDIN_FILENO, &ts);

23:  if (ts.c_lflag & ECHO) {

24:   fprintf(stderr, "Сбой при отключении эхо-контроля ");

25:   tcsetattr(STDIN_FILENO, TCSANOW, &ots);

26:   exit(1);

27:  }

28:

29:  /* получить и вывести пароль */

30:  printf("введите пароль:");

31:  fflush(stdout);

32:  fgets(passbuf, 1024, stdin);

33:  printf("прочитан пароль: %s", passbuf);

34:  /* в passbuf был завершающий символ */

35:

36:  /* восстановить старые настройки termios */

37:  tcsetattr(STDIN_FILENO, TCSANOW, &ots);

38:

39:  exit(0);

40: }