Предотвратить закрытие дескриптора файла в системах POSIX - PullRequest
3 голосов
/ 20 июня 2011

Существует библиотека (libvte, библиотека эмуляции терминала), которая использует пару файловых дескрипторов для пары pty master / slave. Мне нужно иметь возможность «украсть» мастер-файл из библиотеки для моего собственного использования (чтобы реализовать поддержку ZMODEM для очень редкого случая, когда единственная ссылка, которая у меня есть, на сеть - через терминал). Однако есть проблема.

Вы можете указать libvte, что вы хотите изменить дескриптор файла на новый, но затем он попытается закрыть используемый мастер и начать использовать вместо него новый. Это не будет работать, потому что, когда мастер закрыт, раб уходит. Первоначально я думал, что можно будет использовать dup() на мастере pty, так что, когда libvte сделает close() на мастере PTY, у меня все еще будет функционирующий fd для использования. Это явно неправильно.

Мне нужно найти способ:

  • Блокирует операции libvte read() на fd.
  • Увлекайте fd от libvte до тех пор, пока я его не использую (например, до тех пор, пока процесс rz, к которому я подключаю его, не завершится)

Возможно ли в системе POSIX выполнить одно из этих действий? Или был бы какой-то другой способ сделать то же самое, не исправляя сам libvte? Причина, по которой я спрашиваю, состоит в том, что решение должно работать на достаточном количестве существующих систем.

Если это вообще актуально, я взаимодействую с libvte (и непосредственно GTK +) через Python. Однако я бы не отказался от написания расширения Python на C, которое я мог бы затем вызвать из программы Python, потому что вам не нужно быть привилегированным в любой системе для загрузки расширения Python.

Если ничего из этого не возможно, я могу быть вынужден форкнуть libvte, чтобы сделать то, что я хочу, и распространить это с моей программой, но я не хочу этого делать - я не хочу быть попробую трепаться!

Ответы [ 2 ]

3 голосов
/ 20 июня 2011

Одним из возможных решений было бы написать вспомогательный процесс, который открывает свою собственную пару pty master / slave и вставляет между libvte и фактической целевой программой, которая выполняется на ведомом pty:

+---------------+
| libvte        |
|               |
|    pty master=|-----\
+---------------+     |
                      |
+---------------+     |
| helper proxy  |     |
|               |     |
|  stdin/stdout=|-----/
|               |
|    pty master=|-----\
+---------------+     |
                      |
+---------------+     |
| target        |     |
|               |     |
|  stdin/stdout=|-----/
+---------------+

Ваш вспомогательный процесс обычно просто проходит через данные, пока не увидит трафик ZMODEM. Затем он прекращает передачу данных в stdin / stdout (который заканчивается на libvte) и вместо этого либо передает их в приложение через отдельный дескриптор файла, либо даже просто вызывает rz.

1 голос
/ 20 июня 2011

dup() на файловые дескрипторы не влияют close() вызовы других экземпляров; однако, возможно, что libvte может вызывать некоторые другие методы завершения работы, которые изменяют его состояние. Используйте strace для более детального изучения.

Кроме того, есть несколько вещей, которые вы можете сделать, но ни одна из них не очень красива. Один из вариантов - заменить дескриптор файла из-под libvte. То есть:

  • Во-первых, используйте dup(), чтобы получить свою собственную копию fd и спрятать ее куда-нибудь
  • Используйте dup2(), чтобы перезаписать файл libvte с ​​вашим собственным выбором. Это должен быть новый pty с конфигурацией, аналогичной той, которую вы крадете, чтобы избежать путаницы в libvte. Поскольку вы никогда ничего не будете писать на другом конце, чтение заблокирует (вам нужно будет что-то сделать с любыми данными, которые libvte может записать туда!)
  • Если libvte может быть в блокировке read() в этот самый момент, отправьте сигнал его потоку (с no-op - not SIGIGN - handler), чтобы прервать вызов read().
  • Работайте с fd, который вы дублировали на старте
  • Чтобы вернуться к обычному режиму, используйте dup2() для возврата fd, затем скопируйте любые изменения состояния pty, которые libvte могла внести в исходный дескриптор.

Кроме того, вы можете делать то, что предлагает caf, и просто иметь прокси-сервер с самого начала.

...