From faf692aea663ee638674dcc6bb46dcb0f73f82b4 Mon Sep 17 00:00:00 2001
From: rick <rick@gnous.eu>
Date: Mon, 22 Feb 2021 15:48:35 +0100
Subject: [PATCH] Gestion du ctrl d & proto pour ctrl c, close #3

---
 src/boitoutil/essential_shell.c | 12 ++++++
 src/boitoutil/essential_shell.h |  5 +++
 src/boitoutil/parser.c          | 67 +++++++++++++++++++++++++++++----
 src/boitoutil/parser.h          |  3 +-
 src/shellOpt.c                  | 34 ++++++++---------
 5 files changed, 95 insertions(+), 26 deletions(-)

diff --git a/src/boitoutil/essential_shell.c b/src/boitoutil/essential_shell.c
index 53fca43..cc11047 100644
--- a/src/boitoutil/essential_shell.c
+++ b/src/boitoutil/essential_shell.c
@@ -13,6 +13,10 @@
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
+//#include <sys/types.h>
+#include <signal.h>
+
+pid_t pid;
 
 /**
  * native_command(): vérifie si la commande entrée par l’utilisateur
@@ -66,6 +70,14 @@ void change_dir(char *dir)
   }
 }
 
+void ctrl_c_handler()
+{
+  //kill(pid, SIGTERM);
+  //kill(pid, SIGKILL);
+  kill(getpid(), SIGCHLD);
+  printf("\n");
+}
+
 /**
  * error(): gère les erreurs selon leur code et leur type
  * @code: code de l’erreur, voir les différents codes dans le fichier .h
diff --git a/src/boitoutil/essential_shell.h b/src/boitoutil/essential_shell.h
index 53d1eae..48c99fc 100644
--- a/src/boitoutil/essential_shell.h
+++ b/src/boitoutil/essential_shell.h
@@ -7,6 +7,8 @@
  * @date 2021
  */
 
+#include <unistd.h>
+
 #ifndef _ESSHELL_
 #   define _ESSHELL_
 
@@ -17,8 +19,11 @@
 #define ERR_PIPE_CREATION 200   /* erreur lors de la création des pipes */
 #define ERR_FORK 201            /* erreur lors du fork */
 
+extern pid_t pid;
+
 int native_command(char *command[]);
 void change_dir(char *dir);
+void ctrl_c_handler();
 void error(int code, int type, char *message);
 
 #endif
diff --git a/src/boitoutil/parser.c b/src/boitoutil/parser.c
index 7dbcd28..25ade75 100644
--- a/src/boitoutil/parser.c
+++ b/src/boitoutil/parser.c
@@ -16,19 +16,30 @@
 /**
  * get_input(): Permet de récupérer la saisie de l’utilisateur
  *
- * Return: Entrée utilisateur
+ * Return: Entrée utilisateur ou NULL si ctrl d détecté
  */
 char* get_input()
 {
+  int stop = 0; /* en cas de ctrl d */
   char *buffer = (char *) calloc(MAX_LENGTH, sizeof(char));
   buffer[0] = '\n';
 
-  while (buffer[0] == '\n') 
+  while (buffer[0] == '\n' && !stop)
   {
     printf("> ");
-    fgets(buffer, MAX_LENGTH, stdin);
+    if(fgets(buffer, MAX_LENGTH, stdin) == NULL)
+      stop++;
   }
-  buffer[strlen(buffer)-1] = '\0'; /* pour ne pas avoir un retour à la ligne */
+
+  if (stop)
+  {
+    free(buffer);
+    buffer = NULL;
+    putchar('\n'); /* pour un affichage propre */
+  }
+  else
+    buffer[strlen(buffer)-1] = '\0'; /* pour ne pas avoir un retour à la ligne */
+
   return buffer;
 }
 
@@ -39,12 +50,23 @@ char* get_input()
  *
  * Récupère l’entrée de l’utilisateur avant de la parser avec le caractère
  * find. Chaque string sera mise dans une case de args.
+ *
+ * Return: 0 si tout est OK, 1 sinon
  */
