fork()-Problem beim öffnen des vi-Editors aus einem C++-Programm heraus



  • Hallo zusammen,

    ich habe zwar schon den einen oder anderen Hinweis hierzu gefunden, so richtig weitergeholfen hat es mir aber leider nicht.
    Daher beschreibe ich mein Problem hier einfach mal.

    Ich versuche gerade, unter Linux aus einem C++-Programm den vim-Editor zu öffnen (was ansatzweise auch schon klappt).
    Aber irgendwie scheint die Geschichte mit dem fork() noch nicht ganz zu funktionieren. Mein Problem ist folgendes:

    Ich starte das Programm und übergebe den Namen der zu öffnenden Datei als Parameter.
    Der Editor öffnet sich (unten steht also so was wie " "testdatei.txt" [New File] " aber sobald ich irgendeine Taste drücke, z.B. 'i' um in den Insert-Mode zu gelangen, erhalte ich die Meldung

    Vim: Error reading input, exiting...

    Vim: Finished.

    Anschließend finde ich mich auf der Shell wieder und darf das Terminal resetten...

    Hier erst einmal der Code:

    #include <iostream>
    #include <unistd.h>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    	pid_t cpid;
    
    	int ret;
    	char filename[50];
    
    	cout << "Anzahl Argumente: " << argc << endl;
    
    	if(argc == 2)
    	{	strcpy(filename, argv[1]);
    		cout << "Oeffne Datei: " << filename << endl;
    
    		cpid = fork();
    
    		if(cpid == 0)
    		{
    			cout << "Child PID: " << cpid << endl;
    			ret = execl ("/usr/bin/vim", "vi", filename, (char *)0);
    
    			exit(255); 
    		}
    	}
    	else
    	{
    		cout << "Syntax: ./[Programmname] [Dateiname]" << endl;
    	}
    
    	cout << "Programmende!" << endl;
    
    	return 0;
    }
    

    Lasse ich dagegen den fork()-Teil weg, öffnet sich der Editor, ich kann etwas eingeben, speichern und gut.
    Allerdings beendet sich das aufrufende Programm damit auch, was jedoch nicht beabsichtigt ist.

    Vom Ablauf her soll es eigentlich so aussehen, dass das Programm eine Art Wrapper um den vi(m) bildet.
    Nachdem also der Editor geschlossen wurde, soll das Programm noch ein paar weitere Aktionen ausführen, bis es beendet wird.

    Vielen Dank schon mal vorab!

    Gruß,
    kyusho



  • Vermute einfach mal daran das der vim versucht std::cin zu lesen (ist ja schließlich ein Konsolenprogramm) und daran scheitert, da dies an dein Programm gebunden ist. Du musst vim wohl in einer neuen Terminal-Session starten.



  • Du musst vim wohl in einer neuen Terminal-Session starten.

    Hmm, das kann ich mir irgendwie nicht vorstellen.
    Ich hatte (allerdings vor Jahren) mal ein Projekt gesehen, das ähnliche Funktionalität aufwies und bei welchem der Editor in der gleichen Shell/Terminal-Session geöffnet und geschlossen wurde.

    Und, wie schon gesagt, ohne das fork() klappt es ja auch in der gleichen Shell.
    Irgendwie muss es dann ja scheinbar gehen...



  • Ohne das fork wartet dein Programm ja auch und nutzt std::cin nicht.



  • Hmm, also nach langem googlen und diversen Versuchen mit pipe(), fork() und popen() verzweifele ich nun langsam.

    Jedesmal wenn ich das Ganze anhand irgendwelcher simplen Beispiel-Programme nachvollziehen konnte (viele davon in der Art eines Aufrufs von "ls *" aus einem C++-Programm heraus) und es dann wieder mit meinem vi-Aufruf versuche, geht's in die Hose... 😕

    Mal heißt es:

    Vim: Warning: Output is not to a terminal

    , dann wieder

    Vim: Warning: Input is not from a terminal

    .

    Aber ich denke, eigentlich müsste ich doch auf dem richtigen Weg sein, oder?
    Für mein Verständnis müsste es doch eigentlich wie folgt ablaufen:

    - Programmstart mit der zu öffnenden Datei als Parameter.
    - Anlegen einer Pipe zwischen Programm und vim-Editor.
    - Kind-Prozess erzeugen und die Ein- und Ausgaben zwischen Programm und vim-Editor (Aufruf per execl()) über die Pipe abwickeln.
    - Datei im vim-Editor speichern und diesen beenden, wobei das C++-Programm noch weiterläuft und ein paar weitere Aufgaben durchführt.
    - Programmende

    Alternativ dazu habe ich ein paar Beispiele mit popen() gefunden. Leider funktionieren diese auch nur mit dem "ls"-Befehl oder ähnlich simplen Dingen.
    Versucht man, den vi irgendwie darüber anzusprechen, geht's wieder in die Hose...

    Kann ja sein, dass ich auf dem absoluten Holzweg bin aber wie sollte es sonst gehen?
    Wie müsste ich es z.B. anfangen, wenn ich den vi in einer neuen Terminal-Session starten würde?

    Hat vielleicht jemand 'nen Tip?

    Danke!


Log in to reply