stdout - less vs. vim

_RM_

Cadet 4th Year
Registriert
Juli 2018
Beiträge
124
Hallo Forum,

ich habe gerade mit dem Tool "base64" herumgespielt und dort kann man z.B. mit cat encoded.file | base64 -d die Daten im File decoden. Genauso kann man auch echo Y29vbHRvb2wK | base64 -d schreiben.
Also im Endeffekt schickt man was nach stdout und das wird dann von base64 verarbeitet, und wiederum nach stdout geschickt.

Meine Annahme war nun, dass es mit dem Tool less nicht geht. Mein Gedanke dabei war, dass less nicht nur einfach Text nach stdout schickt, sondern es auch Funktionen anbietet, wie z.B. das Suchen nach Text indem man z.B. /irgendwas eingibt oder eben das zeilen- oder seitenweise "scrollen" mit Enter oder Bild-Auf/Ab.
Natürlich hab ich es dann ausprobiert und mein Gedanke hat sich als falsch herausgestellt und less encoded.file | base64 -d funktioniert in meinem Fall genauso gut wie mit cat oder echo, sogar wenn es seitenweise Text ist.

Ich tue mir etwas schwer nun meine erste Frage zu formulieren, also: Wie funktioniert das? :D
Wie weiß das Programm, dass es im einen Fall interaktiv mit allen Funktionen (scrollen, suchen, usw.) starten muss, und im anderen Fall einfach alle Daten auf einmal an stdout schicken muss?

Und weil ich so krass drauf bin und ich es dann so richtig wissen wollte, habe ich vim ausprobiert. Vom Look & Feel ist das ja irgendwie ähnlich, wie less. Oben wird der Text angezeigt und unten hat man eine Statusleiste und eine Art "Command Line", wo man z.B. :q eingeben kann, um das Programm zu verlassen.
So, und hier war mein Gedanke von vorhin wohl richtig und es geht wie "erwartet" nicht. Wenn ich nämlich vim encoded.file | base64 -d aufrufe, kommt ein Fehler Vim: Warning: Output is not to a terminal.

Wenn "Output is not to a terminal", wohin ist Output dann? Schlussendlich zeigt mir vim den Text ja fast gleich an, wie less.
Worin liegen nun also die technischen Unterschiede zwischen vim und less?

Und die vorerst letzte Frage, die ich mir stelle, wie die "interne Command Line" innerhalb eines solchen Programms funktioniert. Wie kommt der interne Befehl vom Terminal zum Programm? Hat das mit Terminfo und Termcap zu tun?

Ich würde mich über eine detaillierte Erläuterung und/oder spezifische Keywords nach denen ich googlen kann sakrisch freuen.
 
Less erkennt, ob das Device ein tty ist oder nicht. vi(m) erwartet zwangsläufig ein tty und bricht ab, wenn das Device keines ist. Und wenn man direkt piped ist das Device natürlich kein tty mehr, sondern stdout.
Aus dem less code (main.c):
Code:
        /*
         * Set up terminal, etc.
         */
        if (!is_tty)
        {
                /*
                 * Output is not a tty.
                 * Just copy the input file(s) to output.
                 */

Das sollte deine Frage, woher das Programm das weiß beantworten: Von der Termcap. Es bekommt die capabilities mitgeteilt. Und die sind eben wenn gepiped wird komplett andere als wenn nicht und das Terminal (z.B. vt100 oder xterm) das output device ist.
is_tty benutzt hier isatty(): https://www.freebsd.org/cgi/man.cgi....2-RELEASE+and+Ports&arch=default&format=html
(habe hier die FreeBSD manpage verlinkt, da die wie üblich ausführlicher als die von der glibc ist)

Less ist im wesentlichen, wie more, ein Pager. Das heißt du schaust eine File an und bekommst das nicht wie bei cat komplett ausgegeben sondern er erkennt die Terminal größe und hört nach einer Seite auf. Du kannst dann mit space z.B. weiter pagen. Und nebenbei gibt's halt noch viele weitere Features wie suchen etc. Da es aber im wesentlichen nur ein Pager ist, dafür aber ein paar nette Gimmicks via Parameter hat ,hat man auch die möglichkeit eingebaut, mit non-tty zu arbeiten um den Output weiterzuverarbeiten.

vi (und dessen erweiterte neuimplementierung) vim ist ein interaktiver fully-fledged Editor. Entstanden aus dem Linebased Editor ex. Wegen der Interaktivität setzt er immer ein Terminal voraus, weil er sonst nutzlos ist. Vim kann halt noch viel mehr als der alte vi, z.B. Syntax highlighting, visual mode und vieles vieles mehr :)

