From 88521d3635f9ecc27d1913c5a6d3c5b281fc647f Mon Sep 17 00:00:00 2001 From: rick Date: Tue, 16 Feb 2021 16:12:37 +0100 Subject: [PATCH] Fork TP --- Makefile | 21 +++++++++ README.md | 20 ++++++++ src/include/mylib.c | 82 ++++++++++++++++++++++++++++++++ src/include/mylib.h | 5 ++ src/shell1.c | 30 ++++++++++++ src/shell2.c | 42 +++++++++++++++++ src/shell3.c | 89 +++++++++++++++++++++++++++++++++++ src/shellOpt.c | 111 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 400 insertions(+) create mode 100644 Makefile create mode 100644 README.md create mode 100644 src/include/mylib.c create mode 100644 src/include/mylib.h create mode 100644 src/shell1.c create mode 100644 src/shell2.c create mode 100644 src/shell3.c create mode 100644 src/shellOpt.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a081e13 --- /dev/null +++ b/Makefile @@ -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 diff --git a/README.md b/README.md new file mode 100644 index 0000000..bf3f108 --- /dev/null +++ b/README.md @@ -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. diff --git a/src/include/mylib.c b/src/include/mylib.c new file mode 100644 index 0000000..0cf1235 --- /dev/null +++ b/src/include/mylib.c @@ -0,0 +1,82 @@ +#include +#include +#include + +#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); +} diff --git a/src/include/mylib.h b/src/include/mylib.h new file mode 100644 index 0000000..1d11177 --- /dev/null +++ b/src/include/mylib.h @@ -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[]); diff --git a/src/shell1.c b/src/shell1.c new file mode 100644 index 0000000..51cc4f4 --- /dev/null +++ b/src/shell1.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include + +#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; +} diff --git a/src/shell2.c b/src/shell2.c new file mode 100644 index 0000000..859acb6 --- /dev/null +++ b/src/shell2.c @@ -0,0 +1,42 @@ +#include +#include +#include +#include +#include + +#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; +} diff --git a/src/shell3.c b/src/shell3.c new file mode 100644 index 0000000..2a2d03c --- /dev/null +++ b/src/shell3.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include + +#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; +} diff --git a/src/shellOpt.c b/src/shellOpt.c new file mode 100644 index 0000000..16af409 --- /dev/null +++ b/src/shellOpt.c @@ -0,0 +1,111 @@ +#include +#include +#include +#include +#include + +#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; +} +