Bonsoir!
Je suis actuellement en train de finaliser mon projet de création d'un shell,
cependant j'ai quelques soucis avec le pipe, une amie m'a donnée le sien mais il ne peut effectuer qu'un pipe, donc pas de récursivité et j'ai du mal à comprendre comment il fonctionne.
(Si vous avez besoin d'une plus grande partie du code, je vous la fournirai).
Il fonctionne sur une main qui affiche le prompt, fait appel au parsing qui retourne un chiffre et affecte un tableau respP avec la commande à l'intérieur.
Dans le cas du chiffre 5 qui symbolise le pipe:
- On duplique l'écran, celui-ci est placé dans la première case vide du tableau des descripteurs
- On ferme l'écran.
- On ouvre un fichier .pipe qui contient selon mon amie les commandes suivantes dans le tableau respP dont le descripteur est fo
- On duplique ce fichier pipe car de nouveau il faut un espace dans la table de descripteur pour pouvoir traiter la deuxième instruction shell.
- On execute dans le processus fils
- Le processus père attend la fin normale du fils.
- On ferme l'écran chez le père car on ne l'utilise pas
- On ferme fo chez le père
- Puis duplique l'écran pour pouvoir afficher de nouveau la commande que l'utilisateur à inscrite.
- On refait un parsing qui nous retourne le délimiteur de la commande suivante (on essaye de mettre en place des appels récursifs).
- On crée une variable keybord.
- On duplique le clavier, son descripteur vient donc à la première case vide des descripteurs
- On ouvre un fichier .pipe qui contient selon mon amie les commandes suivantes dans le tableau respP dont le descripteur est fo
- On duplique ce fichier pipe car de nouveau il faut un espace dans la table de descripteur pour pouvoir traiter la deuxième instruction shell.
- On re duplique le programme
- Si on est chez le fils on exécute la commande,
- Si on est chez le père on attend la fin normale du fils
- On ferme le clavier
- on ferme fo
- on reduplique le clavier.
Je n'arrive pas à exécuter une troisème commande, j'ai l'impression que c'est par ce qu'on a prévu que deux commandes possibles dans un pipe.
J'ai aussi l'impression de me compliquer la vie. Quoiqu'il en soit, voici mon code, qui ne marche donc que dans le cas d'un tube unique. Pouvez-vous m'expliquer pourquoi il fonctionne, si j'ai bien compris comment il fonctionne et comment je pourrai faire pour l'améliorer?
Merci d'avance!
La commande Parsing, en annexe si vous en avez besoin.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 case 5: // SYMBOLE : | screen = dup(1); close(1); fo = open(".pipe", O_CREAT | O_TRUNC | O_RDWR, 0640); dup(fo); p2 = fork(); if(p2 == 0){ execvp(respP[0],respP); } else{ wait(&status); close(1); close(fo); dup(screen); //printf("Retour de l'écran \n"); //printf("w = %s \n", w); //printf("com[0] = %s \n",com[0]); i = 0; respP[i++] = strdup(mot); //com[i++] = 0; parsing(); int keyboard; keyboard = dup(0); close(0); fo = open(".pipe", O_RDWR, 0640); dup(fo); //printf("Avant le 2nd fork \n"); p2 = fork(); if(p2 == 0){ //printf("IN PID, w = %s \n",w); //printf("IN PID, com[0] : %s \n",com[0]); execvp(respP[0],respP); } else{ wait(&status); close(0); close(fo); dup(keyboard); i = 0; return 0; } //dup(screen); } //return 0; break; default: printf(""); } } return 0 ; }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 #include <unistd.h> #include <stdio.h> #include <sys/wait.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/types.h> #include <stdlib.h> #include <string.h> #include <errno.h> char *delimiteurs = ";&<>|"; char *respP[10]; // tableau contenant la commande a executer char *fout[10];// tableau qui affiche le resultat de l'istruction shell lue dans fin char *fin[10]; // la méthode commande va exécuter une instruction shell lue dans le tableau fin elements par element grace a parsing char *tube[10]; // tube qui assusre la communication entre deux processus char mot[50]; int symboleP, status, c; void parsing(){ int i=0; int cmot=0; while(1){ c = getchar(); if (c == '\n') {symboleP = 0;return;} else if (c == ';') {symboleP = 1;return;} else if (c == '&') {symboleP = 2;return;} else if (c == '<') {symboleP = 3;return;} else if (c == '>') {symboleP = 4;return;} else if (c == '|') {symboleP = 5;return;} else if (c == EOF) {symboleP = 7;return;} else if (c != ' ') { symboleP = 10; while(c != '\n' && !strchr(delimiteurs,c)){ i=0; while(c != 32 ){ // 32 correspond a un caractère dans la table ascii if((c != '\n') && !strchr(delimiteurs,c)){ mot[i]=c;i++; c=getchar(); } else {break;} } break; } while(c == ' ') { c=getchar(); } ungetc(c,stdin); // int ungetc(int c, FILE *stream) pushes the character c (an unsigned char) onto the specified stream so that the this is available for the next read operation.//stdin est un flux de l'entrée des données mot[i]=0;// A quoi ça sert? respP[cmot++]=strdup(mot); // fonction strdup renvoie l'adresse de la nouvelle chaine de caractère qui vient dêtre duppliquée ou sinon NULL --> alloue de l'espace necessaire pour stoker au mot fflush(stdout); if(c == '\n' || strchr(delimiteurs,c)) // { respP[cmot]=0; return; } } } }
Partager