EXECVE(2)

BEZEICHNUNG
execve - Programm ausführen

ÜBERSICHT
#include <unistd.h>

int execve(const char *Pfadname, char *const argv[],
           char *const envp[]);

BESCHREIBUNG
execve() führt das Programm aus, auf das sich Pfadname bezieht. Dies führt dazu, dass das Programm, das derzeit vom aufrufenden Prozess ausgeführt wird, durch ein neues Programm, mit einem frisch initialisierten Stack, Heap und (initialisierten und uninitialisierten) Datensegmenten ersetzt wird.

Pfadname muss entweder ein binäres ausführbares Programm oder ein Skript sein, das mit einer Zeile der folgenden Form beginnt:

    #!Interpreter [Optionale-Arg]

Einzelheiten zu letzterem Fall finden Sie in »Interpreter-Skripte« weiter unten.

argv ist ein Feld von Zeigern auf Zeichenketten, die an das neue Programm als dessen Befehlszeilenargumente übergeben werden. Per Konvention sollte die erste dieser Zeichenketten (d.h. argv[0]) den Dateinnamen, der zu der ausgeführten Datei gehört, enthalten. Das Feld argv muss durch einen NULL-Zeiger beendet werden. (Daher wird in dem neuen Programm argv[argc] NULL sein.)

envp ist ein Feld von Zeigern auf Zeichenketten, gewöhnlich von der Form Schlüssel=Wert, die an die Umgebung des neuen Programms übergeben werden. Das Feld envp muss durch einen NULL-Zeiger beendet werden.

Auf den Argumentzeiger und die Umgebung kann von der Main-Funktion des neuen Programms zugegriffen werden, wenn sie wie folgt definiert ist:

    int main(int argc, char *argv[], char *envp[])

Beachten Sie allerdings, dass die Verwendung eines dritten Arguments bei der Funktion main nicht in POSIX.1 spezifiziert ist; laut POSIX.1 sollte auf die Umgebung über die externe Variable environ(7) zugegriffen werden.

execve() kehrt bei Erfolg nicht zurück und Text, initialisierte Daten, uninitialisierte Daten (bss) und Stack des aufrufenden Prozesses werden entsprechend des Inhalts des neu geladenen Programms überschrieben.

Falls das aktuelle Programm mit ptrace verfolgt wird, wird nach einem erfolgreichen execve() ein Signal SIGTRAP an es gesandt.

Falls bei der Programmdatei, auf die sich Pfadname bezieht, das Bit set-user-ID gesetzt ist, dann wird die effektive Benutzerkennung des aufrufenden Programms zu der des Eigentümers der Programmdatei geändert. Ähnlich wird die effektive Gruppenkennung des aufrufenden Prozesses auf die Gruppe der Programmdatei gesetzt, wenn das Bit set-group-ID auf der Programmdatei gesetzt ist.

Die vorgenannten Umwandlungen der effektiven Kennungen werden nicht durchgeführt (d.h. die Bits set-user-ID und set-group-ID werden ignoriert), falls eine der folgenden Aussagen wahr ist:

*   Das Attribut no_new_privs wird für den aufrufenden Thread gesetzt (siehe prctl(2)).

*   Das unterliegende Dateisystem ist nosuid eingehängt (der Schalter MS_NOSUID für mount(2)).

*   Der aufrufende Prozess wird mit ptrace verfolgt.

Die Capabilities der Programmdatei (siehe capabilities(7)) werden auch ignoriert, wenn eine der obigen Bedingungen zutrifft.

Die effektive Benutzerkennung des Prozesses wird in die gespeicherte set-user-ID kopiert. Ähnlich wird die effektive Gruppenkennung in die gespeicherte set-group-ID kopiert. Dieses Kopieren findet nach allen effektiven ID-Änderungen statt, die aufgrund der Modusbits set-user-ID und set-group-ID erfolgen.

Die reale UID und reale GID des Prozesses sowie die zusätzlichen Gruppenkennungen ändern sich beim Aufruf von execve() nicht.

