socat e rich terminal novamente

2

Eu inicio socat em um terminal executando socat - UNIX-listen:/tmp/sock

Então eu vou para outro terminal e inicio um programa (pelo python) de tal forma, que parece rodar no primeiro terminal, aqui está um exemplo:

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()

Programas com entrada / saída simples como "cat", por exemplo, estão funcionando bem, mas os mais complexos (como "vim" ou "bash") não são muito felizes, obviamente. Além disso, quando eu atingi Cntrl-C no primeiro terminal, o socat é morto, enquanto eu preferiria que a interrupção do teclado fosse entregue ao programa prg (iniciado no código python acima).

Minha pergunta é: se é possível e como dizer a socat para se comportar como prg é o proprietário do terminal e não o socat em si.

PS. Pode parecer que esta questão é uma duplicata de esta , mas não é o caso, porque nessa questão o prg é chamado diretamente por socat , então é possível usar as opções EXEC .

    
por ilya 13.07.2016 / 14:44

1 resposta

2

Sinais nem posse de tty não podem ser 'magicamente' carregados em um soquete.

Em AF_UNIX, você poderia enviar o próprio descritor de arquivos tty (usando sendmsg e recvmsg) e tem o lado de recebimento usando ele (e não o socket) como o sub-processo" stdout / stderr ". Isto não pode ser feito com socat simples, mas este método é utilizado internamente por e. a ferramenta tmux.

Com o socat simples, o máximo que você pode fazer é enviar um literal 0x03 byte (^ C) quando o Ctrl + C for pressionado (é o que o telnet e o ssh fazem). Você pode testar isso pressionando Ctrl + V Ctrl + C para enviá-lo uma vez ou executando stty raw antes de entrar no "modo bruto" permanentemente.

Isso não será suficiente para fazer o recebimento realmente entender o pressionamento de tecla, no entanto. O método mais básico seria verificar cada byte manualmente - envie um SIGINT quando vir 0x03; escrevê-lo para o subprocesso "stdin caso contrário.

O que telnetd e sshd fazem, no entanto, é adicionar uma 'pseudo-tty' entre o soquete e o subprocesso - no Python você pode criar um usando os.openpty() ; o lado 'escravo' precisa ser dado como o subprocesso 'stdout / stderr, e seu script precisará rodar em um loop copiando dados entre o soquete e o lado' mestre '.

Ainda não é suficiente - um protocolo de login de terminal completo, como SSH ou Telnet, também teria mensagens para atualizar as dimensões da pty e reagir às mudanças de configuração dos termios (por exemplo, o " echo local "configuração e outros vistos em stty ).

Seria útil ler o código fonte do cliente telnet & servidor telnetd, e. do GNU inetutils, como eles fazem exatamente isso.

    
por 13.07.2016 / 15:20