2

Я запускаю socat на терминале, выполнив socat - UNIX-listen:/tmp/sock

Затем я иду в другой терминал и запускаю программу (с помощью python) таким образом, что она запускается в первом терминале, вот пример:

s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect("/tmp/sock")
proc=subprocess.Popen(['prg'], stdin=s, stdout=s, stderr=s, shell=False)
proc.wait()

Программы с простым вводом / выводом, например "cat", работают нормально, но более сложные (например, "vim" или "bash"), очевидно, не очень счастливы. Кроме того, когда я нажимаю Cntrl-C на первом терминале, socat убивается, а я предпочитаю, чтобы клавиатурное прерывание доставлялось в программу prg (запущено в коде python выше).

Мой вопрос: если это возможно, и как это сказать socat чтобы он вел себя так, будто prg является владельцем терминала, а не сам socat .

PS. Может показаться , что этот вопрос является дубликатом этого один, но это не так, потому что в этом вопросе prg вызывается непосредственно socat поэтому можно использовать варианты EXEC

1 ответ1

2

Сигналы или собственность владельца не могут быть «волшебным образом» перенесены через сокет.

Более AF_UNIX, вы можете отправить сам терминал дескриптор файла (используя sendmsg и recvmsg) и есть принимающая сторона использовать (а не сокет) в качестве подпроцесса стандартный вывод / STDERR. Это не может быть сделано с простым socat, но этот метод используется внутри, например, инструментом tmux.


С простым socat самое лучшее, что вы можете сделать, это заставить его отправлять буквальный байт 0x03 (^ C) при нажатии Ctrl+C (это то, что делают telnet и ssh). Вы можете проверить это, нажав Ctrl+V Ctrl+C, чтобы отправить его один раз, или запустив stty raw перед socat, чтобы окончательно войти в "raw mode".

Однако этого будет недостаточно, чтобы принимающая сторона действительно поняла нажатие клавиши. Самый простой способ - проверять каждый байт вручную - отправлять SIGINT, когда он видит 0x03; в противном случае запишите это в подпроцесс 'stdin.

Однако telnetd и sshd добавляют псевдо-tty между сокетом и подпроцессом - в Python вы можете создать его с помощью os.openpty() ; сторона 'slave' должна быть указана как подпроцесс 'stdout /stderr, а ваш сценарий должен выполняться в цикле, копируя данные между сокетом и стороной' master '.

Это все еще не вполне достаточно - полнофункциональный терминал протокола Логин, такие как SSH или Telnet, также есть сообщения , чтобы обновить размеры в PTy, и реагировать на termios устанавливающих изменения (например , "локального эха" настройки и другие видели в stty ,

Было бы полезно прочитать исходный код клиента telnet и сервера telnetd, например, из GNU inetutils, поскольку они делают именно это.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .