При изменении атрибутов терминала с помощью вызова tcsetattr() аргумент optional_actions определяет, когда именно эти изменения вступят в силу. Он может принимать одно из следующих значений.
• TCSANOW — изменение применяется немедленно.
• TCSADRAIN — изменение вступает в силу после передачи терминалу текущего содержимого исходящей очереди. Обычно этот флаг указывают при изменениях, влияющих на вывод терминала, чтобы не затронуть данные, которые уже попали в очередь, но еще не были выведены на экран.
• TCSAFLUSH — действуют те же правила, что и для TCSADRAIN, но с одним уточнением: любой ввод, находящийся в очереди на момент применения изменений, отклоняется. Это может пригодиться, например, при чтении пароля, когда мы хотим отключить эхо-контроль терминала и предотвратить отображение вводимых символов.
Общепринятым (и рекомендованным) способом изменения атрибутов терминала является извлечение структуры termios с копией текущих параметров с функции tcgetattr(), изменение интересующих атрибутов и затем запись обновленной информации обратно в драйвер с помощью функции tcsetattr() (этот подход гарантирует передачу данной функции полностью инициализированной структуры). Например, чтобы отключить эхо-контроль, можно воспользоваться следующим кодом:
struct termios tp;
if (tcgetattr(STDIN_FILENO, &tp) == -1)
errExit("tcgetattr");
tp.c_lflag &= ~ECHO;
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tp) == -1)
errExit("tcsetattr");
Функция tcsetattr() завершается успешно, если удалось изменить хотя бы
В подразделе 34.7.2 отмечалось: если вызов tcsetattr() выполняется в фоновой группе процессов, драйвер терминала приостанавливает эту группу, посылая ей сигнал SIGTTOU; следовательно, вызов tcsetattr() завершается ошибкой EIO, если его сделать из осиротевшей группы процессов. То же самое касается и некоторых других функций, описанных в данной главе, включая tcflush(), tcflow(), tcsendbreak() и tcdrain().
В старых версиях UNIX доступ к атрибутам терминала осуществлялся с помощью вызова ioctl(). Как и часть других функций, описанных в этой главе, tcgetattr() и tcsetattr() впервые появились в стандарте POSIX и были призваны решить проблему с третьим аргументом вызова ioctl(), тип которого невозможно проверить. В Linux, как и во многих других реализациях UNIX, функции tcgetattr() и tcsetattr() являются обертками поверх ioctl().
Команда stty является консольным аналогом функций tcgetattr() и tcsetattr(), позволяя просматривать и изменять атрибуты терминала из командной строки. Она может пригодиться при мониторинге, отладке или отмене изменений, вносимых в атрибуты терминала какой-либо программой.
Текущее состояние атрибутов терминала можно просмотреть с помощью следующей команды (в данном случае мы имеем дело с виртуальной консолью):
$ stty — a
speed 38400 baud; rows 25; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol =
eol2 =
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
— parenb — parodd cs8 hupcl — cstopb cread — clocal — crtscts
— ignbrk brkint — ignpar — parmrk — inpck — istrip — inlcr — igncr icrnl ixon — ixoff
— iuclc — ixany imaxbel — iutf8
opost — olcuc — ocrnl onlcr — onocr — onlret — ofill — ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok — echonl — noflsh — xcase — tostop — echoprt
echoctl echoke
Первая строка в вышеприведенном выводе содержит скорость последовательного порта (в битах в секунду), размер окна терминала и порядок следования строк в числовом виде (0 соответствует режиму перехода на новую строку N_TTY).
В следующих трех строчках находятся параметры различных специальных символов терминала. Так, ^C означает Ctrl+C и т. д. Строка
Остальные строки содержат параметры разных флагов из полей c_cflag, c_iflag, c_oflag и c_lflag структуры termios (именно в таком порядке). Флаги, имена которых начинаются с дефиса (-), отключены.
Если запустить команду stty без аргументов командной строки, она выведет только скорость последовательного порта, порядок следования строк и любые другие параметры с необычными значениями.
Чтобы изменить настройки специальных символов терминала, можно воспользоваться командами наподобие следующей:
$ stty intr ^L