Falls das Programm eine dynamisch gelinkte Programmdatei im a.out-Format ist, die dynamische Bibliotheken-Stubs enthält, dann wird der dynamische Linker ld.so(8) von Linux am Anfang der Ausführung aufgerufen, um die benötigten Laufzeitobjekte in den Speicher zu bringen und das Programm mit ihnen zu verlinken.

Falls das Programm ein dynamisch gelinktes ELF-Programm ist, wird der in dem Segment PT_INTERP benannte Interpreter zum Laden der gemeinsamen Objekte verwandt. Dieser Interpreter ist typischerweise /lib/ld-linux.so.2 für Programme, die mit der Glibc gelinkt sind (siehe ld-linux.so(8)).

  Auswirkung auf Prozessattribute
Alle außer den nachfolgend aufgeführten Prozessattributen werden durch ein execve() erhalten:

*   Die Zuordnung aller gefangenen Signale wird auf die Vorgabe zurückgesetzt (signal(7)).

*   Alle alternativen Signal-Stacks werden nicht erhalten (sigaltstack(2)).

*   Speicher-Mappings werden nicht erhalten (mmap(2)).

*   Gemeinsam benutzte Speichersegmente vom Typ »System V« werden abgetrennt (shmat(2)).

*   Mappings gemeinsamer Speicherbereiche gemäß POSIX werden aufgehoben (shm_open(3)).

*   Offene POSIX-Nachrichtenwarteschlangendeskriptoren werden geschlossen (mq_overview(7)).

*   Alle offenen benannten POSIX-Semaphoren werden geschlossen (sem_overview(7)).

*   POSIX-Timer werden nicht erhalten (timer_create(2)).

*   Alle offenen Verzeichnis-Streams werden geschlossen (opendir(3)).

*   Speichersperren werden nicht erhalten (mlock(2), mlockall(2)).

*   Exit-Handler werden nicht erhalten (atexit(3), on_exit(3)).

*   Die Gleitkomma-Umgebung wird auf den Standardwert zurückgesetzt (siehe fenv(3)).

Die Prozessattribute in der vorstehenden Liste sind alle in POSIX.1 spezifiziert. Die folgenden Linux-spezifischen Prozessattribute werden auch während eines execve() nicht erhalten:

*   Das Attribut »dumpable« ist auf den Wert 1 gesetzt, außer ein set-user-ID-Programm, ein set-group-ID-Programm oder ein Programm mit Capabilitys wird ausgeführt, in welchem Fall der »dumpable«-Schalter stattdessen unter den in PR_SET_DUMPABLE in prctl(2) beschriebenen Umständen auf den Wert in /proc/sys/fs/suid_dumpable zurückgesetzt werden kann. Beachten Sie, dass Änderungen am Attribut »dumpable« zu Änderungen der Eigentümerschaft von Dateien im Verzeichnis /proc/[PID] des Prozesses auf root:root führen können, wie dies in proc(5) beschrieben ist.

*   Der prctl(2)-Schalter PR_SET_KEEPCAPS wird auf 0 gesetzt.

*   (Seit Linux 2.4.36 / 2.6.23) Falls ein set-user-ID- oder set-group-ID-Programm ausgeführt wird, dann wird das durch den Schalter prctl(2) PR_SET_PDEATHSIG gesetzte Todessignal des Elternprozesses auf 0 gesetzt.

*   Der Prozessname, wie er von prctl(2) PR_SET_NAME gesetzt (und durch ps -o comm angezeigt) wird, wird auf den Namen des ausführbaren Programms zurückgesetzt.

*   Der SECBIT_KEEP_CAPS Schalter securebits wird auf 0 gesetzt. Siehe capabilities(7).

*   Das Terminierungssignal wird auf SIGCHLD zurückgesetzt (siehe clone(2)).

*   Die Dateideskriptortabelle wird getrennt, der Effekt des Schalters CLONE_FILES von clone(2) wird rückgängig gemacht.

