Lesen von STDIN statt aus Datei

Hallo Wissende,

gegeben sei ein Kommandozeilenprogramm unter Linux, das ein Argument erwartet, welches das Programm als Namen seiner Eingabedatei interpretiert. Ich möchte das Programm aber von einem anderen Programm aus aufrufen, und würde ihm seine Eingabedaten lieber via Pipe übergeben. Gibt es eine Möglichkeit, das zu erreichen, ohne auf temporäre Dateien auszuweichen? Einige Programme lesen von STDIN, wenn der Dateiname „-“ ist (z.B. vim), aber das scheint hier nicht zu funktionieren. Irgendwelche Ideen?

Gruß
Chondron

Hallo Chondron,

gegeben sei ein Kommandozeilenprogramm unter Linux, das ein
Argument erwartet, welches das Programm als Namen seiner
Eingabedatei interpretiert. Ich möchte das Programm aber von
einem anderen Programm aus aufrufen, und würde ihm seine
Eingabedaten lieber via Pipe übergeben.

Sind da der „Dateiname“ und die „Eingabedaten“ das gleiche?
Das heisst, Du möchtest ihm den Namen der Eingabedatei übergeben? Mit

befehl1 | befehl2

liest befehl2 von der Standardausgabe des befehls1
http://www.trampelwurm.ch/schmidt/wilhelmtux/swissre…
dort und anderswo unter dem Begriff „pipe“
Allerdings müsstest Du schon etwas präziser werden, welcher Befehl welches Argument erwartet. Wenn dein Befehl das Argument z.B. nur so erwartet

befehl -d dateiname

dann ist eine Pipe nicht geeignet.
Eine andere Möglichkeit wäre eventuell die Kommandosubstitution mittels $( befehl )
http://de.linwiki.org/wiki/Linuxfibel_-_Shells_-_Bas…

das scheint hier nicht zu
funktionieren.

Warum? Gibt es einene Fehlermeldung (welche?) oder passiert nichts? Du müsstest also genauer schreiben, wie dein erster Befehl sein Argument erwartet und wie der zweite Befehl das Argument ausgibt.

Viele Grüße
Marvin

Hallo Marvin,

also, konkret: das Programm ist flasm. Aufruf funktioniert wie folgt:

Usage: flasm [command] filename

Commands:
 -d Disassemble SWF file to the console
[...]

Ich hätte jetzt aber gerne, dass die Daten nicht aus

filename

sondern von STDIN gelesen werden, sodass ich keine temporäre Datei brauche.

Gruß
Chondron

Hallo Chondron,

das Programm ist flasm. Aufruf funktioniert wie
folgt:

flasm [command] filename
Ich hätte jetzt aber gerne, dass die Daten nicht aus

filename

sondern von STDIN gelesen werden, sodass ich keine temporäre
Datei brauche.

Hm, ich bin etwas schwer von Begriff und sehe die temporäre Datei noch nicht. Du hast eine swf-Datei, sagen wir foo.swf und willst sie disassemblieren. Also gibst Du

flasm foo.swf

ein und fertig. Oder erzeugst Du foo.swf erst mit einem anderen Programm? Sagen wir mal das Programm bar erzeugt die Datei foo.swf, die dann wiederum durch flasm gedreht werden soll? Du siehst, ich durchschaue den Ablauf noch nicht so recht :frowning:
Da aber flasm nicht von Standard-In lesen kann (ich habe es nicht da, aber in der Manpage steht zumindest nichts davon), so erschlägt man das meist mit einem Miniskript, etwa so:

DATEI="foo.swf"
bar ${DATEI} && flasm ${DATEI}

