Caracteres de controle TTY enviados para stdin of sh não funcionam

1

Eu tentei desenvolver um aplicativo remoto que lança sh e reenvia os dados recebidos para lá, e descobri que algumas sequências especiais não funcionam.

Então, para testar, eu lancei no meu desktop sh , então executei um comando ping localhost , depois tentei interromper o ping executando echo -e "0x33" > /proc/$shPID/fd/0 do outro shell. O byte %code% é aquele que é produzido pela combinação Ctrl + C . Não importa o que eu tentei (adicionando uma nova linha, adicionando um CSI no começo) , não funcionou - os personagens aparecem em stdout do sh (Quero dizer, por exemplo, nova linha) , mas não interrompe o ping em execução.

Como faço para interromper o ping via stdin do sh?

    
por Hi-Angel 11.06.2015 / 10:43

1 resposta

3

Esse processamento é feito pelo driver do dispositivo de terminal, não pelo shell.

É quando esse caractere é recebido na ligação que se conecta a um dispositivo tty (ou escrito no lado mestre do lado mestre de um par de pseudo-terminais (como xterm quando você pressiona Ctrl + C )) que a disciplina de linha tty (um driver no kernel) envia o sinal SIGINT para o grupo de processos de primeiro plano do terminal.

Então você precisa enviar esse caractere no fd que o xterm abriu no lado mestre.

$ eval "$(xprop -notype -id $WINDOWID 32i '=$0\n' _NET_WM_PID)"; lsof -ap "$_NET_WM_PID" /dev/ptmx
COMMAND   PID     USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
xterm   21123 stephane    4u   CHR    5,2      0t0 1460 /dev/ptmx

Escrevê-lo para /proc/21123/fd/4 no Linux não funcionaria, pois isso só reabria /dev/ptmx , portanto, não se referisse ao mesmo pseudo-terminal. Você precisaria convencer que xterm a escrever esse ^ C em seu fd4.

Portanto, não é realmente uma opção.

Você pode iniciar seu próprio par de pseudo-terminais e executar sh e ping nele. Então você poderia escrever ^ C no lado mestre para que o SIGINT seja enviado para o grupo de processos em primeiro plano, mas mais fácil aqui seria enviar um sinal diretamente (o SIGTERM seria preferido).

Observe também que tentar escrever um caractere em /proc/$pid/fd/0 não faz muito sentido. O descritor de arquivo geralmente está aberto para leitura. No Linux, fazer um open () nesse /proc/$pid/fd/0 realmente reabre o recurso para o qual fd aponta.

Então, por exemplo, se sh foi iniciado com sh < /some/file , fazer echo something > "/proc/$shpid/fd/0" substituiria o conteúdo de /some/file por something\n . Se fosse um tty, então isso mostraria apenas something naquele terminal. O único caso em que escrever something teria que algo lido por sh seria quando esse sh stding fosse um pipe. No Linux (e Linux apenas), se você fizer um open() no modo de gravação para /proc/$shpid/fd/0 (onde isso é um canal), então isso abre a extremidade de gravação daquele canal (enquanto que fd 0 realmente aponta para o final da leitura) ).

    
por 11.06.2015 / 11:13