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/')) {

 93:   /* Интерфейс Unix98 не использовался, необходима

 94:    * специальная обработка полномочий или прав владения.

 95:    *

 96:    * Выполнить chown/chmod для соответствующего pty, если возможно.

 97:    * Это будет работать, только если имеет полномочия root.

 98:    * В качестве альтернативы можно написать и запустить небольшую

 99:    * setuid-программу, которая сделает все это.

100:    *

101:    * В противном случае все проигнорировать и пользоваться

102:    * только интерфейсом Unix98.

103:    */

104:   if ((gptr = getgrnam('tty')) != 0) {

105:    gid = gptr->gr_gid;

106:   } else {

107:    /* если группа tty не существует, не изменять группу

108:     * на подчиненном компоненте pty, а только владельца

109:     */

110:    gid = -1;

111:   }

112:

113:   /* Обратите внимание, что здесь не осуществляется проверка на ошибки.

114:    * Однако если выполняемые действия являются критически важными,

115:    * проверка ошибок должна быть. */

116:   chown(name, getuid(), gid);

117:

118:   /* Этот код делает подчиненный компонент доступным для чтения/записи

119:    * только конкретному пользователю. Если код предназначен для

120:    * интерактивной оболочки, которая должна получать сообщения

121:    * 'write' и 'wall', добавьте ниже 'ИЛИ' с S_IWGRP во второй аргумент.

122:    * В таком случае потребуется перенести эту строку за пределы

123:    * оператора if(), чтобы код мог выполняться для интерфейсов как

124:    * BSD-стиля, так и Unix98-стиля.

125:    */

126:   chmod(name, S_IRUSR|S_IWUSR);

127:  }

128:

129:  /* открыть соответствующий подчиненный компонент pty */

130:  slave = open(name, O_RDWR);

131:

132:  return(slave);

133: }

Функция get_slave_pty() не делает ничего нового. Все функции описываются в других местах этой книги, поэтому здесь они не объясняются.

16.6.4. Примеры псевдотерминалов

Возможно, одной из самых простых программ, которая может быть написана для использования pty, является программа, открывающая пару pty и запускающая оболочку на подчиненном компоненте pty,

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату