Kaynağa Gözat

:sparkles: Parse les commandes

Loquicom 6 yıl önce
ebeveyn
işleme
94d72e3bf7
3 değiştirilmiş dosya ile 158 ekleme ve 27 silme
  1. 1 0
      constante.h
  2. 9 0
      mysh.c
  3. 148 27
      parser.c

+ 1 - 0
constante.h

@@ -9,6 +9,7 @@
 #define CONSTANTE_H
 
 /* --- General --- */
+#define ERR -1
 #define SHELL_ERR -1
 #define SHELL_FAIL 0
 #define SHELL_OK 1

+ 9 - 0
mysh.c

@@ -32,6 +32,15 @@ int main(int argc, char* argv[]) {
     //Parse les commandes
     a = parse_all_command(&ct);
     printf("Result : %d\n\n", a);
+    //Affiche resultat
+    for(int i = 0; i < ct.length; i++){
+        Command* c = ct.cmd[i];
+        printf("Commande %d (%s) : \n", i, c->name);
+        for(int j = 0; j < c->argc; j++){
+            printf("    Argument %d : %s\n", j, c->argv[j]);
+        }
+        printf("\n");
+    }
     //Supprime
     clean_command(&ct);
     return (EXIT_SUCCESS);

+ 148 - 27
parser.c

@@ -9,6 +9,9 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
 #include "parser.h"
 
 /* --- Fonctions privées --- */
@@ -109,6 +112,9 @@ int get_command(Command* c, char* line){
     c->input = STDIN;
     c->output = STDOUT;
     c->error = STDERR;
+    c->erase[0] = false;
+    c->erase[1] = false;
+    c->bck = false;
     //Trim et supprime l'ancienne chaine
     old = c->cmd;
     c->cmd = rtrim(c->cmd, ' ');
@@ -117,38 +123,89 @@ int get_command(Command* c, char* line){
     return length + separator;
 }
 
-/* --- Fonctions publiques --- */
-int parse_line(CommandTab* ct, char* line){
+int set_io(Command* c, char* filename, int redir){
     //Declaration variable
-    int compteur, tmp;
-    //Nettoyage ligne
-    line = trim(mtrim(line, '\n'));
-    //Compte le nombre de commande dans la ligne
-    compteur = nb_commands(line);
-    if(compteur == SHELL_ERR){
+    int file;
+    //Ouverture du fichier
+    file = open(filename, O_CREAT | O_RDWR, S_IRWXU);
+    if(file == ERR){
+        perror("Erreur lors de l'ouverture du fichier pour la redirection : ");
         return SHELL_ERR;
     }
-    //Initialisation structure
-    ct->cmd = malloc(sizeof(Command*) * compteur);
-    ct->length = compteur;
-    //Recupération de chaque commande
-    for(int i = 0; i < compteur; i++){
-        ct->cmd[i] = malloc(sizeof(Command));
-        tmp = get_command(ct->cmd[i], line);
-        line += tmp;
-        //Si pas dernière commande on trim
-        if(i + 1 < compteur){
-            line = ltrim(line, ' ');
-        }
+    //Analyse dans quel descripteur il doit etre mis
+    switch(redir){
+        case SHELLR_IN:
+            //Si un fichier deja ouvert
+            if(c->input != STDIN){
+                //On le ferme
+                if(close(c->input) == -1){
+                    perror("Erreur lors de la fermeture de l'ancien fichier de redirection : ");
+                }
+            }
+            //Set nouveau fichier
+            c->input = file;
+            break;
+        case SHELLR_OUT:
+        case SHELLRE_OUT:
+            //Si un fichier deja ouvert
+            if(c->output != STDOUT){
+                //On le ferme
+                if(close(c->output) == -1){
+                    perror("Erreur lors de la fermeture de l'ancien fichier de redirection : ");
+                }
+            }
+            c->output = file;
+            if(redir == SHELLRE_OUT){
+                c->erase[STDOUT - 1] = true;
+            }
+            break;
+        case SHELLR_ERR:
+        case SHELLRE_ERR:
+            //Si un fichier deja ouvert
+            if(c->error != STDERR){
+                //On le ferme
+                if(close(c->error) == -1){
+                    perror("Erreur lors de la fermeture de l'ancien fichier de redirection : ");
+                }
+            }
+            c->error = file;
+            if(redir == SHELLRE_ERR){
+                c->erase[STDERR - 1] = true;
+            }
+            break;
+        case SHELLR_ALL:
+        case SHELLRE_ALL:
+            //Si un fichier deja ouvert
+            if(c->output != STDOUT){
+                //On le ferme
+                if(close(c->output) == -1){
+                    perror("Erreur lors de la fermeture de l'ancien fichier de redirection : ");
+                }
+            }
+            if(c->error != STDERR){
+                //On le ferme
+                if(close(c->error) == -1){
+                    perror("Erreur lors de la fermeture de l'ancien fichier de redirection : ");
+                }
+            }
+            c->output = file;
+            c->error = file;
+            if(redir == SHELLRE_ALL){
+                c->erase[STDOUT - 1] = true;
+                c->erase[STDERR - 1] = true;
+            }
+            break;
+        default :
+            return SHELL_ERR;
     }
-    //Retour
+    //Si on arrive ici tous est ok
     return SHELL_OK;
 }
 
-int parse_command(Command* c){
-    boolean guillemet = false;
+int set_redirection(Command* c){
+    boolean first = true, guillemet = false;
     char* deb, * file, * buffer = c->cmd + 1;
-    int redir = 0, compteur;
+    int redir = -1, compteur, finCmd = 0;
     //Parcours chaine
     while(*buffer){
         //Repere redirection
@@ -233,13 +290,24 @@ int parse_command(Command* c){
                 break;
             }
             buffer++;
+            //On incremente pour trouver la fin de la commande
+            if(first){
+                finCmd++;
+            }
         }
+        //Apres ce n'est que des redirection
+        first = false;
         //On passe les espaces
         while(*buffer == ' '){
             buffer++;
         }
         //Si on est à la fin de la chaine
         if(*buffer == '\0'){
+            if(redir == -1){
+                //Aucune redirection
+                return finCmd + 1;
+            }
+            //Sinon on est dans un redirection non terminée
             return SHELL_ERR;
         }
         //Regarde si le nom du fichier est entre ""
@@ -273,15 +341,68 @@ int parse_command(Command* c){
         //Allocation file et copie nom fichier
         file = malloc(sizeof(char) * compteur);  
         strncpy(file, deb, compteur);
-        printf("%s %d %d\n", file, redir, guillemet);
+        //Redirection
+        if(set_io(c, file, redir) == SHELL_ERR){
+            free(file);
+            return SHELL_ERR;
+        }
         free(file);
         //Passe les espaces
         while(*buffer == ' '){
             buffer++;
         }
     }
-    
-    return 1;
+    //Si on arrive ici tous est ok
+    return finCmd;
+}
+
+/* --- Fonctions publiques --- */
+int parse_line(CommandTab* ct, char* line){
+    //Declaration variable
+    int compteur, tmp;
+    //Nettoyage ligne
+    line = trim(mtrim(line, '\n'));
+    //Compte le nombre de commande dans la ligne
+    compteur = nb_commands(line);
+    if(compteur == SHELL_ERR){
+        return SHELL_ERR;
+    }
+    //Initialisation structure
+    ct->cmd = malloc(sizeof(Command*) * compteur);
+    ct->length = compteur;
+    //Recupération de chaque commande
+    for(int i = 0; i < compteur; i++){
+        ct->cmd[i] = malloc(sizeof(Command));
+        tmp = get_command(ct->cmd[i], line);
+        line += tmp;
+        //Si pas dernière commande on trim
+        if(i + 1 < compteur){
+            line = ltrim(line, ' ');
+        }
+    }
+    //Retour
+    return SHELL_OK;
+}
+
+int parse_command(Command* c){
+    //Declaration variable
+    int length;
+    char* cmd;
+    //Parse les redirections
+    length = set_redirection(c);
+    if(length == SHELL_ERR){
+        return SHELL_ERR;
+    }
+    //Recup la commande (sans redirection)
+    cmd = malloc(length);
+    strncpy(cmd, c->cmd, length);
+    //Split en un tableau
+    c->argv = str_split(cmd, ' ', &c->argc); //ToDo changer par un methode de split qui prend en compte les " " et les \espaces
+    c->name = c->argv[0];
+    //Analyse wildcard
+    /* Todo */
+    //Ici tous est ok
+    return SHELL_OK;
 }
 
 int parse_all_command(CommandTab* ct){