/* 17May24: Eine eigene einfache Implementierung von execvp ("Execute
 * Vector in Path").  Das ist ein eigenes Modul, welches wir
 * zusammenbinden mit dem Haupt-Modul.
 *
 * Die Idee ist zu zeigen, wie execvp (welches den PATH auflöst) auf
 * einer Funktion wie execv (welches immer einen absoluten Pfad zur
 * ausführbaren Datei braucht). */

#include <stdlib.h>
#include <unistd.h>
#include <string.h>

/* Auch hier brauchen wir die Header-Datei, damit man sichergehen
 * kann, dass sich unser Programm auch an die Schnittstelle hällt. */
#include "execvp.h"


int _execvp(char *cmd, char *argv[])
{
     /* Wir holen uns erst den PATH aus der Umgebung.  Der PATH ist
      * ein String welches mit Doppelpunkten Verzeichnisse aufzählt wo
      * man Programme finden kann.  Damit wird "ls" zu "/usr/bin/ls"
      * aufgelöst.  */
     char *path = getenv("PATH"); /* /usr/bin:/bin:... */

     /* Mit strtok können wir `path' Stück für Stück abarbeiten.  Wir
      * teilen immer an den Doppel-Punkten den String und bauen uns
      * daraus einen absoluten Pfad auf: */
     char *dir = strtok(path, ":");
     while (dir != NULL) {
	  /* Hier haben wir ein Variable Length Array (VLA) welches so
	   * groß ist, damit es den neuen Dateipfad halten kann.
	   * Danach benutzen wir Funktionen aus string.h um die Datei
	   * aufzubauen. */
	  char filepath[strlen(dir) + 1 + strlen(cmd) + 1];
	  strcpy(filepath, dir);
	  strcat(filepath, "/");
	  strcat(filepath, cmd);

	  /* Mit diesem String versuchen wir spekulativ execv
	   * auszuführen.  Wenn es klappt, dann haben wir den Programm
	   * im Prozess ersetzt, ansonsten läuft unser Programm
	   * weiter. */
	  execv(filepath, argv);

	  /* Wenn wir mit strtok(NULL, ...) aufrufen, dann wird es den
	   * letzten Aufruf fortsetzen, und die nächste Komponente
	   * (Token) bis zu einem ":" zurückgeben -- oder NULL wenn
	   * wir nichts mehr haben. */
	  dir = strtok(NULL, ":");
     }

     /* Wenn wir hier angekommen sind, dann haben wir nichts gefunden
      * und deuten einen Fehler an.  */
     return -1;
}