-void get_command(char *args[], char find)
+int get_command(char *args[], char find)
 {
+  int ret = 0;
   char *user_input = get_input();
-  parse_string(user_input, args, find);
-  free(user_input);
+
+  if (user_input == NULL)
+    ret = 1;
+  else
+  {
+    parse_string(user_input, args, find);
+    free(user_input);
+  }
+
+  return ret;
 }
 
 /**
@@ -88,3 +110,34 @@ void parse_string(char *orig, char *dest[], char find)
 
   free(token);
 }
+
+/**
+ * detect_exit(): vérifie si la commande entrée est exit
+ * @command: la première commande entrée par l’utilisateur
+ *
+ * Return: 0 si ce n’est pas exit, 1 sinon
+ */
+int detect_exit(char *command)
+{
+  /*
+   * TODO c’est dégueulasse, à changer pour un truc plus propre
+   */
+  char *str = malloc(MAX_LENGTH * sizeof(char));
+  strcpy(str, command);
+  char find = ' ';
+  char *token = strtok(str, &find);
+  char *args[MAX_LENGTH];
+  int ret = 0, i = 0;
+  while (token != NULL)
+  {
+    args[i] = token;
+    token = strtok(NULL, &find);
+    i++;
+  }
+
+  if (i == 1 && !strcmp(args[0], "exit"))
+    ret++;
+
+  free(token);
+  return ret;
+}
diff --git a/src/boitoutil/parser.h b/src/boitoutil/parser.h
index 3e3ab7d..c4e3d93 100644
--- a/src/boitoutil/parser.h
+++ b/src/boitoutil/parser.h
@@ -11,7 +11,8 @@
 #   define _PARSER_H_
 
 char* get_input();
-void get_command(char *args[], char find);
+int get_command(char *args[], char find);
 void parse_string(char *args,char  *commands[], char find);
+int detect_exit(char *command);
 
 #endif
diff --git a/src/shellOpt.c b/src/shellOpt.c
index 75458ad..7b1e692 100644
--- a/src/shellOpt.c
+++ b/src/shellOpt.c
@@ -14,6 +14,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <sys/wait.h>
+#include <signal.h>
 
 int main()
 {
@@ -27,9 +28,18 @@ int main()
   char *commands[MAX_LENGTH]; 
   char *args[MAX_LENGTH]; 
 
-  int pid, result, index = 0, end = 0; /* end permet de savoir quand s’arreter */
+  int result, index = 0, end = 0; /* end permet de savoir quand s’arreter */
   int my_pipe[2];
-  setenv("HELLO", "test", 1);
+
+  /* init pour la gestion du ctrl c */
+  struct sigaction ctrc_handler;
+  ctrc_handler.sa_handler = ctrl_c_handler;
+  sigemptyset(&ctrc_handler.sa_mask);
+  ctrc_handler.sa_flags = 0;
+
+  sigaction(SIGINT, &ctrc_handler, NULL);
+
+  setenv("HELLO", "test", 1); /* juste un test */
 
   if (pipe(my_pipe) == -1)
     error(ERR_PIPE_CREATION, FATAL_ERROR, NULL);
@@ -40,9 +50,7 @@ int main()
     commands[i] = (char *) calloc(MAX_LENGTH, sizeof(char));
   }
 
-  get_command(commands, '|');
-
-  while (strcmp(commands[0], "exit"))
+  while (!get_command(commands, '|') && !detect_exit(commands[0]))
   {
     while (commands[index] != NULL)
     {
@@ -68,7 +76,7 @@ int main()
           else
             fclose(fdopen(my_pipe[0], "w"));
           /* si la commande est intermédiaire dans le pipe, on vide le buffer
-           * de sortie */
+           * de sortie NE MARCHE PAS */
 
           execvp(args[0], args);
           exit(errno);
@@ -80,12 +88,10 @@ int main()
         {
           close(my_pipe[0]);
           close(my_pipe[1]);
-          waitpid(pid, &result, 0);
         }
-        else 
-          wait(&result);
+        waitpid(pid, &result, 0);
 
-        if(WIFEXITED(result))
+        if(WIFEXITED(result)) /* on récupère le code de retour pour afficher l’erreur */
           error(WEXITSTATUS(result), NON_FATAL_ERROR, NULL);
       }
 
@@ -106,16 +112,8 @@ int main()
       commands[i] = (char *) calloc(MAX_LENGTH, sizeof(char));
     }
 
-    get_command(commands, '|');
     if (pipe(my_pipe) == -1)
-    {
-      for (int i = 0; i < MAX_LENGTH; i++)
-      {
-        free(args[i]);
-        free(commands[i]);
-      }
       error(ERR_PIPE_CREATION, FATAL_ERROR, NULL);
-    }
     index = 0;
   }