Чтение онлайн

ЖАНРЫ

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

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 и возвращает файловый дескриптор родительскому процессу, а также предоставляет имя соответствующему подчиненному компоненту pty. Он сначала испытывает интерфейс Unix98 на распределение управляющего устройства pty, а если это не работает (например, если ядро скомпилировано без поддержки pty Unix98, возможно, для встроенных систем), возвращается к старому интерфейсу стиля BSD. Соответствующая функция
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: /* создать фиктивное имя для заполнения */

 50: *name = strdup("/dev/ptyXX");

 51:

 52: /* искать неиспользуемый pty */

 53: for (i=0; i<16 && master <= 0; i++) {

 54: for (j = 0; j<16 && master <= 0; j++) {

 55: (*name)[8] = "pqrstuvwxyzPQRST"[i];

 56: (*name)[9] = "0123456789abcdef"[j];

 57: /* открыть ведущее устройство pty */

 58: if ((master = open(*name, O_RDWR)) < 0) {

 59: if (errno == ENOENT) {

 60: /* устройства pty исчерпаны */

 61: free(*name);

 62: return(master);

 63: }

 64: }

 65: }

 66: }

 67:

 68: if ((master < 0) && (i == 16) && (j == 16)) {

 69: /* необходимо для каждого неудачного pty */

 70: free(*name);

 71: return(master);

 72: }

 73:

 74: /* Подставляя букву, изменить имя ведущего устройства pty

 75: * в имени подчиненного компонента pty.

 76: */

 77: (*name)[5] = 't';

 78:

 79: return(master);

 80: }

 81:

 82: /* get_slave_pty возвращает целочисленный файловый дескриптор.

 83: * Если возвращается значение < 0, значит, возникла ошибка.

 84: * В противном случае возвращается файловый дескриптор подчиненного

 85: * компонента. */

 86:

 87: int get_slave_pty(char * name) {

 88: struct group *gptr;

 89: gid_t gid;

 90: int slave = -1;

 91:

 92: if (strcmp(name, "/dev/pts/")) {

Поделиться с друзьями: