feat: piping working
This commit is contained in:
parent
89ed491533
commit
61a5953a0f
5
.vscode/launch.json
vendored
5
.vscode/launch.json
vendored
|
@ -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"
|
||||
|
|
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
@ -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"
|
||||
}
|
||||
}
|
121
minishell.c
121
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));
|
||||
|
|
Loading…
Reference in a new issue