diff --git a/.vscode/launch.json b/.vscode/launch.json index f798eb3..d957525 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -20,7 +20,10 @@ "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true - } + }, + // { + // "text": "-gdb-set follow-fork-mode child" + // } ], "preLaunchTask": "C/C++: gcc build active file", "miDebuggerPath": "/usr/bin/gdb" diff --git a/.vscode/settings.json b/.vscode/settings.json index 3f0c39b..eba2745 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,11 @@ { "files.associations": { + "*.html": "django-html", "signal.h": "c", "readcmd.h": "c", "stdlib.h": "c", "wait.h": "c", - "*.bak": "c" + "*.bak": "c", + "*.tcc": "c" } } \ No newline at end of file diff --git a/minishell b/minishell index 839a771..a6d1e3b 100755 Binary files a/minishell and b/minishell differ diff --git a/minishell.c b/minishell.c index de2ffe3..01e9e0b 100644 --- a/minishell.c +++ b/minishell.c @@ -27,6 +27,9 @@ char initcd[256], currentcd[256]; int file_in, file_out; +int pipes[256][2]; +int sous_fils[256]; + void handler_sigchld(int sig_num) { do @@ -34,7 +37,7 @@ void handler_sigchld(int sig_num) pid_fils = waitpid(-1, &wait_code, WNOHANG | WUNTRACED | WCONTINUED); if ((pid_fils == -1) && (errno != ECHILD)) { // wait fail ? - fprintf(stderr, "ERROR: waiting for child failed, (%d) %s\n", errno, strerror(errno)); + fprintf(stderr, "ERROR: waiting for %d failed, (%d) %s\n", pid_fils, errno, strerror(errno)); exit(errno); } @@ -127,6 +130,7 @@ int main(int argc, char *argv[]) cmd = readcmd(); prompting = 0; + // TODO: créer fonction "builtin" ? if (cmd == NULL) { // EOF break; @@ -222,33 +226,129 @@ int main(int argc, char *argv[]) continue; } - pid_fils = fork(); - if (pid_fils == -1) + // compter le nombre de commandes séparées par des pipes + int nb_pipe = -1; + char ***cursor = cmd->seq; + while (*cursor) + { + cursor++; + nb_pipe++; + } + if (nb_pipe < 0) + { // counting failed ? + fprintf(stderr, "ERROR: counting pipes failed"); + exit(1); + } + + if ((pid_fils = fork()) == -1) { // fork fail ? fprintf(stderr, "ERROR: forking failed, (%d) %s\n", errno, strerror(errno)); exit(errno); } - if (pid_fils == 0) { // instructions du fils action.sa_handler = SIG_IGN; - sigaction(SIGTSTP, &action, NULL); // on igonre SIGTSTP + sigaction(SIGTSTP, &action, NULL); // on ignore SIGTSTP sigaction(SIGINT, &action, NULL); // on ignore SIGINT if (cmd->in) - { + { // "<" file_in = open(cmd->in, O_RDONLY); dup2(file_in, 0); } if (cmd->out) - { + { // ">" file_out = open(cmd->out, O_CREAT | O_TRUNC | O_WRONLY, 0640); dup2(file_out, 1); } - execvp(cmd->seq[0][0], cmd->seq[0]); - fprintf(stderr, "ERROR: execvp failed, (%d) %s\n", errno, strerror(errno)); - exit(errno); // si execvp échoue on exit avec une erreur + if (nb_pipe > 0) + { // "|" présent(s) dans la commande + for (int i = 0; i <= nb_pipe; i++) + { // on crée itérativement nb_pipe fils et pipes + if (pipe(pipes[i]) < 0) + { // pipe failed ? + fprintf(stderr, "ERROR: pipe error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + if ((sous_fils[i] = fork()) < 0) + { // fork failed ? + fprintf(stderr, "ERROR: fork error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + else if (sous_fils[i] == 0) + { // instructions des sous-fils + + if (i == 0) + { // premier sous-fils + close(pipes[0][0]); + } + else if (dup2(pipes[i - 1][0], STDIN_FILENO) == -1) + { // dup2 fail + fprintf(stderr, "ERROR: dup2 error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + if (i == nb_pipe) + { // dernier sous-fils + close(pipes[i][1]); + } + else if (dup2(pipes[i][1], STDOUT_FILENO) == -1) + { // dup2 fail + fprintf(stderr, "ERROR: dup2 error, (%d) %s\n", errno, strerror(errno)); + exit(errno); + } + + for (int j = 0; j <= i; j++) + { // on ferme les pipes non nécéssaires + if (j <= i - 2) + { // on ferme tous les pipes que l'on utilise pas + close(pipes[j][0]); + close(pipes[j][1]); + } + else if (j == i - 1) + { // on ferme l'écriture du pipe précédent + close(pipes[j][1]); + } + else if (j == i) + { // on ferme la lecture de son propre pipe + close(pipes[j][0]); + } + } + + execvp(cmd->seq[i][0], cmd->seq[i]); + fprintf(stderr, "ERROR: execvp failed, (%d) %s\n", errno, strerror(errno)); + exit(errno); // si execvp échoue on exit avec une erreur + } + } + for (int i = 0; i <= nb_pipe; i++) + { // on ferme tous les pipes pour le fils + close(pipes[i][0]); + close(pipes[i][1]); + } + for (int i = 0; i <= nb_pipe; i++) + { // on attend chaque sous-fils + pid_t id = waitpid(sous_fils[i], &wait_code, 0); + + if (id == -1) + { // wait fail ? + fprintf(stderr, "ERROR: waiting for %d failed, (%d) %s\n", wait_code, errno, strerror(errno)); + exit(errno); + } + if (wait_code) + { // execvp fail ? + fprintf(stderr, "ERROR: child failed, (%d) %s\n", wait_code, strerror(wait_code)); + } + } + exit(0); // on termine le fils + } + else + { // pas de piping + execvp(cmd->seq[0][0], cmd->seq[0]); + fprintf(stderr, "ERROR: execvp failed, (%d) %s\n", errno, strerror(errno)); + exit(errno); // si execvp échoue on exit avec une erreur + } } else { // instructions du père @@ -266,7 +366,6 @@ int main(int argc, char *argv[]) fprintf(stderr, "ERROR: waiting for %d failed, (%d) %s\n", wait_code, errno, strerror(errno)); exit(errno); } - if (wait_code) { // execvp fail ? fprintf(stderr, "ERROR: child failed, (%d) %s\n", wait_code, strerror(wait_code)); diff --git a/test.sh b/test.sh index 9359f1a..60e6a64 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,2 @@ sleep 4 -printf "\n\n --- bonjour --- \n\n" \ No newline at end of file +printf "\n\n --- bonjour --- \n\n"