• # Quelques problèmes

    Posté par . En réponse au message introduire redirection dans un minishell. Évalué à 2.

    • au moment de l'exec par le fils, il "exec" le shell lui même (argv[0]) au lieu du programme entré.

    • exit(0) après le wait ne devrait pas être là.

    • les modifications sur stdin/stdout doivent se faire dans le fils (avant l'exec). Là tu le fais dans le père/shell et, en plus, après le fork, ce qui n'a aucune incidence sur le fils, ce n'est certainement pas ce que tu veux..

    • surcharger l'argv du main pour construire ton argv pour l'execv est, en plus d'être carrément dégueulasse et illisible, dangereux car rien ne t'indique qu'il est bien dimensionné. Construis en un autre à l'aide de malloc! (btw fgets ne devrait pas non plus être utilisé, je l'avais déja dit à ton collègue ou à toi.

    • conseil: continue de découper ton code en fonctions, par exemple en faire une pour le fork+exec+modification stdou/stdin serait déja pas mal, voire une autre pour construire l'argv ou encore pour "parser" la ligne d'entrée

    • conseil: utilise "strace -o /tmp/trace -f -t ./shell" afin de savoir quels syscalls sont effectués par ton programme. L'argument "-f" est important, il demande de tracer aussi les fils. Avec le code posté, tu obtiens qq chose du genre (j'ai retirés les lignes non pertinentes).

    ...
    3062 20:19:53 write(1, "? ", 2) = 2
    3062 20:19:53 read(0, "ls > /tmp/ls\n", 1024) = 13
    3062 20:19:57 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f956ce1e9d0) = 3063
    3062 20:19:57 write(1, "attendre l'enfant (3063)\n", 25 <unfinished ...>
    3063 20:19:57 execve("./a.out", ["./a.out"], [/* 56 vars */] <unfinished ...>
    3062 20:19:57 <... write resumed> ) = 25
    3062 20:19:57 wait4(-1, <unfinished ...>
    ...
    3063 20:19:57 <... execve resumed> ) = 0
    3063 20:19:57 write(1, "? ", 2) = 2
    3063 20:19:57 read(0, "\n", 1024) = 1
    3063 20:20:02 write(1, "? ", 2) = 2
    3063 20:20:02 read(0, "", 1024) = 0
    3063 20:20:04 write(1, "Bye\n", 4) = 4
    3063 20:20:04 exit_group(0) = ?
    3063 20:20:04 +++ exited with 0 +++
    3062 20:20:04 <... wait4 resumed> [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 3063
    3062 20:20:04 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=3063, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
    3062 20:20:04 write(1, "enfant (3063) fini\n", 19) = 19
    3062 20:20:04 exit_group(0) = ?
    3062 20:20:04 +++ exited with 0 +++
    

    La première ligne indique le pid. On voit bien que le wait fonctionne bien, mais que le fils (pid 3063) fait une lecture sur stdin (fd=0) et ne quitte qu'au moment on on entre CTRL+D (read=0 => EOF). Note que le fork est en fait le "clone", c'est la primitive noyau ("syscall") que la fonction fork de la libc utilise. Tu peux aussi utiliser ltrace (avec un L pour librairies), qui normalement te donne les noms de fonctions appellées, mais en règle générale, c'est beaucoup plus lent et verbeux, et il faut avoir les infos de débuggages.