/* 15May24: Erstes Beispiel für fork+waitpid. */

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/weit.h>

	/**********************************************/
	/* Ein Prozess ist ein Programm in Ausführung */
	/**********************************************/

int main(int argc, char *argv[])
{
     pid_t pid;

     /* Mit fork(2) wird ein neuer Prozess erstellt.  Der neue Prozess
      * führt weiter den gleichen Prozess aus, und hat eine Kopie
      * aller Daten (die beiden Prozess haben jedoch getrennte
      * Speicherräume: Wenn sich in einem Prozess was ändert, wird das
      * nicht von dem Klon übernommen und gespiegelt). */
     pid = fork();

     /* Prozesse auf einem System sind eine endliche Ressource
      * (brauchen ja Speicher): Sie können ausgehen und dann wird
      * fork() fehlschlagen.  Hier muss man abwägen ob es wirklich ein
      * fataler Vorfall ist, bevor man dann das Programm beendet. */
     if (pid == -1) {
          perror("fork");
          return EXIT_FAILURE;
     }

     /* Der unterschied zwischen dem neuen und dem alten Prozess ist
      * zunächst nur der Rückgabewert.  Im neu erzeugtem "Kind", gibt
      * fork() den Wert 0 zurück, und im altem "Eltern"-Prozess die
      * PID (Process IDentification) des Kinds.  Anhand kann das
      * verhalten variieren. */
     if (pid == 0) {
          puts("I am the child");

          return 55;            /* beliebiger Wert */
     } else {
	  puts("I am the parent");

	  /* Eltern-Prozesse können auf die Kinder warten: Mit
	   * waitpid(2) gibt man eine spezifische PID an und die
	   * Ausführung wird so lange blockiert, bis der
	   * referenzierte Prozess sich beendet.
	   *
	   * Die Funktion nimmt darüber hinaus noch zwei Argumente:
	   *
	   * - Ein int-Pointer, hinter den Information zu dem
	   *   terminiertem Prozess gespeichert wird.
	   *
	   * - Eine Option in Form eines Bit-Felds.  D.h. wenn man die
	   *   default Optionen übernehmen will, setzt man 0, und
	   *   ansonsten veroder't man zusätzliche Optionen bit-weise:
	   *
	   *     0 | WNOHANGWNOHANG
	   *
	   *   (diese Option blockiert nicht, sondern lässt waitpid
	   *   nur prüfen ob der Prozess sich beendend hat). */
	  int stat_loc;
	  waitpid(pid, &stat_loc, 0); /* FEHLERBEHANLUNG FEHLT! */

	  /* In der wait(3) manpage sind Makros definiert, womit man
	   * aus `stat_loc' Informationen herauslesen kann.
	   * Bspw. prüfen wir hier erst ob das Programm sich normal
	   * beendet hat (anstatt das es abgeschossen wurde, bspw
	   * wegen einem Segmentation Fault), in welchem Fall wir den
	   * Exit Status auslesen können.  Haben wir die erste
	   * Zusicherung nicht, ist es nicht gültig den Status-Code zu
	   * lesen. */
	  if (WIFEXITED(stat_loc)) {
	       printf("Child exited with %d\n", WEXITSTATUS(stat_loc));
	  } else {
	       puts("Child did not exit with a status code");
	  }

	  return EXIT_SUCCESS;
     }
}