Florian Weimer <
f...@deneb.enyo.de>:
> * Bonita Montero:
>
>> Am 29.08.2023 um 23:02 schrieb Florian Weimer:
>>
>>> Manche Programme öffnen auch /dev/tty, z.B. um Paßwörter
>>> einzulesen.
>>>
>>
>> Man kann auch einfach line-buffering und echoing von stdin
>> abschalten.
>>
>
> Das funktioniert für less z.B. nicht,
>
Das ist richtig, aber das folgende ist nicht der Grund dafür.
> weil das andere Programm immer noch von der Standardeingabe
> liest.
>
Der Grund dafür, dass „less“ das „/dev/tty“ öffnet, ist, dass es
im Fall, dass es ein „anderes Programm“ wie beispielsweise im
folgenden Shell‐Kommando
das_andere_Programm spuckt Ausgaben | less
gibt, als Standardeingabe nicht mehr das Terminal hat sondern die
Ausgabeseite des Pipes. Möchte „less“ also vom Terminal seine
Steuerkommandos lesen, muss es sich das Terminal selber öffnen.
Eine andere Möglichkeit für „less“ wäre gewesen, ihm die Option
„--command-fd“ zu implementieren. Dann könnte man es so
aufrufen:
{
das_andere_Programm spuckt Ausgaben 3<&- |
less --command-fd 3
} 3<&0
Wenn „das andere Programm“ auch noch vom Terminal liest, gibt es
natürlich Chaos. Das kann aber weder dadurch behoben
werden, dass „less“ sich das Terminal noch mal selber öffnet,
noch dadurch, dass „less“ die Option „--command-fd“ hätte.
In einer Umgebung, in der ich mehrere (Pseudo‐)Terminals habe,
also beispielsweise in einer X11‐Umgebung mit „xterm“, kann ich
mir so helfen:
das_andere_Programm spuckt Ausgaben |
xterm -e sh -c -- 'exec 0<&3 3<&- && "$@"' sh less 3<&0
Zunächst eine kurze Erklärung zum Shell‐Kommando: Die
Eingabeumlenkung „3<&0“ am Ende der Kommandozeile bewirkt, dass
die Ausgabeseite des pipes nicht nur über file descriptor Nummer
0 sondern ebensogut über file descriptor Nummer 3 ausgelesen
werden kann. Das „xterm“, wenn es dann das gewünschte Programm,
hier: das Shell („sh -c -- …“) startet, reicht an das Shell nicht
seine eigene Standardeingabe weiter, sondern erzeugt ein neues
(Pseudo‐)Terminal und gibt dem Shell als Standardeingabe einen
Zugriff auf das neue Terminal mit. Weil die alte Standardeingabe
aber auch noch über file descriptor Nummer 3 lesbar ist, kann das
Shell mittels „exec 0<& 3<&-“ seine Standardeingabe auf die alte
dem „xterm“ übergebene Standardeingabe zurückstellen und das so
an das „less“ weitergeben.
Das Kommando bewirkt, dass „less“ in einem eigenen „xterm“ läuft
und deshalb nicht versucht, vom selben Terminal wie
„das_andere_Programm“ zu lesen. Ja, die Entwickler des guten
alten „xterm“s haben sich nicht erdreistet[1], einfach alle file
descriptors zu schließen, sondern sind konservativ vorgegangen:
File descriptors, die das „xterm“ offen vorfindet, tastet es
nicht an, sondern lässt sie, wie sie sind. Und das ist auch gut
so.
So kümmert sich das „xterm“ im angeführten Beispiel nicht darum,
dass file descriptor Nummer 3 zum Lesen geöffnet ist und schließt
es etwa, sondern lässt es einfach unangetastet offen und
reicht es dadurch ganz automatisch an das von ihm gestartete
Shell weiter. Lust, das mal konkret auszuprobieren? Dann nimm
dieses Beispiel:
cat |
xterm -e sh -c -- 'exec 0<&3 3<&- && "$@"' sh less 3<&0
Da läuft ein „cat“ mit Standardeingabe vom Terminal: Man kann
also Text eintippen, der von „cat“ gelesen und ans „xterm“
weitergereicht wird. Im „xterm“ läuft ein Shell, das zuerst eine
Eingabeumlenkung von file descriptor Nummer 0 auf Nummer 3 macht
und Nummer 3 schließt. Dadurch kommen die Daten bei „less“ wie
gewohnt beim file descriptor Nummer 0 an.
[1] Vor Jahren habe ich dasselbe mal mit einem Gnome‐Terminal
versucht und bin gescheitert, weil die Entwickler des
Gnome‐Terminals der Meinung waren, das Gnome‐Terminal müsste beim
Start erst mal nach allen offenen file descriptors fahnden und
diese dann schließen.