Чтение онлайн

ЖАНРЫ

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

 59: /* установить обработчик SIGWINCH */

 60: act.sa_handler = sigwinch_handler;

 61: sigemptyset(&(act.sa_mask));

 62: act.sa_flags = 0;

 63: if (sigaction(SIGWINCH, &act, NULL) < 0) {

 64: perror("ptypair: невозможно обработать SIGWINCH");

 65: exit(1);

 66: }

 67:

 68: /* Обратите внимание, что настройки termios устанавливаются только

 69: *
для стандартного ввода; ведущая сторона pty НЕ является tty.

 70: */

 71: tcgetattr(STDIN_FILENO, &ot);

 72: t = ot;

 73: t.c_lflag &= ~(ICANON | ISIG | ECHO | ECHOCTL | ECHOE |

 74: ECHOK | ECHOKE | ECHONL | ECHOPRT);

 75: t.c_iflag |= IGNBRK;

 76: t.c_cc[VMIN] = 1;

 77: t.c_cc[VTIME] = 0;

 78: tcsetattr(STDIN_FILENO, TCSANOW, &t);

 79:

 80: /* Этот код взят без изменений из robin.с

 81: * Если дочерний процесс завершается, читающая ведущая сторона

 82: * дoлжнa вернуть -1 и завершиться.

 83: */

 84: ufds[0].fd = STDIN_FILENO;

 85: ufds[0].events = POLLIN;

 86: ufds[1].fd = master;

 87: ufds[1].events = POLLIN;

 88:

 89: do {

 90: int r;

 91:

 92: r = poll(ufds, 2, -1);

 93: if ((rs < 0) && (errno != EINTR)) {

 94: done = 1;

 95: break;

 96: }

 97:

 98: /* сначала проверить возможность завершения */

 99: if ((ufds[0].revents | ufds[1].revents) &

100: (POLLERR | POLLHUP | POLLNVAL)) {

101: done = 1;

102: break;

103: }

104:

105: if (propagate_sigwinch) {

106: /* обработчик сигналов запросил распространение SIGWINCH */

107: if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) < 0) {

108: perror("ptypair: не удается получить размеры окна");

109: }

110: if (ioctl(master, TIOCSWINSZ, &ws) < 0) {

111: perror("не удается восстановить размеры окна");

112: }

113:

114: /* не делать этого снова до поступления следующего SIGWINCH */

115: propagate_sigwinch = 0;

116:

117: /* опрос мог быть прерван SIGWINCH,

118: * потому повторить попытку.

119: */

120: continue;

121: }

122:

123: if (ufds[1].revents & POLLIN) {

124: i = read (master, buf, BUFSIZE);

125: if (i >= 1) {

126: write(STDOUT_FILENO, buf, i);

127: } else {

128: done = 1;

129: }

130: }

131:

132: if (ufds[0].revents & POLLIN) {

133: i = read (STDIN_FILENO, buf, BUFSIZE);

134: if (i >= 1) {

135: write(master, buf, i);

136: } else {

137: done = 1;

138: }

139: }

140:

141: } while (!done);

142:

143: tcsetattr(STDIN_FILENO, TCSANOW, &ot);

144: exit(0);

145: }

Программа

forkptytest.с
делает очень немногое из того, чего вы раньше не видели. Обработка сигналов рассматривается в главе 12, а цикл
poll
почти полностью переписан из кода
robin.с
, представленного ранее в этой главе (за исключением обработки управляющих символов), равно как и код, модифицирующий настройки
termios
.

Остается лишь объяснить распространение изменений размеров окна.

В строке 105 после завершения

poll
мы проверяем, является ли причиной завершения
poll
сигнал
SIGWINCH
, доставляемый функции
sigwinch_handler
в строке 20. Если это так, необходимо получить новый размер текущего окна из стандартного ввода и распространить его в pty подчиненного компонента. Установкой размера окна
SIGWINCH
передается автоматически процессу, работающему на pty; мы не должны явно передавать
SIGWINCH
этому процессу.

Теперь для сравнения посмотрите, насколько усложняется этот код в случае использования функций, определенных в

ptypair.с
.

1: /* ptytest.с */

2:

3: #include <errno.h>

4: #include <fcntl.h>

5: #include <signal.h>

6: #include <stdio.h>

7: #include <stdlib.h>

8: #include <string.h>

9: #include <sys/ioctl.h>

 10: #include <sys/poll.h>

 11: #include <sys/stat.h>

 12: #include <termios.h>

 13: #include <unistd.h>

 14: #include "ptypair.h"

 15:

 16:

 17: volatile int propagate_sigwinch = 0;

 18:

 19: /* sigwinch_handler

 20: * распространяет изменения размеров окна из входного файлового

Поделиться с друзьями: