=========================== Umgebungsvariablen und exec [TOC] =========================== Der POSIX-Standard sieht folgende Varianten für _exec_ vor: ---- CODE (type=c) ------------------------------------------------------------ int execl(const char *path, const char *arg0, ... /*, (char *)0 */); int execle(const char *path, const char *arg0, ... /*, (char *)0, char *const envp[]*/); int execlp(const char *file, const char *arg0, ... /*, (char *)0 */); int execv(const char *path, char *const argv[]); int execve(const char *path, char *const argv[], char *const envp[]); int execvp(const char *file, char *const argv[]); int fexecve(int fd, char *const argv[], char *const envp[]); ------------------------------------------------------------------------------- Normalerweise werden nur die Argumente übergeben, aber die Varianten _execle_, _execve_ und _fexecve_ sehen auch die Übergabe der Umgebungsparameter vor. Wenn die Umgebungsparameter nicht mit angegeben werden, wird stattdessen implizit _environ_ übergeben, das bei Bedarf so selbst deklariert werden kann: ---- CODE (type=c) ------------------------------------------------------------ extern char **environ; ------------------------------------------------------------------------------- Die Zeigerliste _environ_ wird mit einem Nullzeiger terminiert und die einzelnen Elemente zeigen auf nullbyte-terminierte Zeichenketten, die jeweils mindestens ein `'='` enthalten. Der Teil vor dem ersten `'='` ist der Name der jeweiligen Umgebungsvariablen, der Teil danach ist der Wert. Die Umgebungsvariablen sind nicht nur über _environ_ zugänglich, sondern können auch bei _main_ über den dritten Parameter bezogen werden. Folgendes Programm gibt sämtliche Umgebungsparameter aus: :import: session02/printenv.c Die Umgebungsvariablen von _environ_ können mit Hilfe der Funktionen _getenv_ und _setenv_ aus `#include ` abgefragt und verändert werden: ---- CODE (type=c) ------------------------------------------------------------ char *getenv(const char *name); int setenv(const char *envname, const char *envval, int overwrite); int unsetenv(const char *name); ------------------------------------------------------------------------------- Hierbei verändert _setenv_ eine bereits vorhandene Umgebungsvariable nur, wenn _overwrite_ ungleich 0 ist. Die Shell selbst bietet die Möglichkeit an, Umgebungsvariablen zu setzen. Und mit dem Werkzeug `env` lassen sich nicht nur Umgebungsvariablen zusätzlich setzen, sondern auch mit der Option „-i“ alle Umgebungsvariablen zuvor entfernen: ---- SHELL (path=session02,hostname=theon) ---- gcc -Wall -o printenv printenv.c env -i foo=bar hello=world ./printenv ----------------------------------------------- Aufgabe ======= Entwickeln Sie _environ.c_ als einfache Variante von _env_, die grundsätzlich nur die Umgebungsvariablen an das aufzurufende Kommando übermittelt, die auf der Kommandozeile angegeben sind (also analog zu _env_ mit impliziter Option „-i“). Die Argumente von _environ_ bestehen somit aus beliebig vielen Umgebungsvariablen (zu erkennen am „=“) und dem eigentlichen Kommando. Die Umgebungsvariablenliste können Sie mit _strlist_ aus der Vorlesungsbibliothek aufbauen: http://www.mathematik.uni-ulm.de/numerik/soft2/ss19/afblib/strlist.html Zu wünschen wäre eine Funktion _execvpe_, die sowohl die Umgebungsparameter entgegennimmt als auch _PATH_ unterstützt. Diese ist aber nicht Teil des POSIX-Standards (wird aber von Linux unterstützt). Verwenden Sie daher zunächst _execve_ und akzeptieren Sie, dass Sie die den vollständigen Pfad des Kommandos angeben müssen. :navigate: up -> doc:index next -> doc:session02/page02