Символ STATUS (обычно вводится как Ctrl+T) заставляет ядро вывести данные о состоянии терминала (включая состояние активного процесса и количество израсходованного процессорного времени) и отправляет сигнал SIGINFO активной группе процессов. При желании процесс может перехватить этот сигнал и вывести дополнительные сведения (Linux предоставляет похожую возможность в виде так называемой
Системы, основанные на System V, поддерживают символ SWTCH, используемый для переключения между
В листинге 58.1 показано, как с помощью функций tcgetattr() и tcsetattr() можно изменить символ
Использование данной программы продемонстрировано в следующей сессии командной строки. Вначале мы применим для прерывания символ Ctrl+L (код ASCII 12), а затем проверяем изменения с помощью команды stty:
$ ./new_intr 12
$ stty
speed 38400 baud; line = 0;
intr = ^L;
Затем запускаем процесс, выполняющий команду sleep(1). Мы обнаружим, что нажатие Ctrl+C больше не приводит к завершению процесса и для этого нужно нажать Ctrl+L.
$ sleep 10
^C
Теперь выведем значение переменной среды $? которое содержит код завершения последней команды:
$ echo $?
130
Как видите, код завершения процесса был равен 130. Из этого следует, что процесс был завершен с помощью сигнала с номером 130–128 = 2, то есть SIGINT.
Воспользуемся нашей командной строкой, чтобы отключить символ прерывания.
$ ./new_intr
$ stty
speed 38400 baud; line = 0;
intr =
В итоге можно обнаружить, что ни Ctrl+C, ни Ctrl+L не генерируют сигнал SIGINT и для завершения программы нужно нажать Ctrl+\:
$ sleep 10
^C^L
Quit
$ stty sane
Листинг 58.1. Изменение символа прерывания терминала
tty/new_intr.c
#include
#include
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
struct termios tp;
int intrChar;
if (argc > 1 && strcmp(argv[1], "-help") == 0)
usageErr("%s [intr-char]\n", argv[0]);
/* Определяем новый параметр INTR из командной строки */
if (argc == 1) { /* Отключаем */
intrChar = fpathconf(STDIN_FILENO, _PC_VDISABLE);
if (intrChar == -1)
errExit("Couldn't determine VDISABLE");
} else if (isdigit((unsigned char) argv[1][0])) {
intrChar = strtoul(argv[1], NULL, 0);
/* Поддерживает шестнадцатеричные и восьмеричные значения */
} else { /* Литерал */
intrChar = argv[1][0];
}
/* Получаем текущие параметры терминала, изменяем символ INTR
и отправляем изменения драйверу терминала */
if (tcgetattr(STDIN_FILENO, &tp) == -1)
errExit("tcgetattr");
tp.c_cc[VINTR] = intrChar;
if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &tp) == -1)
errExit("tcsetattr");
exit(EXIT_SUCCESS);
}
tty/new_intr.c
58.5. Флаги терминала
В табл. 58.2 перечислены параметры, управляемые каждым из четырех полей структуры termios, предназначенных для хранения флагов. Приведенные константы соответствуют одиночным битам. Исключение составляют битовые маски, способные вмещать несколько битов; они поддерживают сочетания значений, перечисленные в скобках. В столбце с названием SUSv3 указаны флаги, входящие в одноименный стандарт. Столбец «Включен» показывает стандартные параметры при входе в систему с помощью виртуальной консоли.
Многие командные оболочки с функцией редактирования текста предоставляют собственные механизмы изменения флагов, перечисленных в табл. 58.2. Это значит следующее: изменение данных параметров путем утилиты stty(1) может не повлиять на ввод консольных команд. Чтобы этого избежать, следует отключить функцию редактирования в командной оболочке. Например, чтобы сделать это в оболочке bash, нужно запустить ее с параметром командной строки — noediting.
Таблица 58.2. Флаги терминала
Поле/флаг
Описание
Включен
SUSv3
c_iflag
BRKINT
Сигнал прерывания (SIGINT) при условии BREAK
Да
*
ICRNL
Привязка CR к NL во время ввода
Да
*
IGNBRK
Игнорирование условия BREAK
Нет
*
IGNCR
Игнорирование CR при вводе
Нет
*
IGNPAR