Beachten Sie die folgenden weiteren Punkte:

*   Alle Threads außer dem aufrufenden werden während eines execve() zerstört. Mutexe, Bedingungsvariablen und andere Pthread-Objekte werden nicht erhalten.

*   Das Äquivalent von setlocale(LC_ALL, "C") wird beim Programmstart ausgeführt.

*   POSIX.1 legt fest, dass Zuordnungen aller ignorierten oder auf die Vorgabewerte gesetzten Signale unverändert bleiben. POSIX.1 legt eine Ausnahme fest: Falls SIGCHLD ignoriert wird, dann darf eine Implementierung die Zuordnung unverändert lassen oder sie auf die Vorgabe zurücksetzen; Linux macht Ersteres.

*   Alle ausstehenden asynchronen E/A-Operationen werden abgebrochen (aio_read(3), aio_write(3)).

*   Für den Umgang mit Capabilities während execve(), siehe capabilities(7).

*   Standardmäßig bleiben Dateideskriptoren über ein execve() hinweg offen. Dateideskriptoren, die mit close-on-exec markiert sind, werden geschlossen; siehe die Beschreibung von FD_CLOEXEC in fcntl(2). (Falls ein Dateideskriptor geschlossen wird, führt dies zur Freigabe aller von der unterliegenden Datei durch den Prozess erhaltenen Datensatzsperren. Siehe fcntl(2) für Details.) Laut POSIX.1 darf das System eine nicht festgelegte Datei für jeden der Dateideskriptoren 0, 1 und 2 öffnen, falls diese andernfalls nach einem erfolgreichen execve() geschlossen und der Prozess aufgrund der Modus-Bits set-user-ID oder set-group-ID Privilegien erhalten würde. Als allgemeines Prinzip darf kein portables Programm, egal ob privilegiert oder nicht, annehmen, dass diese drei Dateideskriptoren über ein execve() geschlossen bleiben.

  Interpreter-Skripte
Ein Interpreter-Skript ist eine Textdatei, die über Ausführrechte verfügt und dessen erste Zeile die folgende Form annimmt:

    #!Interpreter [Optionale-Arg]

Der Interpreter muss ein gültiger Pfadname zu einer ausführbaren Datei sein.

Falls das Argument Pfadname von execve() ein Interpreterskript festlegt, dann wird interpreter mit den folgenden Argumenten aufgerufen.

    Interpreter [Optionale-Arg] Pfadname Arg …

Hierbei ist Pfadname der Pfadname der Datei, die als erstes Argument von execve() festgelegt ist, und arg… die Serie von Wörtern, auf die vom Argument argv von execve() gezeigt wird, beginnen mit argv[1]. Beachten Sie, dass es keine Möglichkeit gibt, argv[0], der dem Aufruf execve() übergeben wurde, zu erhalten.

Für den portablen Einsatz sollte Optionale-Arg entweder abwesend oder als einzelnes Wort angegeben werden (d.h. es sollte keine Leerraumzeichen enthalten); siehe ANMERKUNGEN unten.

Seit Linux 2.6.28 erlaubt es der Kernel, dass der Interpreter eines Skripts selbst wieder ein Skript ist. Diese Erlaubnis ist rekursiv bis zu einer Rekursionstiefe von 4, so dass der Interpreter ein Skript sein darf, das von einem Skript interpretiert wird und so weiter.

  Begrenzungen der Größe der Argumente und der Umgebung
Die meisten UNIX-Implementierungen verhängen eine Begrenzung für die Gesamtgröße der Zeichenketten der Befehlszeilenargumente (argv) und der Umgebung (envp), die an ein neues Programm übergeben werden darf. POSIX.1 erlaubt es einer Implementierung, diese Begrenzung mit der Konstante ARG_MAX bekanntzugeben (entweder definiert in <limits.h> oder zur Laufzeit mit dem Aufruf sysconf(_SC_ARG_MAX) verfügbar).

