Loading

NOM

       execve - Exécuter un programme

SYNOPSIS

       #include <unistd.h>

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

       execve()  exécute  le  programme  correspondant  au  fichier  filename.
       Celui‐ci doit être un exécutable binaire ou bien un  script  commençant
       par une ligne du type :

           #! interprteur [argument-optionnel]

       Pour des détails sur ce dernier cas, voir « Scripts » ci‐dessous.

       argv   est  un  tableau  de  chaînes  d’arguments  passées  au  nouveau
       programme. envp est un tableau de  chaînes,  ayant  par  convention  la
       forme   clé=valeur,   qui  sont  passées  au  nouveau  programme  comme
       environnement. argv ainsi que envp doivent se terminer par un  pointeur
       NULL.  Les arguments et l’environnement sont accessibles par le nouveau
       programme dans sa fonction principale, lorsqu’elle est définie comme :

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

       En cas de réussite, execve()  ne  revient  pas  à  l’appelant,  et  les
       segments  de texte, de données (« data » et « bss »), ainsi que la pile
       du processus appelant sont remplacés par ceux du programme chargé.

       Si l’on effectuait un ptrace(2) sur le programme  appelant,  un  signal
       SIGTRAP est envoyé après la réussite de execve().

       Si le bit Set-UID est positionné sur le fichier filename, si le système
       de fichiers sous‐jacent n’est pas monté nosuid (l’attribut MS_NOSUID de
       mount(2)),  et  si  le  programme  n’est  pas  tracé, l’UID effectif du
       processus appelant est modifié pour prendre celui  du  propriétaire  du
       fichier.  De  même,  lorsque  le  bit  Set‐GID  est  positionné, le GID
       effectif est modifié pour correspondre à celui du groupe du fichier.

       L’UID effectif du processus est copié dans le  Set-UID  sauvé ;  de  la
       même  manière,  le  GID  effectif  est copié dans le Set-GID sauvé. Ces
       copies ont lieu après toute modification d’ID effectif à cause des bits
       de permission Set-UID et Set-GID.

       Si  l’exécutable  est  un  fichier  binaire a.out lié dynamiquement, et
       contenant des appels aux bibliothèques partagées, le  linker  dynamique
       de  Linux  ld.so(8)  est  appelé avant l’exécution, afin de charger les
       bibliothèques partagées nécessaires en mémoire et d’effectuer l’édition
       des liens de l’exécutable.

       Si  l’exécutable  est  au  format ELF lié dynamiquement, l’interpréteur
       indiqué dans  le  segment  PT_INTERP  sera  invoqué  pour  charger  les
       bibliothèques    partagées.    Cet    interpréteur   est   généralement
       /lib/ld-linux.so.1 pour les fichiers binaires liés avec la  libc  Linux
       5, ou /lib/ld-linux.so.2 pour ceux liés avec la glibc 2.

       Tous  les  attributs  du processus sont préservés lors d’un execve(), à
       l’exception des suivants :

       *      Les  signaux  pour  lesquels  le  processus   avait   placé   un
              gestionnaire sont maintenant ignorés.

       *      L’éventuelle  pile  spécifique  pour les gestionnaire de signaux
              n’est pas conservée (sigaltstack(2)).

       *      Les projections en mémoire ne sont pas conservées (mmap(2)).

       *      Les  segments  de  mémoire  partagée  System  V  sont   détachés
              (shmat(2)).

       *      Les   objets   de   mémoire   partagée   POSIX   sont  supprimés
              (shm_open(3)).

       *      Les descripteurs de files de messages POSIX ouverts sont  fermés
              (mq_overview(7)).

       *      Les    sémaphores    nommés    POSIX    ouverts    sont   fermés
              (sem_overview(7)).

       *      Les   temporisations    POSIX    ne    sont    pas    conservées
              (timer_create(2)).

       *      Les flux de répertoires ouverts sont fermés (opendir(3)).

       *      Les  verrouillages  de  mémoire ne sont pas préservés (mlock(2),
              mlockall(2)).

       *      Les  gestionnaires  de  terminaison  ne   sont   pas   préservés
              (atexit(3), on_exit(3)).

       *      L’environnement de travail en virgule flottante est remis à zéro
              (voir fenv(3)).

       Les  attributs  de  processus  listés  ci‐dessus  sont  spécifiés  dans
       POSIX.1-2001.  Les  attributs de processus spécifiques à Linux suivants
       sont également réinitialisés lors d’un execve() :

       *  L’attribut PR_SET_DUMPABLE  de  prctl(2)  est  activé,  sauf  si  un
          programme setuid ou setgid est exécuté, auquel cas il est désactivé.

       *  L’attribut PR_SET_KEEPCAPS de prctl(2) est effacé.

       *  Le nom du processus, positionné par prctl(2) PR_SET_NAME (et affiché
          avec ps -o comm), est réinitialisé avec le nom du nouvel exécutable.

       *  Le signal de terminaison est réinitialisé à SIGCHLD (voir clone(2)).

       Notez également les points suivants :

       *  Tous  les  threads  autre  que  l’appelant  sont  détruits lors d’un
          execve(). Les mutex, les  variables  de  condition,  et  les  autres
          objets de pthreads sont détruits.

       *  L’équivalent  de  setlocale(LC_ALL, "C") est exécuté au démarrage du
          programme.

       *  POSIX.1-2001 indique que les actions pour  les  signaux  ignorés  ou
          placés  à  la valeur par défaut ne sont pas modifiées. Une exception
          est néanmoins spécifiée dans POSIX.1-2001 : si SIGCHLD  est  ignoré,
          l’implémentation peut laisser l’action inchangée ou la replacer à la
          valeur par défaut ; Linux ne modifie pas l’action.

       *  Toutes les opérations  d’E/S  asynchrones  en  cours  sont  annulées
          (aio_read(3), aio_write(3)).

       *  Pour   le   traitement   des  capacités  lors  d’un  execve(),  voir
          capabilities(7).

       *  Par défaut, les descripteurs de fichier restent ouverts  au  travers
          d’un  execve(). Les descripteurs marqués close‐on‐exec sont fermés ;
          voir la description de FD_CLOEXEC dans fcntl(2). (Si un  descripteur
          de  fichier  est fermé, cela cause la libération de tous les verrous
          d’enregistrement  obtenus  sur  le  fichier  correspondant  par   ce
          processus. Voir fcntl(2) pour les détails.) POSIX.1-2001 indique que
          si les descripteurs de fichiers 0, 1 et 2 devaient être fermés après
          un  execve()  réussi,  et  le processus devient privilégié en raison
          d’un bit set-user-ID ou set-group-ID  sur  le  fichier  exécuté,  le
          système  peut  ouvrir  un  fichier  non  spécifié pour chacun de ces
          descripteurs. En général, un programme portable, privilégié ou  pas,
          peut considérer que ces trois descripteurs resteront fermés après un
          execve().

   Scripts
       Un script est un fichier dont le bit d’exécution est activé et dont  la
       première ligne est de la forme :

           #! interprteur [argument-optionnel]

       L’interprteur  doit  être  un nom de fichier valide pour un exécutable
       qui n’est pas un script lui‐même. Si l’argument  filename  de  execve()
       indique  un  script,  l’interprteur  sera  appelé  avec  les arguments
       suivants :

           interprteur [argument-optionnel] filename arg...

       où arg... est la liste de mots pointée par l’argument argv de execve().

       Pour être portable, argument-optionnel doit soit être absent, soit être
       un seul mot (c’est‐à‐dire ne pas contenir d’espace) ;  voir  les  NOTES
       ci‐dessous.

   Limites sur la taille des paramètres et environnement
       La  plupart des implémentations Unix imposent des limites sur la taille
       totale des chaînes des paramètres des lignes de commande (argv)  et  de
       l’environnement (envp) qui peuvent être passées à un nouveau programme.
       POSIX.1  permet  à  une  implémentation  d’annoncer  cette  limite   en
       utilisant  la  constante  ARG_MAX  (soit  définie dans <limits.h>, soit
       disponible à l’exécution en utilisant l’appel sysconf(_SC_ARG_MAX)).

       Sur les noyaux Linux antérieurs à  2.6.23,  la  mémoire  utilisée  pour
       stocker  les  chaînes d’environnement et d’arguments était limitée à 32
       pages  (défini  par  la  constante  noyau   MAX_ARG_PAGES).   Sur   les
       architectures dont la taille de page est 4 Ko, cela donne un maximum de
       128 Ko.

       Sur les noyaux 2.6.23 et ultérieurs, la plupart des  architectures  ont
       une  limite  de  taille  dérivée  de  la  limite  de  ressources souple
       RLIMIT_STACK (voir getrlimit(2))  qui  est  en  vigueur  au  moment  de
       l’appel  à  execve()  (ce  n’est pas le cas pour les architectures sans
       unité de gestion  mémoire :  elles  conservent  la  limite  des  noyaux
       antérieurs  à  2.6.23). Ce changement permet aux programmes d’avoir une
       liste de paramètre ou un environnement beaucoup plus  grand.  Pour  ces
       architectures, la taille totale est limitées à 1/4 de la taille de pile
       permise (imposer une limite de 1/4  permet  d’assurer  que  le  nouveau
       programme  garde  de  l’espace  pour  la pile). Depuis Linux 2.6.25, le
       noyau place une limite inférieure de 32 pages à cette limite de taille,
       de  telle  sorte  que  même  si  RLIMIT_STACK  est  très faible, il est
       garantit aux applications qu’elles auront au moins autant de place pour
       les paramètres et leur environnement que ce qui était fournit par Linux
       2.6.23 et les précédents (cette garantie n’était pas présente dans  les
       noyaux 2.6.23 et 2.6.24). De plus, la limite par chaîne est de 32 pages
       (la constante noyau MAX_ARG_STRLEN), et le nombre  maximum  de  chaînes
       est de 0x7FFFFFFF.

