Разработка приложений в среде 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: /* создать фиктивное имя для заполнения */
Поделиться:
Популярные книги
Кодекс Крови. Книга IV
4. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Девятый
1. Девятый
Фантастика:
боевая фантастика
попаданцы
9.15
рейтинг книги
Кодекс Охотника. Книга XII
12. Кодекс Охотника
Фантастика:
боевая фантастика
городское фэнтези
аниме
7.50
рейтинг книги
Его маленькая большая женщина
Любовные романы:
современные любовные романы
эро литература
8.78
рейтинг книги
Саженец
3. Хозяин дубравы
Фантастика:
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Свет во мраке
8. Изгой
Фантастика:
фэнтези
7.30
рейтинг книги
(Не)свободные, или Фиктивная жена драконьего военачальника
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Вамп
3. История одного эволюционера
Фантастика:
рпг
городское фэнтези
постапокалипсис
5.00
рейтинг книги
Инвестиго, из медика в маги 2
2. Инвестиго
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последняя Арена 4
4. Последняя Арена
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Хозяин Теней 2
2. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 8
8. Лекарь
Фантастика:
юмористическое фэнтези
аниме
7.00
рейтинг книги
Неудержимый. Книга XI
11. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Двойник Короля 2
2. Двойник Короля
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00