Vor Kernel 2.6.23 unter Linux war der Speicher, der zum Ablegen der Umgebungs- und Argumentzeichenketten verwandt wurde, auf 32 Seiten begrenzt (definiert durch die Kernelkonstante MAX_ARG_PAGES). Auf Architekturen mit einer 4-kB-Seitengröße führt dies zu einer Maximalgröße von 128 kB.

Auf den meisten Architekturen wird unter Kernel 2.6.23 und neuer eine Größenbegrenzung, die von der Ressourcenbegrenzung RLIMIT_STACK (siehe getrlimit(2)) abgeleitet ist, die zum Zeitpunkt des Aufrufs execve() in Kraft war, unterstützt. (Architekturen ohne Speicherverwaltungseinheit sind die Ausnahme: bei ihnen bleibt die Begrenzung, die vor dem Kernel 2.6.23 in Kraft war.) Diese Änderung erlaubt es Programmen, eine viel größere Argumenten- und/oder Umgebungsliste zu haben. Für diese Architekturen ist die Gesamtgröße auf 1/4 der erlaubten Stack-Größe begrenzt. (Die Erzwingung der 1/4-Begrenzung stellt sicher, dass neue Programme immer über Stack-Bereich verfügen.) Zusätzlich wird die Gesamtgröße auf 3/4 des Wertes der Kernelkonstanten _STK_LIM (8 MiB) begrenzt. Seit Linux 2.6.25 stellt der Kernel auch eine Untergrenze von 32 Seiten dieser Begrenzung bereit, so dass selbst wenn RLIMIT_STACK sehr gering ist, Anwendungen garantiert über mindestens so viel Argument- und Umgebungsbereich verfügen, wie dies unter Linux 2.6.22 und älter der Fall war. (Diese Garantie wurde nicht unter Linux 2.6.23 und 2.6.24 erfüllt.) Zusätzlich ist die Begrenzung pro Zeichenkette 32 Seiten (der Kernelkonstanten MAX_ARG_STRLEN) und die maximale Anzahl von Zeichenketten ist 0x7FFFFFFF.

RÜCKGABEWERT
Im Erfolgsfall kehrt execve() nicht zurück, im Fehlerfall wird -1 zurückgeliefert und errno gesetzt, um den Fehler anzuzeigen.

FEHLER

E2BIG
    Die Gesamtanzahl von Bytes in der Umgebungs- (envp) und der Argumentenliste (argv) ist zu groß.

EACCES
    Für einen Teil des Pfadpräfixes von Pfadname oder dem Namen des Skript-Interpreters wird die Suchberechtigung verweigert. (Siehe auch path_resolution(7).)

EACCES
    Die Datei oder der Skriptinterpreter ist keine reguläre Datei.

EACCES
    Für die Datei oder ein Skript oder ELF-Interpreter wird die Ausführberechtigung verweigert.

EACCES
    Das Dateisystem ist nicht noexec eingehängt.

EAGAIN (seit Linux 3.1)
    Nach Änderung der realen UID mittels einer der Aufrufe set*uid() war – und ist immer noch – der Aufrufende über seine Ressourcenbegrenzung RLIMIT_NPROC (siehe setrlimit(2)). Für eine detailliertere Erläuterung dieses Fehlers siehe ANMERKUNGEN.

EFAULT
    Pfadname oder einer der Zeiger in den Vektoren argv oder envp zeigt aus dem für Sie zugänglichen Adressraum heraus.

EINVAL
    Ein ELF-Programm hat mehr als ein PT_INTERP-Segment (d.h. versuchte mehr als einen Interpreter anzugeben).

EIO Es ist ein E/A-Fehler (engl. I/O) aufgetreten.

EISDIR
    Ein ELF-Interpreter war ein Verzeichnis.

ELIBBAD
    Ein ELF-Interpreter war in einem unbekannten Format.

ELOOP
    Beim Auflösen von Pfadname oder dem Namen eines Skripts oder ELF-Interpreters wurden zu viele symbolische Links ermittelt.