VALEUR RENVOYÉE

       En  cas de réussite, execve() ne revient pas, en cas d’échec il renvoie
       -1 et errno contient le code d’erreur.

ERREURS

       E2BIG  Le nombre total d’octets dans l’environnement (envp) et la liste
              d’arguments (argv) est trop grand.

       EACCES La  permission de parcours est refusée pour un des composants du
              chemin filename ou du nom d’un  interpréteur  de  script.  (Voir
              aussi path_resolution(7).)

       EACCES Le  fichier  ou  l’interpréteur  de  script n’est pas un fichier
              régulier.

       EACCES L’autorisation d’exécution est refusée pour le  fichier,  ou  un
              interpréteur de script, ou un interpréteur ELF.

       EACCES Le système de fichiers est monté avec l’option noexec.

       EFAULT L’argument  filename  pointe  en  dehors de l’espace d’adressage
              accessible.

       EINVAL Un  exécutable  ELF  a  plusieurs  segments  PT_INTERP  (indique
              plusieurs interpréteurs).

       EIO    Une erreur d’entrée-sortie s’est produite.

       EISDIR L’interpréteur ELF cité est un répertoire.

       ELIBBAD
              L’interpréteur ELF mentionné n’est pas dans un format connu.

       ELOOP  Le  chemin  d’accès au fichier filename, ou à un interpréteur de
              script,  ou  à  un  interpréteur  ELF,  contient  une  référence
              circulaire (à travers un lien symbolique)

       EMFILE Le nombre maximal de fichiers ouverts par processus est atteint.

       ENAMETOOLONG
              La chaîne de caractères filename est trop longue.

       ENFILE La limite du nombre total de fichiers ouverts sur le  système  a
              été atteinte.

       ENOENT Le fichier filename ou un script ou un interpréteur ELF n’existe
              pas, ou une bibliothèque partagée nécessaire pour le fichier  ou
              l’interpréteur n’est pas disponible.

       ENOEXEC
              Le  fichier  exécutable  n’est  pas  dans  le bon format, ou est
              destiné à une autre architecture.

       ENOMEM Pas assez de mémoire pour le noyau.

       ENOTDIR
              Un élément du chemin d’accès au fichier filename, à un script ou
              à un interpréteur ELF, n’est pas un répertoire.

       EPERM  Le  système  de  fichiers est monté avec l’attribut nosuid et le
              fichier a un bit Set-UID ou Set-GID positionné.

       EPERM  Le processus est suivi avec ptrace(2), l’utilisateur  n’est  pas
              le  superutilisateur,  et le fichier a un bit Set-UID ou Set-GID
              positionné.

       ETXTBSY
              Un exécutable a été ouvert  en  écriture  par  un  ou  plusieurs
              processus.

