Разработка приложений в среде Linux. Второе издание
Шрифт:
Функция
forkpty
работает так же, как и openpty
, но вместо возврата файлового дескриптора подчиненного компонента она разветвляет псевдотерминал как управляющий терминал stdin, stdout и stderr для дочернего процесса, а затем, подобно fork
, возвращает идентификатор дочернего процесса родительскому и 0 дочернему либо -1 при возникновении ошибки. Даже с этими удобными интерфейсами связана значительная проблема: аргумент name был изначально предназначен для возврата имени устройства псевдотерминала вызывающему коду, но его использование небезопасно, поскольку
openpty
и forkpty
не знают размера буфера.
NULL
в аргументе name
. Используйте функцию ttyname
, описанную в начале этой главы, чтобы получить путевое имя файла устройства псевдотерминала. Предпочтительный способ работы с
struct termios
заключается в использовании цикла чтение-модификация-запись, но данному случаю это не соответствует по двум причинам. Можно передать NULL
и принять значения по умолчанию, что достаточно в большинстве случаев; а когда вы хотите предоставить настройки termios
, вы часто заимствуете настройки у другого tty, или знаете точно, какими они должны быть (например, в случае концентратора последовательного порта SCSI, описанного ранее в этой главе). tcgetattr(STDIN_FILENO, &term);
ioctl(STDIN_FILENO, TIOCGWINSZ, &ws);
pid = forkpty(&masterfd, NULL, &term, &ws);
16.6.3. Сложные способы открытия псевдотерминалов
Интерфейс Unix98 для распределения пары псевдотерминала представляет собой следующий набор функций.
#define _XOPEN_SOURCE 600
#include <stdlib.h>
#include <fcntl.h>
int posix_openpt(int oflag);
int grantpt(int fildes);
int unlockpt(int fildes);
char * ptsname(int fildes);
Функция
posix_openpt
— это то же, что и открытие устройства /dev/ptmx
, но теоретически она более переносима (поскольку везде принимается). Рекомендуется в этот раз использовать open("/dev/ptmx", oflag)
для максимальной практической переносимости. Если вы хотите установить один или два флага open
или posix_openpt
, используйте O_RDWR
, как обычно; если вы вместо этого не открываете управляющий tty для процесса, используйте O_RDWR | O_NOCTTY
. open
или posix_openpt
вернет открытый файловый дескриптор управляющему устройству псевдотерминала. Затем вызовите grantpt
с файловым дескриптором управляющего устройства псевдотерминала, возвращенным из posix_openpt
, для изменения режима и владельца подчиненного компонента псевдотерминала, а потом — unlockpt
, чтобы сделать подчиненный компонент псевдотерминала доступным для открытия. Интерфейс Unix98 для открытия подчиненного устройства псевдотерминала должен просто открыть имя, возвращенное ptsname
. Все эти функции возвращают – 1
в случае ошибки, кроме ptsname
, возвращающей в такой ситуации NULL
. Функции в
ptypair.c
распределяют согласованную пару устройств pty. Пример функции get_master_pty
в строке 22 ptypair.с
открывает управляющее устройство pty и возвращает файловый дескриптор родительскому
get_slave_pty
в строке 87 может быть использована после fork
для открытия соответствующего подчиненного компонента pty. 1: /* ptypair.c */
2:
3: #define _XOPEN_SOURCE 600
4: #include <errno.h>
5: #include <fcntl.h>
6: #include <grp.h>
7: #include <stdlib.h>
8: #include <string.h>
9: #include <sys/types.h>
10: #include <sys/stat.h>
11: #include <unistd.h>
12:
13:
14: /* get_master_pty принимает дважды косвенный символьный указатель на
15: * место помещения имени подчиненного компонента pty и возвращает целочисленный
16: * файловый дескриптор. Если возвращается значение < 0, значит, возникла ошибка.
17: * В противном случае возвращается файловый дескриптор ведущего устройства pty
18: * и заполняет *name именем соответствующего подчиненного компонента pty. После
19: * открытия подчиненного компонента pty, вы отвечаете за освобождение *name.
20: */
21:
22: int get_master_pty(char **name) {
23: int i, j;
24: /* значение по умолчанию, соответствующее ошибке */
25: int master = -1;
26: char *slavename;
27:
28: master = open("/dev/ptmx", O_RDWR);
29: /* Это эквивалентно, хотя и более широко реализовано,
30: * но теоретически менее переносимо, следующему:
31: * master = posix_openpt(O_RDWR);
32: */
33:
34: if (master >= 0 && grantpt(master) >= 0 &&
3
5: unlockpt(master) >= 0) {
36: slavename = ptsname(master);
37: if (!slavename) {
38: close(master);
39: master = -1;
40: /* сквозной проход для нейтрализации ошибки */
41: } else {
42: *name = strdup(slavename);
43: return master;
44: }
45: }
46:
47: /* Остаток этой функции — нейтрализация ошибки для старых систем */
48:
49: /* создать фиктивное имя для заполнения */
Поделиться:
Популярные книги
Бальмануг. Невеста
5. Мир Десяти
Фантастика:
юмористическое фэнтези
5.00
рейтинг книги
Егерь
1. Сопряжение
Фантастика:
боевая фантастика
попаданцы
рпг
7.00
рейтинг книги
Мастер 8
8. Мастер
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Секретарша генерального
Любовные романы:
современные любовные романы
эро литература
короткие любовные романы
8.46
рейтинг книги
Феномен
2. Уникум
Фантастика:
боевая фантастика
6.50
рейтинг книги
Эра Мангуста. Том 2
2. Рос: Мангуст
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Имперец. Том 1 и Том 2
1. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Ты не мой Boy 2
6. Самбисты
Любовные романы:
современные любовные романы
короткие любовные романы
5.00
рейтинг книги
Право налево
Любовные романы:
современные любовные романы
8.38
рейтинг книги
Треск штанов
6. Сын Петра
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Изгой Проклятого Клана. Том 2
2. Изгой
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Повелитель механического легиона. Том VIII
8. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 21
21. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Изгой. Пенталогия
Изгой
Фантастика:
фэнтези
9.01