Deine letzte Frage (interne command line/Termcap/Terminfo) verstehe ich nicht wirklich. Kannst du die nochmal anders formulieren?
 
Zuletzt bearbeitet von einem Moderator:
  • Gefällt mir
Reaktionen: up.whatever, roestzwiebel, Iapetos und 5 andere
  • Gefällt mir
Reaktionen: roestzwiebel, Iapetos, PHuV und 4 andere
@foo_1337 Das sind schonmal unglaublich gute Informationen für mich. Die erste Frage ist damit definitiv beantwortet :)
Ob ich damit die anderen beiden Fragen auch beantworten kann, werde ich nach dem Schlafen herausfinden.
Danke!
 
  • Gefällt mir
Reaktionen: foo_1337
Das sind gerade sehr spannende Abenteuer, die ich erlebe :D

Dass tty ein Device ist, war mir noch nicht bewusst und hat nun sehr zum Verständnis beigetragen.

Ich weiß jetzt, dass man z.B. mit dem Befehl ttyherausfinden kann, ob es sich um ein tty handelt oder nicht.

Code:
kali@kali:~$ tty
/dev/pts/6
kali@kali:~$ echo hello | tty
not a tty

oder so

Code:
kali@kali:~$ tty -s
kali@kali:~$ echo $?
0
kali@kali:~$ echo hello | tty -s
kali@kali:~$ echo $?
1

Das führte dann zur Erkenntnis, dass man stdout auch ganz einfach an ein anderes Terminal umleiten kann.
echo hello > /dev/pts/9

Wenn man ls -l /proc/self/fd aufruft, sieht man außerdem die momentanen Ziele der FDs.

Meine Frage
_RM_ schrieb:
Wenn "Output is not to a terminal", wohin ist Output dann?
für den Befehl vim base64.txt | base64 -d
kann ich nun so beantworten
Code:
lrwx------ 1 kali kali 64 Jan 23 13:28 0 -> /dev/pts/5
l-wx------ 1 kali kali 64 Jan 23 13:28 1 -> 'pipe:[116830]'
lrwx------ 1 kali kali 64 Jan 23 13:28 2 -> /dev/pts/5
lr-x------ 1 kali kali 64 Jan 23 13:28 3 -> /home/kali/base64.txt
oder anders gesagt, stdout geht scheinbar an eine Pipe ('pipe:[116830]'), was durchaus Sinn ergibt, da der Befehl gepiped ist. Was mir noch nicht klar ist, warum mir die Pipe im Terminal rot markiert wird, so als gäbe es das Ziel nicht.

foo_1337 schrieb:
Deine letzte Frage (interne command line/Termcap/Terminfo) verstehe ich nicht wirklich. Kannst du die nochmal anders formulieren?
Ich versteh die Frage auch nicht :D Ich denke mir fehlt noch das Grundwissen, wie ein Terminal funktioniert, deshalb kann ich es nicht besser formulieren. Ich frag mal so: Gehört die Command Line von vim, wo man z.B. :wq eingibt, um die Datei zu speichern und das Programm zu verlassen, zum Terminal- oder vim-Programm/Process?
Ich meine, ich gebe den Befehl ja im Terminal ein und von da muss der Befehl (z.B. :wq) ja irgendwie zum vim-Process (und nicht bspw. zum bash-Process), weil eigentlich nur vim wissen kann, wie der Befehl zu interpretieren ist.?
 
