Bonsoir,
Je dois réaliser un programme C qui permet d’exécuter des commandes Linux dans le terminal, pour l'instant tout fonctionne avec ceci :
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 #ifndef _LIGNE_COMMANDE_V2_H #define _LIGNE_COMMANDE_V2_H /** CODE DU PROF * Cette fonction lit sur l'entrée standard une ligne de texte, * la découpe selon les espaces, et retourne un tableau de char* * du type attendu par execv et execvp. * * Si la fin de fichier est rencontrée, cette fonction retourne NULL. * * Voir aussi les fonctions fin_de_fichier et ligne_vide. */ char** lis_ligne(); /** * Cette fonction prend en paramètre le tableau de char* retourné par lis_ligne * et retourne vrai si et seulement si lis_ligne a rencontré la fin de fichier. * (c.à.d. si ligne est NULL) */ int fin_de_fichier(char** ligne); /** * Cette fonction prend en paramètre le tableau de char* retourné par lis_ligne * et retourne vrai si la ligne lue était vide. * Pré-condition: on n'est pas en fin de fichier, ligne != NULL */ int ligne_vide(char** ligne); /** * Cette procédure coupe une chaîne de caractères en deux à l'endroit du signe * égal, de sorte qu'après son exécutuion: * - la chaîne passée en paramètre ne contient plus que sa partie gauche, * - le pointeur retourné pointe vers la partie droite. * * Si la chaîne passée en paramètre ne contient pas le signe égal, la chaîne * n'est pas modifiée, et la fonction retourne NULL. */ char* separe_egal(char* str); #endif
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
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 /** *CODE DU PROF * Pour la documentation, voir ligne_commande_v2.h . */ #include "ligne_commande.h" #include <stdio.h> #include <string.h> #include <unistd.h> #define LBUF 1024 #define LLIGNE 256 static char buf[LBUF]; static char* ligne[LLIGNE]; char** lis_ligne() { int i = 0; int s; do { s = read(0, buf+i, 1); i += s; } while (i < LBUF-1 && s > 0 && buf[i-1] != '\n'); if (s < 0) perror("erreur de lecture dans lis_ligne"); if (i == 0) return NULL; // découpage char* tok; buf[i] = '\0'; i = 0; ligne[0] = strtok_r(buf, " \t\n\r", &tok); while (ligne[i] && i < LLIGNE-1) { i += 1; ligne[i] = strtok_r(NULL, " \t\n\r", &tok); } if (i == LLIGNE-2) ligne[LLIGNE-1] = NULL; return ligne; } int fin_de_fichier(char** ligne) { return ligne == NULL; } int ligne_vide(char** ligne) { return ligne[0] == NULL; } char* separe_egal(char* str) { char* p = str; while (*p) { if (*p == '=') { *p = '\0'; return p+1; } p++; } return NULL; } /* fonction de test */ /* int main (int argc, char** argv) { char** l = lis_ligne(); int i; for(i = 0; l && l[i]; i++) { printf("<%s>\n", l[i]); } printf("c'est tout %d %d\n", fin_de_fichier(l), l && ligne_vide(l)); // TODO teste aussi separe_egal return 0; } */
Mais je dois maintenant modifier ce programme afin de permettre à l'utilisateur d’exécuter en tâche de fond la commande si elle commence par tf (tâche de fond) et que le shell affiche directement l'invité de saisie pour une autre commande. Lorsqu'elle est terminée on doit afficher un message indiquant que le processus est fini avec son pid.
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 #include "ligne_commande.h" #include <stdio.h> #include <stdlib.h> #include <string.h> /* strcmp */ #include <unistd.h> /* fork,getpid */ #include <stdio.h> /* perror */ #include <sys/types.h> /* getpid */ #include <sys/wait.h> /* wait */ int commandes_internes(char** cmd); int main(int argc, char** argv) { setenv("INVITE", "\n> ", 1); pid_t pid; int state; while (1) { printf("%s ", getenv("INVITE")); fflush(stdout); char** commande = lis_ligne(); if (fin_de_fichier(commande)) { printf("Fin du programme\n"); return 0; } else { if (!ligne_vide(commande)) { if (!commandes_internes(commande)) { pid = fork(); if (pid == 0) { if (execvp(commande[0], commande) == -1) perror("Commande incorrecte\n"); exit(0); } else { wait(&state); } } } } } } int commandes_internes(char** cmd) { if (!strcmp(cmd[0], "exit")) { printf("Fin du programme\n"); exit(0); } if (!strcmp(cmd[0], "export")) { if (cmd[1]) { char* value = separe_egal(cmd[1]); if (setenv(cmd[1], value, 1) == -1) { perror("Erreur"); } } return 1; } return 0; }
Sans tf, on attendra la fin pour afficher l'invité de saisie, ça j'ai réussi
Tout cela sans créer de zombie
Avez-vous des idées car je galère pour la partie tâche de fond
Merci par avance
Partager