wobei man die Variable DATEI eigentlich lieber als Parameter übergeben sollte. Für das imaginäre Programm bar habe ich jetzt einfach angenommen, daß es den Namen der zu erzeugenden Datei auch als Parameter empfängt. Die Verkettung mit && bewirkt, daß flasm nur ausgeführt wird, wenn zuvor bar erfolgreich war, also tatsächlich die Datei foo.swf erzeugt hat.
Bisschen viel Annahmen, aber vielleicht kannst Du mir noch etwas mehr über den bisher unbekannten ersten Befehl sagen.

Viele Grüße
Marvin

Hallo Marvin,

sorry dass ich Verwirrung stifte, also hier mal der Kontext der Geschichte:
Ich entwickle ein Programm, das in Flash-Dateien enthaltene Links (URLs) analysieren muss. Zu diesem Zweck muss man die URLs natürlich zunächst extrahieren.
Was ich habe ist der Inhalt einer SWF-Datei, der in einer Variablen meines Programms gespeichert ist (Die Datei selbst habe ich aber nicht, die empfange ich übers Netzwerk). Die Daten möchte ich jetzt durch flasm jagen und den Output nach den besagten URLs durchsuchen. Jetzt könnte man natürlich einfach hingehen, die SWF-Daten auf die Platte schreiben, flasm auf die Datei loslassen, den Output wieder einsammeln und die temporäre Datei löschen. Aus verschiedenen Gründen, nicht zuletzt Performanz, möchte ich eine solche Lösung aber vermeiden. Daher wäre es schön, wenn ich flasm die Daten auf STDIN schicken könnte.

Alle Klarheiten beseitigt? :smile:

Gruß
Chondron

Hallo Chondron,

Alle Klarheiten beseitigt? :smile:

Joo! :wink:
Aber da flasm, soweit ich das sehe, keine Eingaben von stdin erwartet (was ungewöhnlich für Linux-Programme ist), weder mit Pipe noch mit Umlenkung, also _, sehe ich hier keine Chance.
Die Performance liesse sich erhöhen, wenn Du die Datei im RAM ablegst, wenn das denn möglich ist.
Tut mir leid, aber vielleicht fällt ja jemand anderem was ein…

Viele Grüße
Marvin_

Hallo Chondron,

ich habe mir mal den Quelltext von flasm angeschaut (http://www.nowrap.de/download/flasm16src.zip von http://www.nowrap.de/flasm.html), danach ist eine Unterstützung von der Standardeingabe nicht enthalten. Diese lässt sich aber leicht nachrüsten:
In der Datei flasm.c vor der Zeile 1732 die Zeilen

 if (strcmp(inputName, "stdin") == 0)
 inputFile = stdin;
 else

einfügen. Dann sieht der Block so aus:

 if (inputName == NULL)
 usage();

 if (strcmp(inputName, "stdin") == 0)
 inputFile = stdin;
 else
 if ((inputFile = fopen(inputName, "rb")) == NULL)
 tellUser(1, "Couldn't open input file %s for reading", inputName);
}

int main(int argc, char \*argv[])

Wenn Du nun (nach dem Kompilieren) als Dateinamen ‚stdin‘ angibst, dann wird die Standardeingabe verwendet.

Getestet habe ich dies mit

wget -q -O - http://cache.addthis.com/downloads/demo/flash/latest/helloworld\_icons.swf | ./flasm -d stdin

Gruß
Diether

Hallo Diether,

wow, hätte nicht erwartet, dass da gleich ein kompletter Patch zurückkommt. Vielen Dank!

Gruß
Chondron

Hi,

als Alternative zu der Patch-Lösung: Die Datei-Deskriptoren der Prozesse sind im virtuellen proc-Dateisystem verfügbar. Also kannst du so etwas machen:

... | foo /proc/self/fd/0

Ich weiß momentan nicht, wie weit Folgendes standardisiert ist, aber normalerweise gibt es dafür auch eine praktische Abkürzung:

... | foo /dev/stdin

Beides setzt natürlich voraus, dass der Befehl foo überhaupt auf einem Stream arbeiten kann (und nicht z.B. in der Datei herumspringen will).

Viele Grüße

Andreas