ELOOP
    Während der rekursiven Skript-Interpretation (siehe »Interpreter-Skripte« oben) wurde die maximale Rekursionsbegrenzung erreicht. Vor Linux 3.8 wurde in diesem Fall der Fehler ENOEXEC erstellt.

EMFILE
    Die Beschränkung pro Prozess der Anzahl offener Datei-Deskriptoren wurde erreicht.

ENAMETOOLONG
    Pfadname ist zu lang.

ENFILE
    Die systemweite Beschränkung für die Gesamtzahl offener Dateien wurde erreicht.

ENOENT
    Die Datei Pfadname oder ein Skript oder ELF-Interpreter existiert nicht.

ENOEXEC
    Ein Programm ist nicht in einem erkennbaren Format, ist für die falsche Architektur oder hat einen anderen Formatfehler, wodurch es nicht ausgeführt werden kann.

ENOMEM
    Es war nicht genügend Kernelspeicher verfügbar.

ENOTDIR
    Ein Teil des Pfadpräfixes von Pfadname oder ein Skript oder ELF-Interpreter ist kein Verzeichnis.

EPERM
    Das Dateisystem ist nosuid eingehängt, der Benutzer ist nicht der Superuser und die Datei hat das Bit set-user-ID oder set-group-ID gesetzt.

EPERM
    Der Prozess wird verfolgt, der Benutzer ist nicht der Superuser und die Datei hat das Bit set-user-ID oder set-group-ID gesetzt.

EPERM
    Eine »Capability-unfähige« Anwendung würde nicht die ganze Menge der vom ausführbaren Programm gewährten erlaubten Capabilities erhalten. Siehe capabilities(7).

ETXTBSY
    Das angegebene Programm war für einen oder mehrere Prozesse zum Schreiben offen.

KONFORM ZU
POSIX.1-2001, POSIX.1-2008, SVr4, 4.3BSD. POSIX dokumentiert das #!-Verhalten nicht, es existiert aber (mit einigen Variationen) auf anderen UNIX-Systemen.

ANMERKUNGEN
Manchmal wird execve() (und die in exec(3) beschriebenen dazugehörigen Funktionen) als »Ausführung eines neuen Prozesses« (oder ähnlich) beschrieben. Dies ist eine hochgradig irreführende Beschreibung: es gibt keinen neuen Prozess, viele Attribute des aufrufenden Prozesses bleiben unverändert (insbesondere seine PID). execve() arrangiert lediglich, dass ein existierender Prozess (der aufrufende Prozess) ein neues Programm ausführt.

Set-user-ID- und Set-group-ID-Prozesse können nicht mit ptrace(2) verfolgt werden.

Das Ergebnis des Einhängens eines Dateisystems mit nosuid unterscheidet sich abhängig von der Linux-Kernelversion. Unter einigen wird die Ausführung von Programmen mit set-user-ID und set-group-ID verweigert, wenn das dem Benutzer Rechte geben würde, die er nicht bereits hatte (und EPERM zurückliefern). Unter anderen werden die Bits set-user-ID und set-group-ID ignoriert und exec() erfolgreich ausgeführt.

Unter Linux können argv und envp als NULL festgelegt werden. In beiden Fällen hat dies den gleichen Effekt wie die Festlegung des Arguments auf einen Zeiger auf eine Liste, die als einziges Element den NULL-Zeiger enthält. Nutzen Sie diese nicht standardisierte und nicht portable Misfunktionalität nicht aus! Unter vielen UNIX-Systemen führt die Festlegung von argv als NULL zu einem Fehler (EFAULT). Einige andere UNIX-Systeme behandeln den Fall envp==NULL wie Linux.

POSIX.1 besagt, dass die von sysconf(3) zurückgelieferten Werte über die Lebensdauer eines Prozesses unveränderlich sein sollen. Seit 2.6.23 wird der von _SC_ARG_MAX berichtete Wert sich allerdings auch ändern, wenn die Ressourcenbegrenzung RLIMIT_STACK sich ändert, um die Tatsache zu berücksichtigen, dass die Begrenzung des Platzes zum Halten der Befehlszeilenargumente und der Umgebungsvariablen sich geändert hat.

