Fork TP
This commit is contained in:
commit
88521d3635
8 changed files with 400 additions and 0 deletions
21
Makefile
Normal file
21
Makefile
Normal file
|
@ -0,0 +1,21 @@
|
|||
CC=gcc
|
||||
CFLAGS=-Wall -g -Isrc/include
|
||||
|
||||
%: obj/lib.o obj/%.o
|
||||
$(CC) -o $@ $^
|
||||
|
||||
obj/%.o: src/%.c
|
||||
$(CC) $(CFLAGS) $^ -o $@ -c
|
||||
|
||||
obj/lib.o: src/include/mylib.c directories
|
||||
$(CC) $(CFLAGS) $< -o $@ -c
|
||||
|
||||
.PHONY: directories clean
|
||||
|
||||
directories:
|
||||
if ! [ -d "obj" ]; then \
|
||||
mkdir obj; \
|
||||
fi
|
||||
|
||||
clean:
|
||||
rm -rf obj
|
20
README.md
Normal file
20
README.md
Normal file
|
@ -0,0 +1,20 @@
|
|||
# tp-shell
|
||||
|
||||
## Compilation
|
||||
|
||||
Il suffit d’utiliser le make avec un de ces paramètres pour compiler le shell correspondant :
|
||||
|
||||
* shell1 (shell basique où juste une commande simple fonctionne)
|
||||
* shell2 (shell permettant d’entrer une commande avec des paramètres)
|
||||
* shell3 (shell permettant d’entrer deux commandes qui communiqueront tel un pipe)
|
||||
* shellOpt (shell permettant d’utiliser | au lieu de taper la commande en 2 fois)
|
||||
|
||||
À part le shell3, tous les autres utilisent une bibliothèque développée par nos soins, se trouvant dans `src/include` (ne sachant ce qu’est la convention).
|
||||
|
||||
## Bugs
|
||||
|
||||
Lors de nos tests, les shells 1 et 2 marchent bien sauf si l’utilisateur entre plusieurs espaces avant de faire entrer, sans taper aucune commande.
|
||||
|
||||
Le shell 3 fonctionne bien mais a le meme bug que les shell 1 et 2 lorsque l’utilisateur entre plusieurs espaces avant de faire entrer.
|
||||
|
||||
Le shellOpt marche bien avec des commandes ne contenant qu’un pipe, comme `ls | wc-l`. Si l’on rajoute un pipe, le programme le fera marcher avant de planter si on retape une commande. Le exit ne marche pas non plus après plusieurs pipes.
|
82
src/include/mylib.c
Normal file
82
src/include/mylib.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mylib.h"
|
||||
|
||||
/**
|
||||
* @brief Permet de récupérer la commande de l’utilisateur
|
||||
*
|
||||
* @param user_input entrée de l’utilisateur, contiendrat la commande à exécuter
|
||||
*/
|
||||
void get_input(char *user_input)
|
||||
{
|
||||
char *buffer = (char *) malloc(MAX_LENGTH);
|
||||
memset(user_input, 0, MAX_LENGTH);
|
||||
printf("\n> ");
|
||||
fgets(buffer, MAX_LENGTH, stdin);
|
||||
while (buffer[0] == '\n')
|
||||
{
|
||||
printf("\n> ");
|
||||
fgets(buffer, MAX_LENGTH, stdin);
|
||||
}
|
||||
strncpy(user_input, buffer, strlen(buffer)-1);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief récupère l’entrée de l’utilisateur et la découpe
|
||||
* selon le caractère passé en paramètre
|
||||
*
|
||||
* @param args Tableau de string qui sera modifié avec
|
||||
* les arguments de la commande
|
||||
* @param find Le caractère à utiliser pour découper la chaine
|
||||
*/
|
||||
void parse_char(char *args[], char find)
|
||||
{
|
||||
char *user_input = (char *) malloc(MAX_LENGTH);
|
||||
get_input(user_input);
|
||||
|
||||
char *token = strtok(user_input, &find);
|
||||
|
||||
int i = 0;
|
||||
while (token != NULL && i < MAX_LENGTH)
|
||||
{
|
||||
strcpy(args[i], token);
|
||||
i++;
|
||||
token = strtok(NULL, &find);
|
||||
}
|
||||
|
||||
// le dernier argument doit être NULL
|
||||
// car il est vide et provoque une erreur si non NULL
|
||||
free(args[i]);
|
||||
args[i] = NULL;
|
||||
|
||||
free(token);
|
||||
free(user_input);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief parse la chaine orig avec les espaces et la met dans le tableau dest
|
||||
* */
|
||||
void tok_space(char *orig, char* dest[])
|
||||
{
|
||||
char find = ' ';
|
||||
|
||||
char *token = strtok(orig, &find);
|
||||
|
||||
int i = 0;
|
||||
while (token != NULL && i < MAX_LENGTH)
|
||||
{
|
||||
strcpy(dest[i], token);
|
||||
i++;
|
||||
token = strtok(NULL, &find);
|
||||
}
|
||||
|
||||
// le dernier argument doit être NULL
|
||||
// car il est vide et provoque une erreur si non NULL
|
||||
free(dest[i]);
|
||||
dest[i] = NULL;
|
||||
|
||||
free(token);
|
||||
}
|
5
src/include/mylib.h
Normal file
5
src/include/mylib.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#define MAX_LENGTH 200
|
||||
|
||||
void get_input(char *user_input);
|
||||
void parse_char(char *args[], char find);
|
||||
void tok_space(char *args,char *commands[]);
|
30
src/shell1.c
Normal file
30
src/shell1.c
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "mylib.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
char *user_input = (char *) malloc(MAX_LENGTH);
|
||||
int result, pid;
|
||||
get_input(user_input);
|
||||
while (strcmp(user_input, "exit"))
|
||||
{
|
||||
pid = fork();
|
||||
|
||||
if (!pid)
|
||||
{
|
||||
execlp(user_input, user_input, NULL);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
wait(&result);
|
||||
|
||||
get_input(user_input);
|
||||
}
|
||||
free(user_input);
|
||||
return 0;
|
||||
}
|
42
src/shell2.c
Normal file
42
src/shell2.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "mylib.h"
|
||||
|
||||
int main()
|
||||
{
|
||||
int result, pid;
|
||||
char *args[MAX_LENGTH];
|
||||
for (int i = 0; i < MAX_LENGTH; i++)
|
||||
args[i] = (char *) calloc(MAX_LENGTH, sizeof(char));
|
||||
|
||||
parse_char(args, ' ');
|
||||
//get_args(args);
|
||||
while (strcmp(args[0], "exit"))
|
||||
{
|
||||
pid = fork();
|
||||
|
||||
if (!pid)
|
||||
{
|
||||
execvp(args[0], args);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
wait(&result);
|
||||
|
||||
for (int i = 0; i < MAX_LENGTH; i++)
|
||||
{
|
||||
free(args[i]);
|
||||
args[i] = (char *) calloc(MAX_LENGTH, sizeof(char));
|
||||
}
|
||||
//get_args(args);
|
||||
parse_char(args, ' ');
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_LENGTH; i++)
|
||||
free(args[i]);
|
||||
return 0;
|
||||
}
|
89
src/shell3.c
Normal file
89
src/shell3.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#define MAX_LENGTH 200
|
||||
|
||||
char** u_get_input(char* buffer, char* user_input, int i);
|
||||
|
||||
int main()
|
||||
{
|
||||
char *buffer = (char *) malloc(MAX_LENGTH);
|
||||
char *user_input1 = (char *) malloc(MAX_LENGTH);
|
||||
char *user_input2 = (char *) malloc(MAX_LENGTH);
|
||||
int pid1, pid2;
|
||||
int my_pipe[2];
|
||||
int t = pipe(my_pipe);
|
||||
if (t == -1)
|
||||
{
|
||||
printf("erreur à la création du pipe");
|
||||
return 1;
|
||||
}
|
||||
char **args1 = u_get_input(buffer, user_input1, 1);
|
||||
char **args2 = NULL;
|
||||
while (strcmp(user_input1, "exit") != 0)
|
||||
{
|
||||
args2 = u_get_input(buffer, user_input2, 2);
|
||||
pid1 = fork();
|
||||
|
||||
if (!pid1)
|
||||
{
|
||||
dup2(my_pipe[1], STDOUT_FILENO);
|
||||
close(my_pipe[0]);
|
||||
close(my_pipe[1]);
|
||||
execvp(user_input1, args1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
pid2 = fork();
|
||||
|
||||
if (!pid2)
|
||||
{
|
||||
dup2(my_pipe[0], STDIN_FILENO);
|
||||
close(my_pipe[1]);
|
||||
close(my_pipe[0]);
|
||||
execvp(user_input2, args2);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
close(my_pipe[0]);
|
||||
close(my_pipe[1]);
|
||||
waitpid(pid2, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
free(args1);
|
||||
free(args2);
|
||||
args1 = u_get_input(buffer, user_input1, 1);
|
||||
pipe(my_pipe);
|
||||
}
|
||||
free(args1);
|
||||
free(buffer);
|
||||
free(user_input1);
|
||||
free(user_input2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
char** u_get_input(char* buffer, char* user_input, int j)
|
||||
{
|
||||
printf("\ncommande%d> ", j);
|
||||
memset(buffer, 0, MAX_LENGTH);
|
||||
memset(user_input, 0, MAX_LENGTH);
|
||||
fgets(buffer, MAX_LENGTH, stdin);
|
||||
strncpy(user_input, buffer, strlen(buffer)-1);
|
||||
|
||||
char *token = strtok(user_input, " ");
|
||||
char **args = (char **) malloc(MAX_LENGTH);
|
||||
int i = 0;
|
||||
while (token != NULL && i < MAX_LENGTH)
|
||||
{
|
||||
args[i] = token;
|
||||
i++;
|
||||
token = strtok(NULL, " ");
|
||||
}
|
||||
return args;
|
||||
}
|
111
src/shellOpt.c
Normal file
111
src/shellOpt.c
Normal file
|
@ -0,0 +1,111 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "mylib.h"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
int pid;
|
||||
char *args[MAX_LENGTH];
|
||||
char *command[MAX_LENGTH];
|
||||
int my_pipe[2];
|
||||
if (pipe(my_pipe) == -1)
|
||||
{
|
||||
printf("erreur pipe");
|
||||
return 1;
|
||||
}
|
||||
for (int i = 0; i < MAX_LENGTH; i++)
|
||||
{
|
||||
args[i] = (char *) calloc(MAX_LENGTH, sizeof(char));
|
||||
command[i] = (char *) calloc(MAX_LENGTH, sizeof(char));
|
||||
}
|
||||
|
||||
parse_char(args, '|');
|
||||
/*
|
||||
int indx = 0;
|
||||
while (args[indx] != NULL)
|
||||
{
|
||||
tok_space(args[indx], command);
|
||||
int i = 0;
|
||||
while (command[i] != NULL)
|
||||
{
|
||||
printf("- %s - ", command[i]);
|
||||
i++;
|
||||
}
|
||||
for (int i = 0; i < MAX_LENGTH; i++)
|
||||
{
|
||||
free(command[i]);
|
||||
command[i] = (char *) calloc(MAX_LENGTH, sizeof(char));
|
||||
}
|
||||
if ( args[indx+1] == NULL )
|
||||
printf("CASSSSSESESESESISRETNRISUT.NR\n");
|
||||
indx++;
|
||||
}
|
||||
return 0;
|
||||
*/
|
||||
|
||||
|
||||
int index = 0;
|
||||
while (strcmp(args[0], "exit"))
|
||||
{
|
||||
if (args[1] != NULL)
|
||||
{
|
||||
while (args[index] != NULL)
|
||||
{
|
||||
pid = fork();
|
||||
if (!pid)
|
||||
{
|
||||
tok_space(args[index], command);
|
||||
if (args[index+1] == NULL)
|
||||
dup2(my_pipe[0], STDIN_FILENO);
|
||||
else if (index == 0)
|
||||
dup2(my_pipe[1], STDOUT_FILENO);
|
||||
/*else {
|
||||
dup2(my_pipe[0], STDIN_FILENO);
|
||||
dup2(my_pipe[1], STDOUT_FILENO);
|
||||
}*/
|
||||
|
||||
close(my_pipe[0]);
|
||||
close(my_pipe[1]);
|
||||
execvp(command[0], command);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (args[index + 1] == NULL)
|
||||
{
|
||||
close(my_pipe[1]);
|
||||
close(my_pipe[0]);
|
||||
//wait(&result);
|
||||
waitpid(pid, NULL, 0);
|
||||
}
|
||||
//waitpid(-1, NULL, 0);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_LENGTH; i++)
|
||||
{
|
||||
free(args[i]);
|
||||
free(command[i]);
|
||||
args[i] = (char *) calloc(MAX_LENGTH, sizeof(char));
|
||||
command[i] = (char *) calloc(MAX_LENGTH, sizeof(char));
|
||||
}
|
||||
parse_char(args, '|');
|
||||
pipe(my_pipe);
|
||||
index = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_LENGTH; i++)
|
||||
{
|
||||
free(command[i]);
|
||||
free(args[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in a new issue