CONFORMITÉ

       SVr4,   BSD 4.3,   POSIX.1-2001.   POSIX.1-2001  ne  documente  pas  le
       comportement avec « #! » mais est néanmoins compatible.

NOTES

       Les processus Set-UID  et  Set-GID  ne  peuvent  pas  être  suivis  par
       ptrace(2).

       Linux ignore les bits Set-UID et Set-GID sur les scripts.

       Le  résultat d’un montage de système de fichiers avec l’attribut nosuid
       peut varier suivant les versions du noyau Linux : certaines  refuseront
       l’exécution  des  fichiers  Set-UID et Set-GID lorsque cela donnerait à
       l’appelant des privilèges qu’il n’a pas (et renverront l’erreur EPERM),
       d’autres  ignoreront  simplement  les  bits  Set-UID  et  Set-GID  mais
       accepteront d’effectuer l’appel exec().

       La première ligne d’un shell script  exécutable  (#!)  a  une  longueur
       maximale de 127 caractères.

       La  sémantique  de  l’argument-optionnel  d’un script diffère selon les
       implémentations.  Sous  Linux,  la  chaîne   qui   suit   le   nom   de
       l’interprteur  est passée à l’interpréteur comme un seul mot, et cette
       chaîne peut  contenir  des  espaces.  Cependant,  le  comportement  est
       différent  sur d’autres systèmes. Certains utilisent la première espace
       comme fin de l’argument-optionnel. Sur  certains  systèmes,  un  script
       peut   avoir  plusieurs  arguments,  délimités  par  des  espaces  dans
       argument-optionnel.

       Sous Linux, argv peut être  NULL,  ce  qui  a  le  même  effet  que  de
       spécifier  que cet argument est un pointeur vers une liste contenant un
       pointeur NULL unique. Ne vous servez  pas  de  cette  caractéristique !
       Elle  n’est ni standard ni portable : sur la plupart des systèmes Unix,
       faire cela causera une erreur.

       POSIX.1-2001 indique  que  les  valeurs  renvoyées  par  sysconf(3)  ne
       doivent  pas  changer  pendant la vie d’un processus. Cependant, depuis
       Linux 2.6.23, si la limite de ressources RLIMIT_STACK change, alors  la
       valeur  renvoyée  par  _SC_ARG_MAX changera également, pour refléter le
       fait que la limite de l’espace qui reçoit les paramètres de la ligne de
       commande et les variables d’environnement a changé.

   Historique
       Avec Unix V6, la liste des arguments d’un appel exec() se terminait par
       0, alors que la liste des arguments de main se terminait par -1. Aussi,
       cette  liste  d’arguments  n’était  pas  utilisable directement dans un
       appel exec() supplémentaire. Depuis Unix V7, les deux terminateurs sont
       NULL.

EXEMPLE

       Le  programme  suivant  est  conçu  pour  être  exécuté  par  le second
       programme ci‐dessous. Il se contente d’afficher sa ligne  de  commande,
       un argument par ligne.

           /* myecho.c */

           #include <stdio.h>
           #include <stdlib.h>

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

               for (j = 0; j < argc; j++)
                   printf("argv[%d]: %s\n", j, argv[j]);

               exit(EXIT_SUCCESS);
           }

       Ce  programme  peut être utilisé pour exécuter le programme donné comme
       argument de ligne de commande :

           /* execve.c */

           #include <stdio.h>
           #include <stdlib.h>
           #include <unistd.h>

           int
           main(int argc, char *argv[])
           {
               char *newargv[] = { NULL, "hello", "world", NULL };
               char *newenviron[] = { NULL };

               if (argc != 2) {
                fprintf(stderr, "Usage: %s <file-to-exec>\n", argv[0]);
                exit(EXIT_FAILURE);
               }

               newargv[0] = argv[1];

               execve(argv[1], newargv, newenviron);
               perror("execve");   /* execve() ne retourne qu’en cas d’erreur */
               exit(EXIT_FAILURE);
           }

       On peut utiliser le second programme pour exécuter  le  premier  de  la
       façon suivante :

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

       On  peut  aussi utiliser ces programmes pour montrer l’utilisation d’un
       interpréteur de  scripts.  Pour  ce  faire,  on  crée  un  script  dont
       l’«interpréteur » est notre programme myecho :

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

       On peut alors utiliser notre programme pour exécuter le script :

           $ ./execve ./script.sh
           argv[0]: ./myecho
           argv[1]: script-arg
           argv[2]: ./script.sh
           argv[3]: hello
           argv[4]: world

