Кроме того, что уже было отмечено, эти функции возвращают 0 в случае успеха и -1 при ошибке. Вызовы функций, которые можно использовать для управления терминалом, описаны ниже.
int tcgetattr(int fd, struct termios * t);
Восстанавливает текущие настройки файлового дескриптора fd и помещает их в структуру, на которую указывает t.
int tcsetattr(int fd, int options, struct termios * t);
Устанавливает текущие настройки терминала для файлового дескриптора fd в настройки, приведенные в t. Всегда используйте tcgetattr() для заполнения t, затем модифицируйте его. Никогда не заполняйте t вручную: некоторые системы требуют установки или снятия флагов, кроме флагов, определенных POSIX, поэтому заполнение вручную является непереносимым.
Аргумент options определяет, когда изменения вступают в силу.
TCSANOW Изменение немедленно вступает в силу. TCSADRAIN Изменение вступает в силу после того, как передаются все входные данные, уже записанные в fd; перед вступлением в силу оно очищает очередь. Необходимо использовать это при смене выходных параметров. TCSAFLUSH Изменение вступает в силу после того, как выходная очередь была очищена; входная же очередь отбрасывается перед вступлением изменений в силу.
Если система не может обработать некоторые настройки, например, скорость передачи данных, ей разрешается игнорировать их без выдачи сообщения об ошибке. Единственный способ, с помощью которого можно узнать, были ли приняты настройки — вызвать tcgetattr() и сравнить содержимое возвращаемой им структуры с содержимым структуры, переданной tcsetattr().
Поэтому более переносимые приложения используют код вроде показанного ниже.
#include <termios.h>
struct termios save;
struct termios set;
struct termios new;
int fd;
...
tcgetattr(fd, &save);
set = save;
cfsetospeed(&set, B2400);
cfsetispeed(&set, B2400);
tcsetattr(fd, &set);
tcgetattr(fd, &new);
if ((cfgetospeed(&set) != B2400) ||
(cfgetispeed(&set) != B2400)) {
/* объяснение */
}
Обратите внимание, что если не имеет значения, "зависнет" ли настройка termios, лучше проигнорировать это условие, как делается в robin.
speed_t cfgetospeed(struct termios * t);
speed_t cfgetispeed(struct termios * t);
Извлекает скорость, соответственно, вывода или ввода из t. Эти функции возвращают символическую скорость, такую же, которая дается cfsetospeed() и cfsetispeed().
int cfsetospeed(struct termios * t, speed_t speed);
int cfsetispeed(struct termios * t, speed_t speed);
Устанавливает, соответственно, вывода или ввода в t на speed. Обратите внимание, что эта функция не меняет скорость соединения на любом файловом дескрипторе; она просто устанавливает скорость в структуре termios. Скорость, как и другие характеристики, применяется к файловому дескриптору с помощью tcsetattr().
Эти функции принимают символическую скорость — то есть число, соответствующее определению одного из следующих макросов, имена которых определяют скорость в битах в секунду: B0 (0 бит в секунду, определяет отключенное состояние) B50, B75, B110, B134[113], B150, B200, B300, B600, B1200, B1800, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, B3500000 или B4000000. B57600 и выше в POSIX не описаны; переносимые исходные коды использует их только в том случае, если они защищены операторами #ifdef.
По мере того, как будут разрабатываться драйверы Linux для оборудования, поддерживающего другие скорости передачи данных, в заголовочный файл будут добавляться новые символические скорости.
В настоящий момент скорость ввода игнорируется. Интерфейс termios устанавливает отдельные скорости ввода и вывода для асинхронного оборудования, допускающего раздельные скорости, но такое оборудование встречается довольно редко. Просто вызовите cfsetospeed() и cfsetispeed() попарно, чтобы ваш код продолжил работать в системах, поддерживающих раздельные скорости.
Не все tty поддерживают все скорости — последовательные порты на стандартных ПК не поддерживают более 115 200 бит/с. Как уже упоминалось выше, если для вас имеет значение, вступит ли в силу определенная настройка, необходимо использовать tcgetattr() для проверки после того, как вы попытаетесь установить ее с помощью tcsetattr(). Также обратите внимание, что установленная вами скорость является необязательной. Некоторые tty, например, локальные консоли, благополучно принимают и игнорируют любую установленную вами скорость.
int tcsendbreak(int fd, int duration)
Посылает поток нулей в fd, чтобы узнать определенную длительность (duration), которая также известна как разрыв. Если duration равняется 0, разрыв длится не менее 250 и не более 500 миллисекунд. К сожалению, POSIX не определяет элемент, длительность которого измеряется, поэтому единственной переносимой величиной для duration является 0. В Linux длительность увеличивает разрыв; 0 или 1 задают длительность между четвертью секунды и полсекунды; 2 — между полсекунды и секундой и так далее.
int tcdrain(int fd)
Ожидает, пока не передадутся все входные данные, ожидающие в данный момент на файловом дескрипторе fd.
int tcflush(int fd, int queue_selector)
Отбрасывает некоторые данные в файловом дескрипторе fd в зависимости от величины queue_selector.
TCIFLUSH Сбрасывает на диск все полученные, но еще не прочитанные интерфейсом данные. TCOFLUSH Сбрасывает на диск все данные, записанные в интерфейс, но еще не отправленные. TCIOFLUSH Сбрасывает на диск все ожидающие входные и выходные данные.
int tcflow(int fd, int action)
Приостановить или возобновить вывод или ввод в файловом дескрипторе fd. Более точные действия определяются action.
TCOOFF Приостановить вывод. TCOON Восстановить вывод. TCIOFF Передать символ STOP, запрашивающий прекращение передачи символов вторым концом соединения. TCION Передать символ START, запрашивающий восстановление передачи символов вторым концом соединения.
Обратите внимание, что TCIOFF и TCION необязательны, и даже если второй конец соединения принимает их на обработку, перед этим может возникнуть задержка.
16.5.2. Размеры окна
Существуют два запроса ioctl(), которые, к сожалению, не были закодированы как часть интерфейса termios, хотя и должны были. Размер tty, измеряемый строками и столбцами, должен управляться tcgetwinsize() и tcsetwinsize(), но, поскольку они не существуют, вместо этого следует использовать ioctl(). Для запроса текущего размера и установки нового размера применяйте структуру struct winsize.
#include <termios.h>
struct winsize {
unsigned short ws_row; /* количество строк */
unsigned short ws_col; /* количество столбцов */
unsigned short ws_xpixel; /* не используется */
unsigned short ws_ypixel; /* не используется */
};
Для запроса текущего размера используйте следующий вызов:
struct winsize ws;
ioctl(fd, TIOCGWINSZ, &ws);
Для установки нового размера заполните struct winsize и предусмотрите такой вызов:
ioctl(fd, TIOCSWINSZ, &ws);
В конце этой главы представлен пример условий, при которых возникает потребность в установке нового размера окна.
При изменении размеров окна лидеру группы процессов переднего плана на данном tty передается сигнал SIGWINCH. Ваш код может перехватить этот сигнал; используйте TIOCGWINSZ для запроса нового размера и внесите в свою программу все необходимые изменения.
16.5.3. Флаги
Четыре флаговых переменных — c_iflag, с_oflag, c_cflag и c_lflag — хранят флаги, управляющие определенными характеристиками. Заголовочный файл <termios.h> предоставляет символические константы битовых масок, которые, в свою очередь, предоставляют эти флаги. Устанавливайте их с помощью |= и переустанавливайте с помощью &= и как показано ниже.