Récupérer valeur sortie exec

Nb2 -  
paly2 Messages postés 254 Date d'inscription   Statut Membre Dernière intervention   -
Bonjour,

J'ai codé un script qui me permet d’exécuter plusieurs commandes à la suite.

Voici mon code :

# include <stdio.h>
# include <unistd.h>
# include <sys/wait.h>
# include <stdlib.h>
# include <string.h>
# include <assert.h>

int parse( char * arg)
{
int t;
t = fork();
if (t < 0)
return -1;
if (t == 0)
{
execl("/bin/sh", "sh", "-c", arg,NULL);
exit(1);
}
return t;
}

int main(int argc, char *argv[])
{
int t, tt, status, i;
i = 1;

for (i=1; i < argc; i++)
{
t = parse(argv[i]);
tt = wait(&status);
assert(tt == t);

}
return 0;
}


Voici un exemple d’exécution :

$ ./test 'echo foo' 'echo false'
foo
false
$


J'aimerais le modifier de sorte qu'il s’arrête si une commande est fausse, actuellement ce qu'il fait est :

$ ./test 'ech foo' 'echo false'
sh: 1: ech: not found
false
$


Je crois savoir que je dois faire un fork avec l'exec dans l'enfant et récupérer la valeur de sortie de l'exec mais je n'y arrive pas.

Est-ce que quelqu'un voudrait bien m'aider ?

1 réponse

paly2 Messages postés 254 Date d'inscription   Statut Membre Dernière intervention   25
 
Il faut que le processus fils écrive la valeur de retour dans une variable à une adresse connue.

# include <stdio.h> 
# include <unistd.h> 
# include <sys/wait.h> 
# include <stdlib.h> 
# include <string.h> 
# include <assert.h>

int parse(const char* arg, int* exec_return)
{
 int t;
 t = fork();
 if (t < 0)
  return -1;
 if (t == 0)
 {
  *exec_return = execl("/bin/sh", "sh", "-c", arg,NULL); // On modifie à l'adresse d'exec_return.
  exit(1);
 } 
 return t; 
} 
 
int main(int argc, char *argv[])
{
 int t, tt, status, i, exec_return;
 
 for (i = 1; i < argc; i++)
 {
  exec_return = 0;
  t = parse(argv[i], &exec_return); // S'il n'y a pas eu d'erreur, exec_return est resté à 0 (parce que execl n'a pas retourné), sinon, il est passé à -1.
  printf("exex_return: %d\n", exec_return);
  tt = wait(&status);
  assert(tt == t);
 }
 return 0; 
}


Note que execl ne retourne que s'il y a eu une erreur dans l'exécution de la fonction (pas celle du processus appelé).


Si c'est le retour du processus appelé que tu souhaites en fait récuperer (et visiblement c'est le cas), il faut utiliser la variable status que tu as la bonne idée de récupérer :
tt = wait(&status);
if(WIFEXITED(status))
        printf("Retour de la commande: %d\n", WEXITSTATUS(status));


La curiosité est une excellente qualité !
0
paly2 Messages postés 254 Date d'inscription   Statut Membre Dernière intervention   25
 
Note aussi la commande system() de stdlib.h, beaucoup plus simple à utiliser, mais j'ai souvenir d'avoir entendu que son utilisation causait une faille de sécurité. En tous cas, ton programme est largement simplifié par son utilisation :
# include <stdio.h>
# include <stdlib.h>

int main(int argc, char *argv[])
{
	int i, system_return;
	
	for (i = 1; i < argc; i++)
	{
		system_return = system(argv[i]);
       		// system_return est maintenant égal au retour de la commande argv[i] (donc 0 s'il n'y a eu aucune erreur), ou -1 s'il y a eu une erreur pendant l'exécution de system().
	}
	return 0; 
}


En fait, la fonction system() fait exactement ce que ton programme faisait: elle fork(), elle execve(), elle wait() puis elle retourne.
0
fiddy Messages postés 11069 Date d'inscription   Statut Contributeur Dernière intervention   1 846 > paly2 Messages postés 254 Date d'inscription   Statut Membre Dernière intervention  
 
Hello paly2,

Je confirme. C'est le mal absolu cette fonction system() :-).
Si c'est pour l'utiliser, autant programmer dans un autre langage car niveau performance elle n'est pas terrible.
Côté sécurité, le problème est que si l'utilisateur contrôle la variable dedans (accès direct sans contrôle, buffer overflow, etc.), il peut faire exécuter du code.
0
paly2 Messages postés 254 Date d'inscription   Statut Membre Dernière intervention   25
 
Ok merci pour les infos, c'était assez obscur pour moi cette faille de sécurité ^^
0