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 передается 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: * распространяет изменения размеров окна из входного файлового
21: * дескриптора на ведущую сторону pty.
22: */
23: void sigwinch_handler(int signal) {
24: propagate_sigwinch = 1;
25: }
26:
27:
28: /* ptytest пытается открыть пару pty с запуском оболочки
29: * на подчиненной стороне pty.
30: */
31: int main(void) {
32: int master;
33: int pid;
34: char * name;
35: struct pollfd ufds[2];
36: int i;
