('
') как о символах новой строки ('
'). Как и при отключении BRKINT это действует лишь тогда, когда сеанс регистрации присоединяется к другому последовательному порту. Также это действует тогда, когда символы возврата каретки не игнорируются (то есть если не установлен флаг IGNCR).
Функция IGNBRK заставляет драйвер tty игнорировать разрывы. Включение IGNBRK будет здесь излишним. При установке IGNBRK игнорируется BRKINT. Но не беда, если вы установите обе функции.
Это флаги обработки входных данных. Также модифицируется локальный флаг обработки: отключается ISIG. Это предотвращает драйвер tty от передачи SIGINT, SIGQUIT и SIGTSTP при получении соответствующего символа (INTR, QUIT или SUSP). Мы делаем это потому, что хотим переслать эти символы на удаленную систему (или на другое устройство, подключенное к последовательному порту) для последующей обработки там.
Затем следует обработка опций. В некоторых случаях модификаций настроек termios по умолчанию может оказаться недостаточно, или же, наоборот, слишком много. В таких случаях мы предлагаем некоторые опции командной строки для модификации опций termios.
По умолчанию мы оставляем последовательный порт в том состоянии управления потоком, в котором мы его находим. Однако в строке 212 есть опции аппаратного управления потоком (использующего управляющие провода CTS и RTS), программного управления потоком (резервирование ^S и ^Q для STOP и START соответственно) и полного отключения управления потоком.
212: case 'h':
213: /* аппаратное управление потоком */
214: pts.c_cflag |= CRTSCTS;
215: pts.c_iflag &= ~(IXON | IXOFF | IXANY);
216: break;
217: case 's' :
218: /* программное управление потоком */
219: pts.c_cflag &= ~CRTSCTS;
220: pts.c_iflag |= IXON | IXOFF | IXANY;
221: break;
222: case 'n':
223: /* отключение управления потоком */
224: pts.q._cflag &= ~CRTSCTS;
225: pts.c_iflag &= ~(IXON | IXOFF | IXANY);
226: break;
Обратите внимание, что программное управление потоком включает три флага.
IXON | Прекратить пересылать выходные данные при получении символа STOP (обычно ^S) и начать заново при получении символа START (обычно ^Q). |
IXOFF | Передать символ STOP, когда во входящем буфере накопится слишком много данных. В случае прочтения достаточного количества данных отправите символ START. |
IXANY | Позволить любому принятому символу, не только START, перезапустить вывод. (Этот флаг обычно реализован в системах Unix, но не определен в POSIX.) |
Когда другая программа использует robin как вспомогательную, может помешать обработка спецсимволов (robin обычно интерпретирует последовательность ^ ), поэтому во избежание такой обработки устанавливается неформатируемый режим. В строке 120 мы предоставляем переменную, определяющую, включен ли неформатируемый режим; по умолчанию этот режим не включается. В строке 140 мы сообщаем popt о том, как информировать, когда в командной строке была указана опция -r или -raw, включающая неформатируемый режим.
Некоторые системы требуют передачи им символа возврата каретки для представления новой строки. Слово 'системы' здесь следует понимать буквально; например, это применимо ко многим интеллектуальным периферийным устройствам, например, источникам бесперебойного питания (UPS) с последовательными портами, поскольку они предназначены для функционирования в DOS, где пара 'возврат каретки/перевод строки' всегда используется для обозначения новой строки. В строке 228 определяется это DOS-ориентированное поведение.
228: if (crnl) {
229: /* послать CR с NL */
230: pts.c_oflag |= ONLCR;
231: }
Последняя часть обработки опций управляет скоростью передачи в битах в секунду[111]. Вместо включения огромного вложенного оператора выбора мы вызываем уже описанную ранее функцию symbolic_speed(), чтобы получить speed_t, понимаемый termios, как показано в строке 233.
233: /* скорость не изменяется, пока не будет указано -b */
234: if (speed) {
235: cfsetospeed(&pts, symbolic_speed(speed));
236: cfsetispeed(&pts, symbolic_speed(speed));
237: }
Перед тем, как зафиксировать изменения наших копий структур termios, в строке 241 регистрируются обработчики для важных сигналов, которые могут в противном случае вызвать уничтожение процесса и оставить tty в неформатируемом состоянии. Более подробно обработчики сигналов рассматриваются в главе 12.
241: sact.sa_handler = cleanup_termios;
242: sigaction(SIGHUP, &sact, NULL);
243: sigaction(SIGINT, &sact, NULL);
244: sigaction(SIGPIPE, &sact, NULL);
245: sigaction(SIGTERM, &sact, NULL);
Как только обработчик сигналов окажется на месте для восстановления старых настроек termios в случае уничтожения robin, мы можем благополучно обновить установки termios.
248: tcsetattr(pf, TCSANOW, &pts);
249: tcsetattr(STDIN_FILENO, TCSANOW, &sts);
На этом этапе программа robin готова читать и записывать символы. У robin есть два файловых дескриптора для чтения: данные с последовательного порта и данные с клавиатуры. Для мультиплексирования ввода-вывода между четырьмя файловыми дескрипторами используется poll() (см. главу 13).
Цикл poll() делает упрощенческое предположение о том, что он всегда может записать столько, сколько в состоянии прочитать. Это почти всегда верно и не вызывает проблем на практике, поскольку блокирование на короткие периоды незаметно при нормальных условиях. Цикл никогда