In den meisten Fällen, in denen execve() fehlschlägt, kehrt die Steuerung zu dem ursprünglichen Abbild zurück und der Aufrufende von execve() kann mit dem Fehler umgehen. In (seltenen) Fällen kann (typischerweise durch Ressourcenerschöpfung verursacht) der Fehlschlag den Punkt ohne Rückkehr passieren: das ursprüngliche Abbild wurde bereits entfernt aber das neue Abbild konnte nicht komplett gebaut werden. In diesen Fällen beendet der Kernel den Prozess mit einem Signal SIGSEGV (SIGKILL bis Linux 3.17).

  Interpreter-Skripte
Der Kernel legt eine maximal Länge für Text, der den Zeichen »#!« am Anfang eines Skriptes folgt, auf. Zeichen hinter dieser Begrenzung werden ignoriert. Vor Linux 5.1 war die Begrenzung 127 Zeichen, seit Linux 5.1 ist die Begrenzung 255 Zeichen.

Die Semantik des Arguments Optionale-Args eines Interpreterskriptes unterscheidet sich zwischen Implementierungen. Unter Linux wird die gesamte Zeichenkette, die Interpreter folgt, als einziges Argument an den Interpreter übergeben und diese Zeichenkette kann Leerzeichen enthalten. Das Verhalten unterscheidet sich aber auf einigen anderen Systemen. Einige Systeme verwenden das erste Leerzeichen, um Optionale-Args zu beenden. Auf einigen Systemen kann ein Interpreterskript mehrere Argumente haben und Leerzeichen in Optionale-Args werden zum Begrenzen der Argumente verwandt.

Linux (wie die meisten anderen modernen UNIX-Systeme) ignoriert die Bits set-user-ID und set-group-ID bei Skripten.

  execve() und EAGAIN
Eine detailliertere Beschreibung des Fehlers EAGAIN, der (seit Linux 3.1) beim Aufruf von execve() auftreten kann, ist wie folgt:

Der Fehler EAGAIN kann auftreten, wenn ein vorhergehender Aufruf von setuid(2), setreuid(2) oder setresuid(2) dazu führte, dass die reale Benutzerkennung des Prozesses geändert wurde und diese Änderung dazu führte, dass der Prozess seine Ressourcenbeschränkung RLIMIT_NPROC überschritt (d.h. die Anzahl der zu der neuen realen UID gehörenden Prozesse überschreitet die Ressourcenbeschränkung). Von Linux 2.6.0 bis 3.0 führte dies dazu, dass der Aufruf set*uid() fehlschlug. (Vor 2.6 wurde die Ressourcenbeschränkung bei Prozessen, die ihre Benutzerkennungen änderten, nicht durchgesetzt.)

Seit Linux 3.1 schlägt in dem gerade beschriebenen Szenario der Aufruf set*uid() nicht mehr fehl, da dies zu oft zu Sicherheitslöchern führte, bei denen fehlerhafte Anwendungen nicht den Rückgabewert prüften und annahmen, dass – falls der Aufrufende Root-Rechte hatte – der Aufruf immer erfolgreich sein würde. Stattdessen ändert der Aufruf set*uid() jetzt erfolgreich die reale UID, aber der Kernel setzt einen internen Schalter namens PF_NPROC_EXCEEDED, um zu vermerken, dass die Ressourcenbeschränkung RLIMIT_NPROC überschritten wurde. Falls der Schalter PF_NPROC_EXCEEDED gesetzt ist und die Ressourcenbeschränkung zum Zeitpunkt eines folgenden execve()-Aufrufs immer noch überschritten ist, dann schlägt dieser Aufruf mit dem Fehler EAGAIN fehl. Diese Kernellogik stellt sicher, dass die Ressourcenbeschränkung RLIMIT_NPROC für den häufigen Ablauf bei privilegierten Daemons – also fork(2) + set*uid() + execve() – weiterhin durchgesetzt wird.

