Willemers Informatik-Ecke
Zunächst soll der Rahmen betrachtet werden, in dem sich ein Programm bewegt.
Das ist zwar eigentlich nicht Bestandteil der Systemaufrufe, gibt aber
einen ersten Einblick, in welcher Umgebung sich ein Programm unter UNIX
bewegt.
Ein C-Programm wird immer mit der Funktion main() gestartet. Diese hat drei
Parameter, von denen normalerweise nur die ersten beiden verwendet werden. Der
dritte Parameter hält das Environment, das aber auch per getenv() gelesen
werden kann.
int main(int argc, char **argv)
{
return 0;
}
|
Aufrufparameter
argv enthält die Aufrufparameter
In der Variablen argc steht nach dem Start, wieviele Parameter bei Aufruf des
Programmes übergeben wurden. Dieser Wert ist immer mindestens 1, da auch der
Name, unter dem das Programm aufgerufen wurde, als Parameter zählt.
Die Variable argv ist ein Array von Strings. Die Programmparameter werden von
der Shell an den Leerzeichen zerlegt und dann einzeln an das Programm
weitergereicht.
Beispiel:
Wenn im aktuellen Verzeichnis die Dateien lolita}, lolli
und lonzo stehen, sind
die Parameter von main folgendermaßen belegt:
In argc steht eine 5. Im Element argv[0] findet sich der Name des Programmes
inklusive Pfad, in diesem Fall >>./tudochwas<<.
Da tudochwas aus dem aktuellen Verzeichnis gestartet wurde und kein
Pfad angegeben wurde, bemühte die Shell die Variable PATH. Darin fand sie dann
den Pfad . und setzte ihn vor den Programmnamen.
argv[1] enthält die Option -f und argv[2] den
Parameter >>huhu<<. Die weiteren Elemente von argv hängen von den Dateien
im aktuellen Verzeichnis ab. Da auf lol* sowohl lolita als auch lolli passen,
füllen diese die nächsten zwei argv-Elemente.
argv[0] ist der Programmname
Da das erste Element in argv immer der Name ist, mit dem das Programm
aufgerufen wurde, kann man dem Programm Optionen durch den Befehlsnamen
mitgeben. So entspricht beispielsweise der Befehl uncompress dem
Aufruf compress -d. Das erreicht man, indem ein Link namens
uncompress auf compress erzeugt wird. So ein Link kostet
unter UNIX nur einen Verzeichniseintrag mehr. Das Programm prüft beim
Start, ob es unter dem Namen uncompress aufgerufen wurde und fügt
in diesem Fall die Option -d hinzu.
Wildcards überlässt man der Shell
An den letzten Argumenten erkennt man, dass der Stern unter UNIX von der Shell
aufgelöst wird. Dadurch ist erreicht, dass alle Programme von Haus aus die
Wildcards der Shell gleichermaßen interpretieren, da sie sie selbst nicht
auswerten.
Das folgende kleine Programm zeigt die Aufrufparameter an:
int main(int argc, char **argv)
{
int i;
for (i=0; i<argc; i++) {
puts(argv[i]);
}
return 0;
}
|
Rückgabewert ist der Fehlercode
Auch der Rückgabewert der Funktion main ist von Bedeutung. Gibt sie 0 zurück,
wird dies als fehlerfreier Ablauf gewertet. Alle anderen Werte sin Hinweis
auf einen Fehler bei der Ausführung.
Gerade wenn Fehler entstehen, ist es oft sehr umständlich, wieder zur Funktion
main zurückzukehren. Hier hilft die Funktion exit. Sie beendet das
Programm und der Übergabeparameter wird als Rückgabewert an den Aufrufer des
Programms weitergereicht.
Zugriff auf die Umgebungsvariablen
Der bislang nicht erwähnte dritte Parameter von main zeigt auf die
Umgebungsvariablenliste. Schon wie bei argv handelt es sich um ein Array von
Zeichenketten. Da hier allerdings die Anzahl in einem separaten Parameter
mitgeteilt wird, muss es eine andere Form der Endekennung geben. Der Zeiger
nach dem letzten Eintrag hat den Wert 0. Mit dem Beispielprogramm wird die
komplette Liste der Umgebungsvariablen angezeigt.
main(int argc, char **argv, char **env)
{
int i;
char *str;
if (env) {
i=0;
while(str = env[i]) {
puts(env[i++]);
}
}
}
|
Wer das Programm startet bekommt eine riesige Liste, von der hier nur ein
kurzer Ausschnitt angezeigt wird:
WINDOWMANAGER=/usr/X11R6/bin/kde
HOME=/home/arnold
TERM=xterm
XNLSPATH=/usr/X11R6/lib/X11/nls
no_proxy=localhost
|
Umgebung über globale Variable
Dieser dritte Parameter ist relativ unbekannt, da
man auch über die externe, globale Variable environ auf die
gleiche Liste zugreifen kann. Aus diesem Grund hat sich POSIX auch auf die
Variante mit zwei Parametern festgelegt.
Einzelne Umgebungsvariablen setzen und lesen
Im Normalfall wird man allerdings mit der kompletten Liste wenig anfangen
wollen, sondern man braucht eine spezielle Umgebungsvariable. Dazu verwendet
man die Funktion getenv().
#include <stdlib.h>
char *getenv(const char *name);
int putenv(const char *string);
|
Sofern die als Parameter angegebene Variable gesetzt ist, bekommt man einen
Zeiger auf den Wert zurückgeliefert. Da dieser Zeiger beim nächsten Aufruf
von getenv verloren gehen kann, sollte man das Ergebnis in eine lokale
Variable kopieren, wenn man ihn später noch braucht.
Es ist auch möglich, vom Programm aus Umgebungsvariablen zu setzen. Dazu
dient die Funktion setenv(). Als Parameter erwartet sie einen
vollständigen Variableneintrag der Form var=wert. Beispiel: