#include #include #include #include #include // Siehe auch die Datei 03-Makefile. ;) static int compare(const void *p1, const void *p2) { return strcmp(*(const char **)p1, *(const char **)p2); } // Beispiel: `./listRun echo Das ist ein Test` // argv[0]: Programmname selbst ("./listRun") // argv[1]: auszufuehrendes Programm (z.B. "echo") // argv[2...]: Argumente (z.B. "das ist ein Test") // -> `echo Das` // -> `echo ist` // -> `echo ein` // -> `echo Test` int main(int argc, char *argv[]) { // Argumente ueberpruefen ist eigentlich immer eine gute Idee, damit der // Benutzer eine gute Fehlermeldung bekommt. Ausserdem kann dann nichts // schief gehen - in vielen Faellen greift man sonst versehentlich mal auf // NULL zu, was boese enden kann. ;) if (argc < 3) { fprintf(stderr, "usage: %s \n", argv[0]); exit(EXIT_FAILURE); } // Optional: sortieren der Argumente. qsort(argv + 2, argc - 2, sizeof(*argv), compare); // Iterieren ueber die Argumente fuer das auszufuehrende Programm. for (int i = 2; i < argc; i++) { pid_t pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); // Hier koennte man auch ueber "continue" nachdenken. } else if (pid == 0) { // Kindprozess // Wichtig: der Programmname ("argv[1]") muss doppelt uebergeben // werden. Das vergisst man leicht... ;) execlp(argv[1], argv[1], argv[i], NULL); /* Alternativ: char *av[] = {argv[1], argv[i], NULL}; execvp(argv[1], av); */ // Die exec(3)-Funktionen returnen nur im Fehlerfall (im Erfolgsfall // wird das aktuell ausgefuehrte Programm quasi komplett ersetzt), // deswegen kann die Fehlerbehandlung direkt folgen - ohne den // Rueckgabewert anzuschauen. perror("execlp"); exit(EXIT_FAILURE); } else { // Elternprozess // Wir warten hier, bis sich der Kindprozess beendet, damit die // Reihenfolge der Argumente auf jeden Fall eingehalten wird. Es // waere prinzipiell auch moeglich, das hier nicht zu tun. int status; if (wait(&status) == -1) { perror("waitpid"); // exit(2)/continue kann man machen, wenn man es fuer sinnvoll // haelt. } // Alternativ: waitpid(pid, &status, 0) } } }