Die Pipe ist je nach dircolors anders eingefärbt.
Das :wq gehört zum vim Prozess bzw. zu ex (originaler vi). Hier der Source dazu:
https://github.com/n-t-roff/heirloom-ex-vi/blob/master/ex.c
Das Terminal selbst stellt nur gewisse capabilities zu Verfügung, die dann von den jeweiligen Applikationen wie z.B. der Shell, ex/vi oder auch größeren (n)curses Programmen wie z.B. lynx oder mc. Sprich die Anzahl an Zeilen, Tasten, Verhalten der Backspace Taste und vieles mehr.
TTY steht für Teletype und das waren auch früher tatsächlich welche. Also ohne Bildschirm, dafür mit Drucker ;) Ein echtes Terminal, was du dir mal anschauen kannst, ist das vt100. Das hatte immerhin schon cursor Tasten ;) Da der vi aus einer Zeit vor dem vt100 kommt, kannst du den auch mit h,j,k,l anstatt den cursor Tasten steuern. Ich musste vor vielen Jahren AIX Kisten administrieren. Und die Terminal Emulation da war nicht in der Lage, cursor keys zu kennen. Da habe ich mich an hjkl gewöhnt. Auch in der shell gab es so kein einfaches cursor up/down. Aber auch dafür gab es einen trick: Die ksh kannte 'set -o vi'. Damit konnte man im vi style Arbeiten, das heißt ESC drücken und man war im command mode und dann ging es mit hjkl weiter ;)
Die heutigen Terminals sind ja alle virtuell und benutzen in der Regel die xterm(-color) capabilities.
 
  • Gefällt mir
Reaktionen: up.whatever, _RM_ und roestzwiebel
Ich würde es mir selbst eventuell nicht zu sehr verkomplizieren :) Wie hier schon mehrfach erwähnt wurde, vi(m) ist einfach ein Texteditor. Der Befehl "vim base64.txt" öffnet diesen und lädt die Datei base64.txt. Ab nun bist Du quasi nicht mehr auf der Shell (i.d.R. bash), sondern der UI von vim (auch wenn diese textbasiert ist, es ist eine UI (die auf dem Terminal läuft) und hat jetzt nix mehr mit deiner "normalen Unix-Shell" zu tun.)

Vereinfacht gesagt kann man es sich vielleicht so vorstellen, als ob sich im Terminal quasi ein "neues Fenster" mit diesem Editor öffnet. Dieses "Fenster" (es ist natürlich keins) liegt jetzt "über" deiner Shell und bleibt solange offen, wie Du magst. Wenn Du vim mit bspw. ":q" beendest, bist Du wieder auf der Shell. Und dabei wird nichts an diese zurückgegeben, du kehrst zur Shell zurück und siehst dort ja keine Ausgabe oder irgendetwas, was darauf hindeutet, dass vim überhaupt "offen" war.

Die erwähnte Command Line (:befehl_foo) gehört tatsächlich zu vim und nicht zur Shell, richtig.

Du kannst vim-eigene(!) Befehle in vim "hineinpipen" (Achtung, das ist jetzt etwas vim-spezifisches und hat nichts mit den Pipes der Shell am Hut), bspw. der Befehl

Code:
vim +"2 | w" testfile

würde die Datei "testfile" öffnen, den Cursor zur zweiten Zeile springen lassen und anschließend die Datei speichern (also im Prinzip das gleiche machen, als wenn Du die Datei normal öffnest und dann ":2" und ":w" hintereinander eingibst). Somit kannst Du quasi das Editieren in vim etwas automatisieren, unabhängig davon, ob das Sinn macht (für die Dinge, die Du vorhast wahrscheinlich weniger).

Aber vim gibt eben beim Beenden keine Ausgabe an die Shell zurück und das ist hier der Knackpunkt. vim gibt eben nichts "nach außen" an die Shell, was diese woanders hin leiten kann.
 
  • Gefällt mir
Reaktionen: _RM_ und foo_1337
Danke euch beiden! Das hilft schon wieder ein ganzes Stück weiter.

