Como consigo este apartamento e o que posso fazer com ele?

Como consigo este apartamento e o que posso fazer com ele?

Parece que um simples redirecionamento de shell /dev/ptmxme dá um novo pseudo-terminal.

$ ls /dev/pts; ls /dev/pts </dev/ptmx
0  1  2  ptmx
0  1  2  3  ptmx

Ele desaparece assim que o processo que possui a reivindicação fd é /dev/ptmxencerrado, mas é simples o suficiente para mantê-lo:

$ PS1='<$(ls -1 "$@" /dev/pts/*|uniq -u)> $ ' \
  exec 3<>/dev/ptmx "$0" -si -- /dev/pts/*
</dev/pts/3> $ ls /dev/pts; exec 3>&-
0  1  2  3  ptmx
<> $ ls /dev/pts; exec 3<>/dev/ptmx
0  1  2  ptmx
</dev/pts/3> $ exit

Portanto, parece que o simples open()é /dev/ptmxsuficiente para obter um pseudo-terminal. Acho que isso faria a concha...(ou o processo para o qual ele faz o redirecionamento)- o proprietário do lado mestre do prédio.

Mas como atribuo o lado escravo - oupodeEu atribuo o lado escravo? E se eu puder, o que posso fazer com isso? Posso afetar seus tempos de leitura/gravação/liberação com stty? Um processo do lado escravo será vinculado ao meu novo pty ao fazer referência /dev/tty?

Responder1

Então, como @muru aponta nos comentários, não parece haver uma maneira simples de fazer a interface do pty criado para você apenas com o shell. Eu consegui tudo menos uma unlockpt()parte. De acordo com algo que liaquipode haver algumas opções de tempo de compilação no kernel para desabilitar o bloqueio de pty recém-criado, mas eu não queria fazer isso. Então, fiz outra coisa.

Na verdade , eu não precisava grantpt(). De acordo com a descrição encontradaaquitudo o que faz é alterar o UID/GID do /dev/pts/[num]arquivo do dispositivo. Mas de acordo com man mountexistem maneiras mais fáceis de lidar com isso. Aqui estão algumas devptsopções de montagem:

  • uid=valueegid=value
    • Isto define o proprietário ou o grupo de PTYs recém-criados para os valores especificados. Quando nada for especificado, eles serão definidos para o UID e GID do processo de criação. Por exemplo, se houver um tty grupo com GID 5, gid=5fará com que os PTYs recém-criados pertençam aottygrupo.

Esse já era o caso no meu sistema por padrão. Mas depois de ler isso, percebi que, afinal, talvez eu quisesse fazer uma mudança. A próxima seção diz:

  • ptmxmode=value
    • Defina o modo para o novo nó do dispositivo ptmx no devptssistema de arquivos.
    • Com suporte para múltiplas instâncias de devpts(veja newinstancea opção acima), cada instância possui um nó ptmx privado na raiz do devptssistema de arquivos(normalmente /dev/pts/ptmx).
    • Para compatibilidade com versões mais antigas do kernel, o modo padrão do novo nó ptmx é 0000. ptmxmode=value especifica um modo mais útil para o nó ptmx e é altamente recomendado quando a newinstanceopção é especificada.

Embora teria funcionado sem isso, gostei da ideia e defini-a conforme 0640recomendado nodocumentação do kernel. A propósito, o link do documento do kernel detalha a newinstanceopção de montagem - o que é muito legal e basicamente permite que você obtenha um grupo de ptys com espaçamento de nome separado por /dev/ptmxmontagem.

De qualquer forma, então oalgo maistotalizou principalmente:

mount -o remount,newinstance,gid=5,ptmxmode=0640 /dev/pts
mount --bind /dev/pts/ptmx /dev/ptmx

... como recomendam os documentos do kernel - veja o link sobre o porquê. Também tornei o efeito dos comandos acima permanente adicionando algumas linhas ao meu arquivo /etc/fstab.

E...

<<\C cc -xc - -o pts
#include <stdio.h>
int main(int argc, char *argv[]) {
        if(unlockpt(0)) return 2;
        char *ptsname(int fd);
        printf("%s\n",ptsname(0));
        return argc - 1;
}
C

Que apenas compila um pequeno programa C que tenta chamar unlockpt()seu stdin e, se for bem-sucedido, imprime o nome do pty recém-criado e desbloqueado stdoutou então retorna silenciosamente 2.

Feito isso, eu poderia criar o meu própriorastreadosprocessos como:

exec 3<>/dev/ptmx

... para obter o fd do lado mestre no shell atual então ...

(setsid -c "$0" -i 2>&1|tee log) <>"$(./pts <&3)" 3>&- >&0 &

Isso faz com que um shell interativo seja executado na outra extremidade do pseudoterminal em segundo plano. Ele interpretará qualquer coisa impressa >&3como entrada do usuário.

mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$
mikeserv@localhost$ echo echo hey >&3
mikeserv@localhost$ cat log
$ hey
$ hey
$ 

O que basicamente me dá um intérprete interativo, registrado e com experiência(ou qualquer outra coisa que eu queira usar)ala, screensem tanta sobrecarga e em qualquer descritor de arquivo que eu escolher.

O fd do lado mestre de propriedade do meu shell atual é o único meio de servir a entrada do lado escravo e só pode ser gravado pelo meu processo atual do shell(e seus filhos). Posso me comunicar com o outro lado escrevendo >&3e posso ler o mesmo ou um arquivo de log, conforme desejar.

E sttyafinal funciona no terminal:

mikeserv@localhost$ echo stty -a ">$(tty)" >&3
speed 38400 baud; rows 0; columns 0; line = 0;                                      
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>; eol2 = <undef>;
swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W;
lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd -cmspar cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc
-ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl
echoke

informação relacionada