¿Cómo obtengo este pty y qué puedo hacer con él?

¿Cómo obtengo este pty y qué puedo hacer con él?

Parece que una simple redirección de shell /dev/ptmxme proporciona un nuevo pseudoterminal.

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

Desaparece tan pronto como el proceso que posee el reclamo fd /dev/ptmxsale, pero es bastante simple retenerlo:

$ 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

Entonces parece que el simple open()encendido /dev/ptmxes suficiente para obtener un pseudo-terminal. Supongo que eso haría que el caparazón...(o el proceso para el cual realiza la redirección)- el propietario de la parte principal de la pty.

Pero ¿cómo asigno el lado esclavo - opoder¿Le asigno el lado esclavo? Y si puedo, ¿qué puedo hacer con ello? ¿Puedo afectar sus tiempos de lectura/escritura/vaciado con stty? ¿Se vinculará un proceso del lado esclavo a mi nueva pty al hacer referencia /dev/tty?

Respuesta1

Entonces, como @muru señala en los comentarios, no parece haber una manera sencilla de interconectar el pty creado para usted solo con el shell. Lo logré todo menos una unlockpt()parte. Según algo que leíaquíEs posible que haya algunas opciones en tiempo de compilación en el kernel para deshabilitar el bloqueo de pty recién creado, pero no quería hacer eso. Entonces hice otra cosa.

En realidad no lo necesitaba grantpt(). Según la descripción encontrada.aquítodo lo que hace es cambiar el UID/GID del /dev/pts/[num]archivo del dispositivo. Pero según man mounthay formas más fáciles de manejar eso. Aquí hay algunas devptsopciones de montaje:

  • uid=valueygid=value
    • Esto establece el propietario o el grupo de PTY recién creados en los valores especificados. Cuando no se especifica nada, se establecerán en el UID y GID del proceso de creación. Por ejemplo, si hay un tty grupo con GID 5, entonces gid=5hará que los PTY recién creados pertenezcan alttygrupo.

Ese ya era el caso en mi sistema de forma predeterminada. Pero después de leer eso, me di cuenta de que, después de todo, tal vez quisiera hacer un cambio. La siguiente sección dice:

  • ptmxmode=value
    • Configure el modo para el nuevo nodo del dispositivo ptmx en el devptssistema de archivos.
    • Con soporte para múltiples instancias de devpts(ver newinstanceopción arriba), cada instancia tiene un nodo ptmx privado en la raíz del devptssistema de archivos.(normalmente /dev/pts/ptmx).
    • Para compatibilidad con versiones anteriores del kernel, el modo predeterminado del nuevo nodo ptmx es 0000. ptmxmode=value especifica un modo más útil para el nodo ptmx y es muy recomendable cuando newinstancese especifica la opción.

Si bien hubiera funcionado sin hacerlo, me gustó la idea y la configuré 0640como se recomienda en eldocumentación del núcleo. El enlace del documento del kernel, por cierto, detalla la newinstanceopción de montaje, que es bastante interesante y básicamente le permite obtener un grupo de ptys con espacios de nombres separados por /dev/ptmxmontaje.

De todos modos, entonces elalgo másascendió principalmente a:

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

... como recomiendan los documentos del kernel: consulte el enlace sobre el motivo. También hice permanente el efecto de los comandos anteriores agregando un par de líneas a mi archivo /etc/fstab.

Y...

<<\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 simplemente compila un pequeño programa en C que intenta llamar unlockpt()a su entrada estándar y, si tiene éxito, imprime el nombre del pty recién creado y desbloqueado o, stdoutde lo contrario, devuelve silenciosamente 2.

Una vez hecho esto, pude crear el mío propio.proyectadoprocesos como:

exec 3<>/dev/ptmx

...para obtener el fd del lado maestro en el shell actual entonces...

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

Esto hace que un shell interactivo se ejecute en el otro extremo del pseudo-terminal en segundo plano. Interpretará cualquier cosa impresa >&3como entrada del usuario.

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

Lo que básicamente me proporciona un intérprete interactivo, registrado y con antecedentes.(o cualquier otra cosa que me interese ejecutar con estos)Ala, screensin tanta sobrecarga y en cualquier descriptor de archivo que elija.

El fd del lado maestro propiedad de mi shell actual es el único medio de servir la entrada del lado esclavo y solo se puede escribir mediante mi proceso de shell actual.(y sus hijos). Puedo comunicarme con el otro extremo escribiendo >&3y puedo leer desde el mismo o desde un archivo de registro como desee.

Y, sttydespués de todo, funciona en la 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

información relacionada