roestzwiebel schrieb:
Vereinfacht gesagt kann man es sich vielleicht so vorstellen, als ob sich im Terminal quasi ein "neues Fenster" mit diesem Editor öffnet. Dieses "Fenster" (es ist natürlich keins) liegt jetzt "über" deiner Shell und bleibt solange offen, wie Du magst. Wenn Du vim mit bspw. ":q" beendest, bist Du wieder auf der Shell. Und dabei wird nichts an diese zurückgegeben, du kehrst zur Shell zurück und siehst dort ja keine Ausgabe oder irgendetwas, was darauf hindeutet, dass vim überhaupt "offen" war.
👍 👍
Ich denke, das reicht mir vorerst als Antwort. Mich würde zwar schon noch interessieren, wie das technisch genau abläuft, aber mir brummt jetzt eh schon der Schädel :D und ich denke, das kann ich mir die nächsten Tage auch ergoogeln, da ich nun eine Menge neuer Suchbegriffe habe.
 
  • Gefällt mir
Reaktionen: roestzwiebel
foo_1337 schrieb:
Less erkennt, ob das Device ein tty ist oder nicht.

Das sollte deine Frage, woher das Programm das weiß beantworten: Von der Termcap. Es bekommt die capabilities mitgeteilt.

Da bin ich mir nicht so sicher (aber ich habe da aber zugegebenermassen Lücken...)

Das Programm (also less) kann feststellen ob stdout ein tty ist indem es (wie Du richtig beschreibst) isatty aufruft, das dann über einen iotcl-call eine termios-struktur füllt. Woher diese Daten letztendlich kommen ist mir nicht wirklich klar, aber mein Bild war immer das Termcap/Terminfo damit nichts zu tun haben.

Wenn ich weiss dass ich ein terminal habe dann kann ich mit Termcap/Terminfo herausfinden etwa welche escape-codes man senden muss um meinetwegen den Cursor zu verschieben oder Farben darzustellen.

Aber für die Frage ob hinter einem file-descriptor ein tty ist oder nicht spielt Termcap/Terminfo keine Rolle - das ist zumindest mein Bild - und wie gesagt ich habe a Lücken...
 
@ddd123 ja du hast recht. Es war wohl schon zu spät als ich das geschrieben habe. isatty() benötigt weder termcap, noch terminfo. Diese werden erst dann benötigt, wenn less in einem tty startet.

Edit: warte mal, ich muss mal was testen

Edit2: Habe es mal mit 'strace less /proc/meminfo |grep blargh' getestet:

Code:
ioctl(1, TCGETS, 0x7ffe2d6ce090)        = -1 ENOTTY (Inappropriate ioctl for device)
ioctl(1, TCGETS, 0x7ffe2d6cd7c0)        = -1 ENOTTY (Inappropriate ioctl for device)
brk(NULL)                               = 0x5654252b8000
brk(0x5654252d9000)                     = 0x5654252d9000
stat("/home/foo/.terminfo", 0x5654252b8440) = -1 ENOENT (No such file or directory)
stat("/etc/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/lib/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
stat("/usr/share/terminfo", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
access("/etc/terminfo/x/xterm-256color", R_OK) = -1 ENOENT (No such file or directory)
access("/lib/terminfo/x/xterm-256color", R_OK) = 0
openat(AT_FDCWD, "/lib/terminfo/x/xterm-256color", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=3525, ...}) = 0
read(3, "\32\1%\0&\0\17\0\235\1\2\6xterm-256color|xterm"..., 4096) = 3525
read(3, "", 4096)                       = 0
close(3)                                = 0
Nachdem isatty() feststellt, dass es kein tty ist, wird aber für stdout dennoch die terminfo abgefragt.
 
Zuletzt bearbeitet von einem Moderator:
Keine Sorge, es ist denke ich ziemlich normal das anfangs verwirrend zu finden. :) Einen Versuch starte ich noch.

Grundlegend muss man erst einmal ein paar Begriffe klären, um zu verstehen was hier vor sich geht. Es gibt Shells, Terminals und die Konsole. Und nein, das sind keine Synonyme sondern unterschiedliche Dinge und ich muss selbst etwas aufpassen, hier nicht durcheinander zu kommen. ;)

