This commit is contained in:
rick 2021-02-16 16:12:37 +01:00
commit 88521d3635
Signed by: Rick
GPG key ID: 2B593F087240EE99
8 changed files with 400 additions and 0 deletions

21
Makefile Normal file
View 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
View file

@ -0,0 +1,20 @@
# tp-shell
## Compilation
Il suffit dutiliser 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 dentrer une commande avec des paramètres)
* shell3 (shell permettant dentrer deux commandes qui communiqueront tel un pipe)
* shellOpt (shell permettant dutiliser | 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 quest la convention).
## Bugs
Lors de nos tests, les shells 1 et 2 marchent bien sauf si lutilisateur 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 lutilisateur entre plusieurs espaces avant de faire entrer.
Le shellOpt marche bien avec des commandes ne contenant quun pipe, comme `ls | wc-l`. Si lon 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
View 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 lutilisateur
*
* @param user_input entrée de lutilisateur, 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 lentrée de lutilisateur 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
View 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
View 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
View 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
View 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
View 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;
}