Como eu obtenho este artigo e o que posso fazer com ele?

5

Parece que um simples redirecionamento de shell de /dev/ptmx me fornece 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 solicitação fd em /dev/ptmx é encerrado, mas é simples o suficiente para retê-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() on /dev/ptmx é suficiente para obter um pseudo-terminal. Eu acho que isso faria o shell - (ou o processo para o qual ele faz o redirecionamento) - o proprietário do lado mestre do arquivo.

Mas como eu atribuo o lado escravo - ou posso eu atribuo o lado escravo? E se eu puder - o que posso fazer com isso? Posso afetar seus tempos de leitura / gravação / limpeza com stty ? Um processo do lado do escravo ligará para o meu novo arquivo ao fazer referência a /dev/tty ?

    
por mikeserv 14.01.2015 / 03:21

1 resposta

4

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

Eu não precisei de grantpt() na verdade. De acordo com a descrição encontrada aqui tudo o que isso faz é alterar o UID / GID para /dev/pts/[num] arquivo do dispositivo. Mas, de acordo com man mount , há maneiras mais fáceis de lidar com isso. Aqui estão algumas opções de devpts mount:

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

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

  • %código%
    • Defina o modo para o novo nó do dispositivo ptmx no sistema de arquivos ptmxmode=value .
    • Com o suporte para várias instâncias de devpts (consulte a opção devpts acima), cada instância tem um nó ptmx particular na raiz do sistema de arquivos newinstance (geralmente devpts )
    • Para compatibilidade com versões mais antigas do kernel, o modo padrão do novo nó ptmx é /dev/pts/ptmx . 0000 especifica um modo mais útil para o nó ptmx e é altamente recomendado quando a opção ptmxmode=value é especificada.

Apesar de ter funcionado sem fazê-lo, gostei da ideia e defini-a como newinstance conforme recomendado no documentação do kernel . O link doc do kernel, a propósito, elabora sobre a opção 0640 mount - que é bem legal e basicamente permite que você obtenha um grupo separado de espas por nome por newinstance mount.

De qualquer forma, o algo mais foi principalmente para:

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

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

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 em C que tenta chamar /etc/fstab em seu arquivo stdin e, se for bem sucedido, imprime o nome do recém-criado e desbloqueado pty em unlockpt() ou então silenciosamente retorna 2.

Uma vez que isso foi feito, eu poderia criar meus próprios processos selecionados como:

exec 3<>/dev/ptmx

... para obter o fd master-side no shell atual ...

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

Isso obtém um shell interativo em execução na outra extremidade do pseudo-terminal em segundo plano. Ele irá interpretar qualquer coisa impressa em stdout como 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
$ 

Que basicamente me faz um intérprete interativa, com registro em log (ou qualquer outra coisa que eu possa me preocupar em executar nelas) ala >&3 sem muita 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 do escravo e é apenas gravável pelo meu processo de shell atual (e seus filhos) . Eu posso me comunicar com o outro lado escrevendo para screen e eu posso ler do mesmo ou de um arquivo de log como eu desejo.

E >&3 funciona no terminal depois de tudo:

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
    
por 14.01.2015 / 22:34