Parece que una simple redirección de shell /dev/ptmx
me 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/ptmx
sale, 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/ptmx
es 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 mount
hay formas más fáciles de manejar eso. Aquí hay algunas devpts
opciones de montaje:
uid=value
ygid=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=5
hará que los PTY recién creados pertenezcan alttygrupo.
- 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
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
devpts
sistema de archivos. - Con soporte para múltiples instancias de
devpts
(vernewinstance
opción arriba), cada instancia tiene un nodo ptmx privado en la raíz deldevpts
sistema 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 cuandonewinstance
se especifica la opción.
- Configure el modo para el nuevo nodo del dispositivo ptmx en el
Si bien hubiera funcionado sin hacerlo, me gustó la idea y la configuré 0640
como se recomienda en eldocumentación del núcleo. El enlace del documento del kernel, por cierto, detalla la newinstance
opción de montaje, que es bastante interesante y básicamente le permite obtener un grupo de ptys con espacios de nombres separados por /dev/ptmx
montaje.
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, stdout
de 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 >&3
como 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, screen
sin 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 >&3
y puedo leer desde el mismo o desde un archivo de registro como desee.
Y, stty
despué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