execvp(3)

Fonction de la bibliothèque C

Remplace le programme du processus courant par une commande cherchée dans le PATH, avec ses arguments dans un tableau terminé par NULL.

Synopsis
#include <unistd.h>
int execvp(const char *file, char *const argv[]);

Description

execvp charge un autre programme dans le processus courant et l'exécute depuis son début. Le code, les données et la pile de l'ancien programme sont remplacés ; le PID ne change pas, et les descripteurs de fichiers ouverts restent ouverts (sauf ceux marqués « close-on-exec »). On l'appelle presque toujours dans un enfant créé par fork, pour que le parent continue.

Le p du nom signifie que file est cherché dans les dossiers de la variable PATH, comme le fait le shell, sauf s'il contient un / : il est alors pris tel quel. Le v signifie que les arguments arrivent dans un tableau (vector). Par convention, argv[0] est le nom de la commande, et la dernière case doit valoir NULL. Le nouveau programme reçoit l'environnement du processus courant.

Les autres membres de la famille changent une lettre : execlp prend les arguments un par un, terminés par (char *) NULL, execv ne cherche pas dans le PATH, et l'appel système sous-jacent, execve, veut un chemin exact et un environnement explicite.

Valeur de retour

En cas de succès, execvp ne revient jamais : il n'y a plus de programme appelant pour recevoir une valeur. S'il revient, c'est un échec, la valeur est -1 et errno en donne la cause : ENOENT quand la commande est introuvable, EACCES quand le fichier n'est pas exécutable.

Pièges

  • Tout ce qui suit execvp ne s'exécute qu'en cas d'échec. Écris-y un perror puis un exit, sinon l'enfant continue le code du parent.

  • Un tableau d'arguments sans NULL final fait lire execvp au-delà du tableau.

  • Le tampon de printf est perdu dans le remplacement. Vide-le avec fflush(stdout) avant l'appel.

  • No such file or directory peut aussi venir d'un script dont l'interpréteur n'existe pas, comme un #!/bin/sh suivi d'un retour chariot Windows.

Exemple

lance.c
#include <stdio.h>#include <unistd.h>
int main(int argc, char **argv){    if (argc < 2) {        fprintf(stderr, "usage : %s commande [arguments]\n", argv[0]);        return 2;    }    execvp(argv[1], argv + 1);    perror(argv[1]);    return 127;}
Terminal
$ gcc -Wall -Wextra lance.c -o lance$ ./lance echo bonjour depuis execvpbonjour depuis execvp$ ./lance commande-inconnuecommande-inconnue: No such file or directory$ echo $?127

argv + 1 est déjà un tableau au bon format : il commence au nom de la commande et se termine par le NULL que la norme C garantit en argv[argc].

C

pipe_chain

Écris pipe_chain, qui lance chaque commande d'une liste dans son propre enfant avec execvp et branche la sortie de chacune sur l'entrée de la suivante.

Ouvrir l'exercice

À toi d'écrire le code.