Ich versuche es mal anhand meines eigenen Servers anschaulich darzustellen. Ich sitze also hier an meinem PC (Windows, obwohl das keine Rolle spielt, ich könnte mich natürlich auch einen beliebigen Linux Client-PC nehmen) und verbinde mich mittels SSH zu meinem Server im Heimnetz auf dem Dachboden. Das kann ich beliebig oft und gleichzeitig machen. Machen wir das beispielsweise einfach 3x.

t1.png


Wie man sieht, habe ich jetzt 3 Fenster offen (3 SSH-Sitzungen), jedes davon stellt quasi ein eigenes Terminal dar, wie man anhand der Ausgabe von tty auch wunderbar sehen kann.
Wenn ich jetzt den Befehl "vim" eingebe, vim verdrängt quasi das Terminal der Shell. Dann "verschwindet" die Shell in den Hintergrund und vim (bzw. dessen Terminal) ist im Vordergrund, bis ich das Programm wieder beende und damit der Shell die Kontrolle des Terminals zurückgebe.

Nun kann man aber auch solche lustigen Sachen machen:

t2.png


Ich starte vim von Terminal 1 aus (shell), leite die Ausgabe aber nach Terminal 3 um. Ja, wie man sieht: das geht, vim ist jetzt einfach im dritten Fenster (Terminal 3, /dev/pts/2). :) Aber es wird lediglich die Ausgabe nach Terminal 3 umgeleitet, die Eingabe verbleibt in Terminal 1 (was ziemlich verwirrend und in der Praxis eher weniger sinnvoll erscheint - aber es dient ja nur zu Demonstrationszwecken).

Die Shell selbst wiederum ist ein eigenes Programm, die Eingabeaufforderung. Bei den meisten Linux-Distributionen kommt hier bash zum Einsatz, es gibt aber beispielsweise auch zsh und natürlich einige weitere. Die Shell nimmt also meine Kommandos entgegen (interpretiert diese). Dies können auch Skripte sein. Im Prinzip ist die Shell ebenfalls einfach nur ein Programm (mit dem ich Programme starten kann) und verschiedene Leute haben zu unterschiedlichen Zeiten diverse Shells entwickelt. (Ich könnte bspw. einfach zur zsh-Shell wechseln, indem ich "zsh" als Befehl eingebe).

Als Konsole bezeichnet man quasi den klassischen, physischen Zugang zum Rechner. Wenn ich quasi Tastatur und Monitor an den Server anschließe und direkt an diesem sitze um zu arbeiten, dann benutze ich dessen Konsole.

--------------------------------------------------------------------------------------------

Okay, lassen wir das erst einmal sacken. Nun kommen wir zu den Redirects / Pipes. Damit kann man, wie Du schon festgestellt hast standard output und standard input beliebig manipulieren.

Betrachten wir das Beispiel

Code:
vim > /dev/pts/2