Falls die Ressourcenbegrenzung zum Zeitpunkt des Aufrufs execve() noch nicht überschritten wurde (da andere zu dieser realen UID gehörende Prozesse sich zwischen dem Aufruf von set*uid() und dem Aufruf von execve() beendeten), dann gelingt der Aufruf und der Kernel bereinigt den Prozessschalter PF_NPROC_EXCEEDED. Der Schalter wird auch auf 0 gesetzt, falls ein folgender Aufruf von fork(2) durch diesen Prozess gelingt.

  Geschichtliches
Unter UNIX V6 wurde die Argumentenliste von einem exec()-Aufruf durch 0 beendet, während die Argumentenliste von main durch -1 beendet wurde. Daher war diese Argumentenliste nicht für weitere exec()-Aufrufe direkt verwendbar. Seit UNIX V7 sind beide NULL.

BEISPIELE
Das folgende Programm ist dafür gedacht, vom zweiten folgenden Programm ausgeführt zu werden. Es gibt nur seine Befehlszeile (eine pro Zeile) wieder aus.

    /* myecho.c */
    #include <stdio.h>
    #include <stdlib.h>
    int
    main(int argc, char *argv[])
    {
        for (int j = 0; j < argc; j++)
            printf("argv[%d]: %s\n", j, argv[j]);
        exit(EXIT_SUCCESS);
    }

Dieses Programm kann zur Ausführung des in seinem Befehlszeilenargument benannten Programms verwandt werden:

    /* execve.c */
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    int
    main(int argc, char *argv[])
    {
        char *newargv[] = { NULL, "Hallo", "Welt", NULL };
        char *newenviron[] = { NULL };
        if (argc != 2) {
    	printf(stderr, "Aufruf: %s <auszuführende-Datei>\n", argv[0]);
    	exit(EXIT_FAILURE);
        }
        newargv[0] = argv[1];
        execve(argv[1], newargv, newenviron);
        perror("execve");   /* execve() kehrt nur im Fehlerfall zurück */
        exit(EXIT_FAILURE);
    }

Wir können das zweite Programm verwenden, um das erste wie folgt aufzurufen:

    $ cc myecho.c -o myecho
    $ cc execve.c -o execve
    $ ./execve ./myecho
    argv[0]: ./myecho
    argv[1]: Hallo
    argv[2]: Welt

Wir können diese Programme auch zur Demonstration der Verwendung eines Skript-Interpreters verwenden. Dafür erstellen wir ein Skript, dessen »Interpreter« unser myecho-Programm ist.

    $ cat > script
    #!./myecho script-arg
    ^D
    $ chmod +x script

Wir können dann unser Programm verwenden, um das Skript auszuführen:

    $ ./execve ./script
    argv[0]: ./myecho
    argv[1]: script-arg
    argv[2]: ./script
    argv[3]: Hallo
    argv[4]: Welt

SIEHE AUCH
chmod(2), execveat(2), fork(2), get_robust_list(2), ptrace(2), exec(3), fexecve(3), getauxval(3), getopt(3), system(3), capabilities(7), credentials(7), environ(7), path_resolution(7), ld.so(8)

KOLOPHON
Diese Seite ist Teil der Veröffentlichung 5.13 des Projekts Linux-man-pages. Eine Beschreibung des Projekts, Informationen, wie Fehler gemeldet werden können sowie die aktuelle Version dieser Seite finden sich unter https://www.kernel.org/doc/man-pages/.

ÜBERSETZUNG
Die deutsche Übersetzung dieser Handbuchseite wurde von Helge Kreutzmann <debian@helgefjell.de> erstellt.

Diese Übersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 (https://www.gnu.org/licenses/gpl-3.0.html) oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen.

Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Übersetzer (debian-l10n-german@lists.debian.org).