Ver Fonte

Merge pull request #1 from Loquicom/parser

Ajout parser de commande
Loquicom há 6 anos atrás
pai
commit
de9e9cc66f
5 ficheiros alterados com 281 adições e 3 exclusões
  1. 10 0
      constante.h
  2. 13 1
      mysh.c
  3. 257 1
      parser.c
  4. 1 0
      parser.h
  5. 0 1
      str.c

+ 10 - 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
@@ -25,6 +26,15 @@
 #define SHELL_ELSE 3 //La commande suivante s'execute si l'actuel échou
 #define SHELL_PIPE 4 //Envoi des données de sorties vers la commande suivante
 
+/* --- Redirection (Shell Redirect [Erase]) --- */
+#define SHELLR_IN 0 // <
+#define SHELLR_OUT 1 // >>
+#define SHELLRE_OUT 2 // >
+#define SHELLR_ERR 3 // 2>>
+#define SHELLRE_ERR 4 // 2>
+#define SHELLR_ALL 5 // >>&
+#define SHELLRE_ALL 6 // >&
+
 /* --- Boolean --- */
 #define boolean int
 #define true 1

+ 13 - 1
mysh.c

@@ -22,13 +22,25 @@ int main(int argc, char* argv[]) {
     char str[500];
     int a;
     //Recup ligne
-    printf("%s\n", fgets(str, 500, stdin));
+    //printf("%s\n", fgets(str, 500, stdin));&
+    memset(str, 0, 500);
+    a = read(STDIN, str, 500);
+    printf("%s\n", str);
     //Separe les commandes
     a = parse_line(&ct, str);
     printf("Result : %d\n\n", a);
     //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);

+ 257 - 1
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,6 +123,239 @@ int get_command(Command* c, char* line){
     return length + separator;
 }
 
+int set_io(Command* c, char* filename, int redir){
+    //Declaration variable
+    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;
+    }
+    //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;
+    }
+    //Si on arrive ici tous est ok
+    return SHELL_OK;
+}
+
+int set_redirection(Command* c){
+    boolean first = true, guillemet = false;
+    char* deb, * file, * buffer = c->cmd + 1;
+    int redir = -1, compteur, finCmd = 0;
+    //Parcours chaine
+    while(*buffer){
+        //Repere redirection
+        while(*buffer){
+            //Entrée
+            if(*buffer == '<'){
+                //Si il n'y a rien apres
+                if(!(*(buffer + 1))){
+                    return SHELL_ERR;
+                }
+                buffer++;
+                redir = SHELLR_IN;
+                break;
+            } 
+            //Sortie
+            else if (*buffer == '>'){
+                //Si il n'y a rien apres
+                if(!(*(buffer + 1))){
+                    return SHELL_ERR;
+                } else {
+                    buffer++;
+                    //Si >>
+                    if(*buffer == '>'){
+                        //Si il n'y a rien apres
+                        if(!(*(buffer + 1))){
+                            return SHELL_ERR;
+                        } else {
+                            buffer++;
+                            //Si >>&
+                            if(*buffer == '&'){
+                                //Si il n'y a rien apres
+                                if(!(*(buffer + 1))){
+                                    return SHELL_ERR;
+                                }
+                                buffer++;
+                                redir = SHELLRE_ALL;
+                            }
+                            //Sinon toujours >>
+                            else {
+                                redir = SHELLR_OUT;
+                            }
+                        }
+                    }
+                    // Si >&
+                    else if(*buffer == '&'){
+                        //Si il n'y a rien apres
+                        if(!(*(buffer + 1))){
+                            return SHELL_ERR;
+                        }
+                        redir = SHELLRE_ALL;
+                        buffer++;
+                    } 
+                    //Sinon >
+                    else {
+                        redir = SHELLRE_OUT;
+                    }
+                }
+                break;
+            }
+            //Sortie erreur
+            else if (*buffer == '2' && *(buffer - 1) == ' ' && *(buffer + 1) && *(buffer + 1) == '>'){
+                buffer++;
+                //Si il n'y a rien apres
+                if(!(*(buffer + 1))){
+                    return SHELL_ERR;
+                } else {
+                    buffer++;
+                    //Si 2>>
+                    if(*buffer == '>'){
+                        buffer++;
+                        //Si il n'y a rien apres
+                        if(!(*(buffer + 1))){
+                            return SHELL_ERR;
+                        }
+                        redir = SHELLR_ERR;
+                    }
+                    //Sinon 2>
+                    else {
+                        redir = SHELLRE_ERR;
+                    }
+                }
+                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 ""
+        guillemet = *buffer == '"';
+        //Sauvegarde debut nom fichier
+        deb = buffer;
+        compteur = 0;
+        //Lecture nom du fichier
+        while(*buffer){     
+            //Incremente
+            compteur++;
+            buffer++;
+            //Test arret
+            if(guillemet && *buffer == '"'){
+                break;
+            }
+            else if(!guillemet && (*buffer == '<' || *buffer == '>' || (*buffer == ' ' && *(buffer - 1) != '\\'))){
+                break;
+            }
+        }
+        //Si fin de la commande et guillemet alors erreur
+        if(!(*buffer) && guillemet){
+            return SHELL_ERR;
+        }
+        //Retire guillement si besoin
+        if(guillemet){
+            deb++;
+            compteur--;
+            buffer++;
+        }
+        //Allocation file et copie nom fichier
+        file = malloc(sizeof(char) * compteur);  
+        strncpy(file, deb, compteur);
+        //Redirection
+        if(set_io(c, file, redir) == SHELL_ERR){
+            free(file);
+            return SHELL_ERR;
+        }
+        free(file);
+        //Passe les espaces
+        while(*buffer == ' '){
+            buffer++;
+        }
+    }
+    //Si on arrive ici tous est ok
+    return finCmd;
+}
+
 /* --- Fonctions publiques --- */
 int parse_line(CommandTab* ct, char* line){
     //Declaration variable
@@ -146,7 +385,24 @@ int parse_line(CommandTab* ct, char* line){
 }
 
 int parse_command(Command* c){
-    return 1;
+    //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){

+ 1 - 0
parser.h

@@ -21,6 +21,7 @@ typedef struct{
     int input; //Descripteur de fichier d'entré
     int output; //Descripteur de fichier de sortie
     int error; //Descripteur de fihier d'erreur
+    boolean erase[2]; //Si on efface le fichier
     boolean bck; //En fond ou non
     int next; //Lien avec la prochaine commande
 }Command;

+ 0 - 1
str.c

@@ -1,6 +1,5 @@
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include "str.h"
 
 char** str_split(char* str, const char delim, int* length) {