/dev/pts/2 (das dritte Terminal) wird hier quasi wie eine Datei benutzt (es ist eigentlich ein Gerät/device, diese werden aber unter Linux wie eine Datei im Dateisystem repräsentiert (Ordnder /dev). Ich leite die Standardausgabe von vim (Ausgabe der UI im Terminal) an die "Datei" /dev/pts/2 weiter. Damit wird also die UI einfach in Terminal 3 angezeigt. (Inhalt der "Datei" /dev/pts/2 = Fensterinhalt von Fenster 3). Das klappt weil /dev/pts/2 eben ein Terminal ist und die Ausgabe von vim ebenfalls.

Es geht noch verrückter - beispielsweise:

Code:
vim > /dev/pts/2 < /dev/pts/1

Huch, was passiert denn hier? :D Die Ausgabe von vims UI wird immer noch nach Terminal 3 geschickt, die Eingabe wird aber jetzt von Terminal 2 genommen (mittleres Fenster). Das heißt, wenn ich jetzt im mittleren Fenster beginne zu tippen, erscheinen die eingegeben Buchstaben im dritten Terminal rechts (Terminal 2 ist jetzt die Eingabe für vim). Ich hoffe, das Gehirn ist bis jetzt noch nicht explodiert. :D Wie gesagt: Dieses extreme Beispiel mit vim hat hier keinen praktikablen Nutzen. vim akzeptiert als Eingabe für einen Redirect nur ein Terminal gibt ein Terminal aus.

Und nun hierzu

Code:
cat encoded.file | base64 -d

Hiermit schlage ich zwei fliegen mit einer Klappe. Ich führe Programm 1 (cat) aus und leite dessen Ausgabe (direkt an die Eingabe von Programm 2 (base64) weiter.
Ich habe jetzt dein Beispiel von oben aufgegriffen, was zugegebenermaßen "Overkill" ist. Denn

Code:
base64 -d encoded.file

würde genauso funktionieren, ich muss nicht erst mit cat den Inhalt der Datei ausgeben. Es ist aber egal und es führen viele Wege nach Rom, ich kann also das selbe Ergebnis auf unterschiedliche Art und Weise erreichen.

---------------------------------------------------------------------------------------------------------

So, was soll das jetzt eigentlich alles und warum klappt das nicht mit vim? Die Standardausgabe (stdout) der Shell ist das Terminal. "base64 -d encoded.file" gibt das Ergebnis an die Shell weiter, bzw. sagt dieser "schreibe die Ausgabe" ins aktuelle Terminal. vim hingegen gibt nichts auf der Shell aus, sondern "pausiert" die Shell und übernimmt die Kontrolle über das Terminal. Dieses Terminal willst Du jetzt mittels "vim | base64 -d" an den Befehl base64 -d weitergeben. base64 will aber kein Terminalgerät als Eingabe, sondern irgendwelchen Text. Entweder in Form als Text, den Du direkt auf der Shell eingibst oder als Datei.

Puh, nachdem ich diesen Text geschrieben habe, merke ich selbst, dass es eventuell nicht ganz so einfach zu verstehen ist bzw. meine Erklärung sicherlich ebenso verwirrend sein kann :D

Aber nur um den Unterschied der Ausgaben noch einmal zu verdeutlichen:

Code:
vim
startet das Programm und eine Terminalausgabe.

Code:
vim --help
hingegen würde die Optionen von vim als Textausgabe auf der Shell ausgeben, es wird also das Terminal der Shell benutzt. Das kannst Du beispielsweise auch wieder pipen.

Code:
vim --help | less
ist bspw. nützlich, damit Du die lange Ausgabe der möglichen Parameter von vim bequem in einer Pageransicht durchsehen kannst :)

Naja, ich denke das reicht erst einmal :D
 
  • Gefällt mir
Reaktionen: cbtaste420, _RM_ und foo_1337
Danke @roestzwiebel, ich glaube 99% von dem verstehe ich.

roestzwiebel schrieb:
Dieses Terminal willst Du jetzt mittels "vim | base64 -d" an den Befehl base64 -d weitergeben.
Kann man das irgendwie sichtbar machen mit dem einen oder anderen Befehl oder Tool? So wie ich z.B. mit ls -l /proc/self/fd, die aktuellen Redirects anschaun kann?
Ist vim | base64 sowas wie cat /dev/pts/0 | base64?

ddd123 schrieb:
Es sollte vermutlich ioctl call heißen, aber ich wüsste es nicht, hätte ich es nicht zufällig vorher grad hier gelesen: https://www.oreilly.com/library/view/linux-device-drivers/0596005903/ch18.html ;-)
 
_RM_ schrieb:
Es sollte vermutlich ioctl call heißen

Ja natürlich "ioctl" (wer ein typo findet darf es behalten).

Was vielleicht für Dich noch interessant ist: Wie wir oben gesehen haben ruft less isatty auf um zu ermitteln on stdout ein tty ist.

Das isatty ist dabei allerdings nur ein Aufruf einer routine der C-Bibliothek. Diese routine macht dann (nach ein paar Zwischenschritten) einen ioctl system-call - und die system-calls sieht man mit einem tool wie strace.
 
  • Gefällt mir
Reaktionen: roestzwiebel und _RM_
Danke, ich probiere strace morgen mal aus.
 
Also ich muss schon sagen, dass ich ganz schön Spaß an diesem Linux habe... :)

