Recuperar valor de salida de exec
Nb2
-
paly2 Mensajes publicados 261 Estado Miembro -
paly2 Mensajes publicados 261 Estado Miembro -
Bonjour,
J'ai codé un script qui me permet d’exécuter plusieurs commandes à la suite.
Voici mon code :
Voici un exemple d’exécution :
J'aimerais le modifier de sorte qu'il s’arrête si une commande est fausse, actuellement ce qu'il fait est :
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 ?
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 respuesta
-
El proceso hijo debe escribir el valor de retorno en una variable en una dirección conocida.
# include <stdio.h> # include <unistd.h> # include <sys> # 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); // Se modifica la dirección de 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); // Si no hubo error, exec_return se quedó en 0 (porque execl no retornó), de lo contrario, pasa a -1. printf("exex_return: %d\n", exec_return); tt = wait(&status); assert(tt == t); } return 0; } </assert.h></string.h></stdlib.h></sys></unistd.h></stdio.h>
Nota que execl solo retorna si hubo un error en la ejecución de la función (no en la del proceso invocado).
Si lo que quieres en realidad es obtener el retorno del proceso invocado (y a juzgar por todo parece ser así), hay que usar la variable status que ya tienes la buena idea de obtener:tt = wait(&status); if(WIFEXITED(status)) printf("Retour de la commande: %d\n", WEXITSTATUS(status));
La curiosité est une excellente qualité !-
Toma en cuenta también la orden system() de stdlib.h, mucho más simple de usar, pero tengo el recuerdo de haber oído que su uso genera una falla de seguridad. En todo caso, tu programa queda ampliamente simplificado con su uso:
# 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 ahora es igual al retorno de la orden argv[i] (por lo tanto 0 si no hubo error), o -1 si hubo un error durante la ejecución de system(). } return 0; }
De hecho, la función system() hace exactamente lo que hacía tu programa: hace fork(), hace execve(), wait() y luego devuelve.- Hola paly2,
Confirmo. Es el mal absoluto esa función system() :-).
Si es para usarla, mejor programar en otro lenguaje porque en rendimiento no es terrible.
En cuanto a seguridad, el problema es que si el usuario controla la variable ahí (acceso directo sin control, desbordamiento de búfer, etc.), puede hacer que se ejecute código.
-
-