VOIR AUSSI

       chmod(2),   fork(2),   ptrace(2),   execl(3),   fexecve(3),  getopt(3),
       credentials(7), environ(7), path_resolution(7), ld.so(8)

COLOPHON

       Cette page fait partie de  la  publication  3.23  du  projet  man-pages
       Linux.  Une description du projet et des instructions pour signaler des
       anomalies      peuvent      être       trouvées       à       l’adresse
       http://www.kernel.org/doc/man-pages/.

TRADUCTION

       Cette  page  de  manuel  a  été  traduite et mise à jour par Christophe
       Blaess <http://www.blaess.fr/christophe/> entre 1996 et 2003, puis  par
       Alain  Portal  <aportal AT univ-montp2 DOT fr> jusqu’en 2006, et mise à
       disposition sur http://manpagesfr.free.fr/.

       Les mises à jour et corrections de la version présente dans Debian sont
       directement gérées par Julien Cristau <jcristau@debian.org> et l’équipe
       francophone de traduction de Debian.

       Veuillez  signaler  toute  erreur   de   traduction   en   écrivant   à
       <debian-l10n-french@lists.debian.org> ou par un rapport de bogue sur le
       paquet manpages-fr.

       Vous pouvez toujours avoir accès à la version anglaise de  ce  document
       en utilisant la commande « man -L C <section> <page_de_man> ».