Weiterleiten von Argumenten an anderes Programm



  • Btw: Nach elf Jahren mein zweites Posting hier im Forum. 🙂

    Folgendes Problem:
    Es gibt ja so manchen Cross-Compiler, bei dem Entwickler von Programmen, die damit kompiliert wurden, auf make- und ninja-Skripte setzen.
    Will man das Programm oder ein anderes Programm selber kompilieren, dann funktioniert jedoch leider gar nichts, weil man die ganzen Compiler- und Linker-Optionen nicht richtig gesetzt hat.

    Daher habe ich nun kleine Hilfsprogramme geschrieben, die leider nicht alle funktionieren (und ich weiß nicht warum).

    Als Hilfsprogramm ist hier erst einmal hallo.c genannt, das auf Linux zu hallo kompiliert wird.

    #include <stdio.h>
    
    int main() {
        printf("Hallo zusammen!\n");
        return 0;
    }
    

    Um mir die Übergabe auf der Kommandozeile anzusehen, habe ich folgendes kleines Programm printit.c geschrieben

    #include <stdio.h>
    
    int main(int argc, char *argv[]) {
      int i=0;
      printf("\n[->] %s", argv[0]);
    
      for (i=1; i<argc; i++) {
         printf(" %s", argv);
      }
    
      printf("\n");
      return 0;
    }
    

    Ein Test mit der Eingabe von

    $ ./printit egreg wgrgh wrgh
    

    gibt auch

    [->] ./printit egreg wgrgh wrgh
    

    aus.
    So weit so gut.
    Das heißt, wenn ich den gcc durch das Programm ersetze, dann werden mir die Kommandozeileonptionen zurückgegeben, die während des Kompilierens übergeben wurden.

    Nun will ich jedoch nicht einfach nur die Compiler durch solche Binaries ersetzen, denn der Compiler soll auch gleichzeitig seine Aufgabe erfüllen.
    Daher möchte ich, daß das eigentliche Programm ebenfalls aufgerufen wird.

    Hier mein Programm printit4.c

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <dirent.h>
    
    int main(int argc, char *argv[]) {
       char *string = argv[0];
       int ret;
       int i=0;
       printf("\n\n[->] %s", argv[0]);
    
       for (i=1; i<argc; i++) {
         printf(" %s", argv[i]);
       }
    
       printf("\n\n");
    
       strncat(string, ".orig",5);
       execvp(string, argv);
    
       return -1;
    }
    

    Der erste Test ist nun das Binary [i]hallo* (*) in hallo.orig umzubenennen und printit4 zu hallo zu kopieren.
    Ausführen vom neuen hallo liefert dann

    $ ./hallo
    
    [->] ./hallo
    
    Hallo zusammen!
    

    Wuderbar. Nun benenne ich printit in printit.orig um und printit4 kopiere ich zu printit.
    Aufruf vom neuen printit mit Argumenten:

    $ ./printit dew wegewg 4 646 jm   rtg4 4t4
    
    [->] ./printit dew wegewg 4 646 jm rtg4 4t4
    
    [->] ./printit.orig orig  4 646 jm rtg4 4t4
    

    Man sieht, daß an das ursprüngliche printit4-Programm (das als Binary nun printit hieß)alles richtig übergeben wurde. Nur hat dieses Programm dann die Argumente nicht richtig an das Original printit (dessen Binary nun printit.orig heißt) übergeben. Warum?

    Grüße
    theuserbl

    (*) An der Stelle wird nun das in [ i ] und [ /i ] gesetzte "hallo" nicht kursiv geschrieben. Keine Ahnung, was da nun wieder falsch gelaufen ist.


  • Mod

    strncat(string, ".orig",5);
    

    Woher weisst du, dass argv[0] Platz für weitere 5 Zeichen hat?



  • camper schrieb:

    strncat(string, ".orig",5);
    

    Woher weisst du, dass argv[0] Platz für weitere 5 Zeichen hat?

    Eigentlich wußte ich es gar nicht. Hatte mich auch damit vertan, indem ich string mit dem Pointer identisch mit arg[0] machte.

    Hatte zuletzt hauptsächlich mit Java zu tun gehabt (die Sprache ohne Pointer).

    Hier nun mein überarbeitetes Programm:

    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #include <dirent.h>
    
    int main(int argc, char *argv[]) {
      int laenge = strlen(argv[0]) + 7;
      char string[laenge];
      strcpy(string, argv[0]);
    
      int ret;
      int i=0;
      printf("\n\n[->] %s", argv[0]);
    
      for (i=1; i<argc; i++) {
        printf(" %s", argv[i]);
      }
    
      printf("\n\n");
    
      strncat(string, ".orig",5);
    
      execvp(string, argv);
    
      return -1;
    }
    

    Und hier die Ausgabe, wenn ich das Binary wieder zu "printit" kopiere:

    $ ./printit efrh ergr rgregergh re 5436 546 gerg 
    
    [->] ./printit efrh ergr rgregergh re 5436 546 gerg
    
    [->] ./printit efrh ergr rgregergh re 5436 546 gerg
    

    Die Ausgabe verstehe ich nun auch wieder nicht.
    Also aus dem string wurde nun "./printit.orig". Die Ausgabe lautet aber "./printit" 😕
    Sollte das Programm sich ewig selbst aufrufen, dann wäre es eine Endlosschleife. Macht es aber nicht. Es ruft "./printit.orig" auf. Und warum sagt "./printit.orig" nun etwas von "./printit" ?

    Das ist zwar der erste Wert vom argv-Array, aber das dürfte printit.orig doch egal sein, denn es wurde doch ganz anders aufgerufen. 😕

    Danke noch mal für die schnelle Antwort.

    Grüße
    theuserbl



  • Will man das Programm oder ein anderes Programm selber kompilieren, dann funktioniert jedoch leider gar nichts, weil man die ganzen Compiler- und Linker-Optionen nicht richtig gesetzt hat.

    Tja, das ist dann aber nicht Schuld der Programme, sondern deine eigene, weil du die diversen make Optionen/Alternativen nicht kennst und/oder richtig bedienen kannst. Es ist sinnfrei, sich eigene Projektverwaltungstools zu bauen - allenfalls zu Programmier-Gehversuchen.

    Hatte zuletzt hauptsächlich mit Java zu tun gehabt

    Also keinerlei verwertbare Vorkenntnisse.

    (die Sprache ohne Pointer)

    lol
    lollol
    lollollol
    Wie hieß doch nochmal die häufigste Deppenjava-Exception?
    Ich glaube doch sowas wie NullPointerException

    #include <unistd.h> /* kein Standard */
    #include <dirent.h> /* kein Standard */
    
    int main(int argc, char *argv[]) {
      int laenge = strlen(argv[0]) + 7;
      char string[laenge]; /* nur Deppen verwenden VLA */
      strcpy(string, argv[0]);
    
      int ret;
      int i=0;
      printf("\n\n[->] %s", argv[0]);
    
      for (i=1; i<argc; i++) {
        printf(" %s", argv[i]);
      }
    
      printf("\n\n");
    
      strncat(string, ".orig",5); /* wieso nicht einfach strcat? */
    
      execvp(string, argv); /* kein Standard */
    
      return -1; /* sinnfrei, da im hosted environment nicht portabel auswertbar */
    }
    

    exec* starten das Programm nicht in einem neuen Prozess, d.h. das bestehende Prozessenvironment (wozu auch die argv-Argumente gehören) wird wiederverwendet.
    Nimm system (Standard) zum Starten eines neuen Prozesses.


  • Mod

    man 3 execvp schrieb:

    The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a NULL pointer.



  • Wie ich diese Form der Klammerung (und Nicht-Einrückung) hasse...
    Unübersichtlicher geht's kaum noch.


Anmelden zum Antworten