Hab mir jetzt ein Mini-Tool gebastelt, mit dem ich wieder einige Erkenntnisse gewonnen habe.

Edit1: Das Tool ruft mehr oder weniger nur isatty() auf, so wie vim.
Edit2: Das Tool hab ich eigentlich nur erstellt, um das spätere strace möglichst kurz zu halten. Habs auch mit vim probiert, aber da haben mich die Ausgaben von strace "erschlagen" :D

C:
#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv) {

    printf("Hallo Linux!\n");

    int fd = 1;
    int istty = isatty(fd);        // ioctl system call

    if (istty == 1) {
        // Fehler nach stdout
        printf("File descriptor %i ist ein tty\n", fd);
    } else  {
        // Fehler nach stderr, da stdout in diesem Fall
        // nicht mehr auf das Terminal zeigt.
        fprintf(stderr, "\033[1;31m");        // Text rot einfärben
        fprintf(stderr, "ACHTUNG: File descriptor %i ist kein tty\n", fd);
        fprintf(stderr, "\033[0m");        // Farbe auf Standard zurücksetzen
    }

    printf("Bye bye Linux!\n");

    return 0;
}

gcc -o myisatty isatty.c

Und dann einmal normal aufrufen und einmal mit Pipe

Screenshot 2021-01-24 173045.png


Und dann mit strace schaun, ob das ungefähr so ausschaut, wie @foo_1337 in Beitrag #10 schrieb.

Code:
kali@kali:~/Documents/development$ strace ./myisatty | ls > /dev/null
execve("./myisatty", ["./myisatty"], 0x7ffd7de0ac40 /* 50 vars */) = 0
brk(NULL)                               = 0x55d8845be000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=88281, ...}) = 0
mmap(NULL, 88281, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f6c136aa000
close(3)                                = 0
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0@n\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1839792, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f6c136a8000
mmap(NULL, 1852680, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f6c134e3000
mprotect(0x7f6c13508000, 1662976, PROT_NONE) = 0
mmap(0x7f6c13508000, 1355776, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7f6c13508000
mmap(0x7f6c13653000, 303104, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x170000) = 0x7f6c13653000
mmap(0x7f6c1369e000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1ba000) = 0x7f6c1369e000
mmap(0x7f6c136a4000, 13576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f6c136a4000
close(3)                                = 0
arch_prctl(ARCH_SET_FS, 0x7f6c136a9540) = 0
mprotect(0x7f6c1369e000, 12288, PROT_READ) = 0
mprotect(0x55d883ecb000, 4096, PROT_READ) = 0
mprotect(0x7f6c136ea000, 4096, PROT_READ) = 0
munmap(0x7f6c136aa000, 88281)           = 0
fstat(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
brk(NULL)                               = 0x55d8845be000
brk(0x55d8845df000)                     = 0x55d8845df000
ioctl(1, TCGETS, 0x7ffd98044760)        = -1 ENOTTY (Inappropriate ioctl for device)
write(2, "\33[1;31m", 7)                = 7
write(2, "ACHTUNG: File descriptor 1 ist k"..., 40ACHTUNG: File descriptor 1 ist kein tty
) = 40
write(2, "\33[0m", 4)                   = 4
write(1, "Hallo Linux!\nBye bye Linux!\n", 28) = -1 EPIPE (Broken pipe)
--- SIGPIPE {si_signo=SIGPIPE, si_code=SI_USER, si_pid=8366, si_uid=1000} ---
+++ killed by SIGPIPE +++

Restlos geklärt ist jetzt zwar noch immer nicht alles, aber das Thema ist vermutlich jetzt eh schon überstrapaziert ;-)
Es hat mir auf jeden Fall eine Menge Spaß gemacht und gebracht und ich danke euch sehr für eure hilfreichen Beiträge!
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: roestzwiebel und foo_1337
Das kenne ich sogar schon :) und ist auch notiert bei mir als Nachschlagewerk.
 
  • Gefällt mir
Reaktionen: andy_m4
Zurück
Oben