-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.c
220 lines (193 loc) · 5.35 KB
/
main.c
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
// minish.c -- Jacques.Madelaine@info.unicaen.fr --
// un mini shell
#define _GNU_SOURCE
// GNU_SOURCE pour avoir getline qui permet de borner la lecture de ligne
// pas comme scanf
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <stdlib.h>
int nbMaxPid = 4;
int listePid[4];
int nbPid = 0;
//char *listeCmds[10];
char** listeCmds = NULL;
int indiceDebut = 0;
int indiceFin = 0;
int nbElements = 0;
int pidATuer;
typedef enum {
false,
true
}
bool;
// supprime les blancs qui traînent en queue et retourne la nelle longueur
int
nettoie(char *ligne) {
int lg = (int) strlen(ligne);
while (isspace(ligne[lg - 1]))
lg--;
ligne[lg] = '\0';
return (lg);
}
// Fait une tableau d'arguments avec les mots de la ligne
void
mkargs(char *args[], int MAXARGS, char *ligne) {
static char IFS[] = " \t";
int i = 0;
args[i++] = strtok(ligne, IFS);
while ((args[i++] = strtok(0, IFS)))
if (i > MAXARGS) {
fprintf(stderr, "plus de %d arguments, le reste n'est pas pris en compte\n", MAXARGS);
return;
}
}
#include <setjmp.h>
jmp_buf env; // le "jump buffer" du début de lecture
// Fonction attachée à SIGINT et SIGQUIT
void
nvligne(int sig) {
printf("Interruption %d\n", sig);
longjmp(env, 1); // pour forcer la reprise de la lecture
}
void
echanger(int *A, int *B) {
int AIDE = *A;
*A = *B;
*B = AIDE;
}
int
trouver_indice(int pid) {
for (int i = 0; i < nbPid; i++) {
if (listePid[i] == pid) {
return i;
}
}
return -1;
}
void
ajoutCmd(char *ligne) {
//printf("Ajout Commande : %s \n",ligne);
strcpy(listeCmds[nbElements], ligne);
nbElements++;
indiceFin++;
if (indiceDebut == sizeof(listeCmds)) {
indiceDebut = 0;
} else if (indiceFin == sizeof(listeCmds)) {
indiceFin = 0;
}
}
void
supprimerCmd() {
//printf("Supprimer Commande \n");
nbElements--;
indiceDebut++;
if (indiceDebut == sizeof(listeCmds)) {
indiceDebut = 0;
} else if (indiceFin == sizeof(listeCmds)) {
indiceFin = 0;
}
}
void
gestionAlarme(int numSig) {
printf("> La commande a dépassé 10 secondes de chargement. Arret du processus %d. \n", pidATuer);
kill(pidATuer, SIGKILL);
}
void
lancerCmd(char *args[], int size, char *ligne) {
//printf("Lancer commande : %s \n",ligne);
signal(SIGALRM, gestionAlarme);
int ppid;
switch (ppid = fork()) {
case -1:
perror("fork");
case 0:
switch (ppid = fork()) {
case -1:
perror("fork");
case 0:
signal(SIGQUIT, SIG_DFL);
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
// la commande en arrière plan ne doit pas lire l'entrée standard
int fd = open("/dev/null", O_RDONLY);
close(0);
dup(fd);
//sleep(7);
mkargs(args, size, ligne);
execvp(args[0], args);
perror(args[0]);
default:
pidATuer = ppid;
//printf("Alarm 10 sec %d \n", pidATuer);
alarm(10);
wait(NULL);
exit(10);
}
default:break;
}
}
void
hand(int sig) {
int pid = wait(NULL);
//printf("Handler %d %d \n", sig, pid);
if (pid != -1) {
int indice = trouver_indice(pid);
echanger(&listePid[indice], &listePid[nbPid] - 1);
nbPid--;
}
}
int
main() {
listeCmds = malloc(sizeof(char)*10);
for(int i = 0 ; i < 10 ; i++){
listeCmds[i] = malloc(sizeof(char)*250);
}
char *ps1 = getenv("PS1"); // Le prompt du Bourne (Again) SHell
char *ligne = 0;
size_t MAXLIGNE = 0;
char *args[256];
signal(SIGTERM, SIG_IGN);
if (ps1 == 0)
ps1 = "$ ";
setjmp(env); // C'est ici que l'on revient après une interruption
signal(SIGINT, nvligne);
signal(SIGQUIT, nvligne);
signal(SIGCHLD, hand);
while (1) {
int pid;
printf("%s", ps1);
if (getline(&ligne, &MAXLIGNE, stdin) == -1)
break; // C'est fini
if (nettoie(ligne) == 0) {
printf("Nombre de processus en cours d'execution : %d \n", nbPid);
continue; // juste une ligne vide, on continue
} else
printf("Nombre de processus en cours d'execution : %d \n", nbPid + 1); // +1 prise en compte de la commande prochaine
ajoutCmd(ligne);
if (nbPid < nbMaxPid && nbElements != 0) {
switch (pid = fork()) {
case -1:
perror("fork");
case 0: // Fils
if (nbElements != 0) {
lancerCmd(args, sizeof(args), listeCmds[indiceDebut]);
supprimerCmd();
}
default: // Père
listePid[nbPid] = pid;
nbPid++;
}
} else if(nbPid < nbMaxPid){
printf("Trop de processus en cours \n");
}
}
for (int i = 0; i < 10; i++)
free(listeCmds[i]);
free(listeCmds);
return 0;
}