Рейтинговые книги
Читем онлайн Разработка приложений в среде Linux. Второе издание - Майкл Джонсон

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 74 75 76 77 78 79 80 81 82 ... 150

fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) & ~O_NONBLOCK);

Четыре флага termios контролируют четыре отдельных части управления вводом и выводом. Флаг входных данных, с_iflag, определяет, каким образом интерпретируются и обрабатываются принятые символы. Флаг выходных данных, c_oflag, определяет, каким образом интерпретируются и обрабатываются символы, записываемые вашим процессом в tty. Управляющий флаг, c_cflag, определяет характеристики последовательного протокола устройства и полезен лишь для физических устройств. Локальный флаг, c_lflag, определяет, каким образом символы собираются и обрабатываются перед отправкой на обработку выходных данных. На рис. 16.1 показана упрощенная схема того, какое место занимает каждый флаг в общей схеме обработки символов.

Рис. 16.1. Упрощенная схема обработки tty

Сначала мы продемонстрируем способы применения termios, а затем представим короткую справку о нем.

16.3. Примеры использования termios

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, "Сбой при отключении эхо-контроляn");

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 был завершающий символ n */

35:

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

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

38:

39:  exit(0);

40: }

16.3.2. Последовательные коммуникации

В качестве примера программирования обоих концов tty рассмотрим программу, подключающую текущий терминал к последовательному порту. На одном tty программа под названием robin сообщается с вами во время набора. На другом tty она взаимодействует с последовательным портом. С целью мультиплексирования вводных и выходных данных на локальном tty и последовательном порте программа использует системный вызов poll(), описанный в главе 13.

Ниже приведен полный код программы robin.с, за которым даны объяснения.

  1: /* robin.с */

  2:

  3: #include <sys/poll.h>

  4: #include <errno.h>

  5: #include <fcntl.h>

  6: #include <popt.h>

  7: #include <stdio.h>

  8: #include <stdlib.h>

  9: #include <signal.h>

 10: #include <string.h> /* для strerror() */

 11: #include <termios.h>

 12: #include <unistd.h>

 13:

 14: void die(int exitcode, const char *error, const char *addl) {

 15:  if (error) fprintf(stderr, "%s: %sn", error, addl);

 16:  exit(exitcode);

 17: }

 18:

 19: speed_t symbolic_speed(int speednum) {

 20:  if (speednum >= 460800) return B460800;

 21:  if (speednum >= 230400) return B230400;

 22:  if (speednum >= 115200) return B115200;

 23:  if (speednum >= 57600) return B57600;

 24:  if (speednum >= 38400) return B38400;

 25:  if (speednum >= 19200) return B19200;

 26:  if (speednum >= 9600) return B9600;

 27:  if (speednum >= 4800) return B4800;

 28:  if (speednum >= 2400) return B2400;

 29:  if (speednum >= 1800) return B1800;

 30:  if (speednum >= 1200) return B1200;

 31:  if (speednum >= 600) return B600;

 32:  if (speednum >= 300) return B300;

 33:  if (speednum >= 200) return B200;

 34:  if (speednum >= 150) return B150;

 35:  if (speednum >= 134) return B134;

 36:  if (speednum >= 110) return B110;

 37:  if (speednum >= 75) return B75;

 38:  return B50;

 39: }

 40:

 41: /* Это нужно для области видимости в пределах файла, так что

 42:  * их можно будет использовать в обработчиках сигналов */

 43: /* старые настройки порта termios для восстановления */

 44: static struct termios pots;

 45: /* старые настройки stdout/stdin termios для восстановления */

 46: static struct termios sots;

 47: /* файловый дескриптор порта */

 48: int pf;

 49:

 50: /* восстановить первоначальные настройки терминала при выходе */

 51: void cleanup_termios(int signal) {

 52:  tcsetattr(pf, TCSANOW, &pots);

 53:  tcsetattr(STDIN_FILENO, TCSANOW, &sots);

 54:  exit(0);

 55: }

 56:

 57: /* обработать одиночный управляющий символ */

 58: void send_escape(int fd, char c) {

 59:  switch (c) {

 60:  case 'q':

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

 62:   cleanup_termios(0);

 63:   break;

 64:  case 'b':

 65:   /* послать символ разрыва*/

 66:   tcsendbreak(fd, 0);

 67:   break;

 68:  default:

 69:   /* пропустить символ */

 70:   /* "C- C-" sends "C-" */

 71:   write(fd, &c, 1);

 72:   break;

 73:  }

 74:  return;

 75: }

 76:

 77: /* обработать управляющие символы, записывая их в вывод */

 78: void cook_buf(int fd, char * buf, int num) {

 79:  int current = 0;

 80:  static int in_escape = 0;

 81:

 82:  if (in_escape) {

 83:   /* cook_buf последний раз вызывался с незавершенной

 84:      управляющей последовательностью */

 85:   send_escape(fd, buf[0]);

 86:   num--;

 87:   buf++;

 88:   in_escape = 0;

 89:  }

 90:  while (current < num) {

 91: # define CTRLCHAR(c) ((c)-0x40)

 92:   while ((current < num) && (buf[current] != CTRLCHAR('W')))

 93:    current++;

 94:   if (current) write (fd, buf, current);

 95:   if (current < num) {

 96:    /* найден управляющий символ */

 97:    current++;

 98:    if (current >= num) {

 99:     /*интерпретировать первый символ следующей последовательности*/

100:     in_escape = 1;

101:     return;

102:    }

103:    send_escape(fd, buf[current]);

104:   }

105:   num -= current;

106:   buf += current;

107:   current = 0;

108:  }

109:  return;

110: }

111:

112: int main(int argc, const char * argv[]) {

113:  char с; /* используется для разбора аргументов */

114:  struct termios pts; /* настройки termios для порта */

115:  struct termios sts; /* настройки termios для stdout/stdin */

116:  const char *portname;

117:  int speed = 0; /* используется при разборе аргументов для скорости */

118:  struct sigaction sact; /* используется для инициализации обработчика сигналов */

1 ... 74 75 76 77 78 79 80 81 82 ... 150
На этой странице вы можете бесплатно читать книгу Разработка приложений в среде Linux. Второе издание - Майкл Джонсон бесплатно.
Похожие на Разработка приложений в среде Linux. Второе издание - Майкл Джонсон книги

Оставить комментарий