Prechádzať zdrojové kódy

Merge pull request #15 from Loquicom/mem

Mem
Loquicom 6 rokov pred
rodič
commit
687b9c6c55
21 zmenil súbory, kde vykonal 1812 pridanie a 112 odobranie
  1. 3 1
      .gitignore
  2. 236 12
      command.c
  3. 116 1
      command.h
  4. 8 0
      constante.h
  5. 6 1
      execute.c
  6. 66 0
      expreg.c
  7. 50 0
      expreg.h
  8. 150 0
      ipc.c
  9. 74 0
      ipc.h
  10. 18 4
      makefile
  11. 39 91
      mysh.c
  12. 7 1
      mysh.h
  13. 14 1
      parser.c
  14. 140 0
      sem.c
  15. 71 0
      sem.h
  16. 126 0
      shm.c
  17. 63 0
      shm.h
  18. 322 0
      subdiv.c
  19. 85 0
      subdiv.h
  20. 164 0
      variable.c
  21. 54 0
      variable.h

+ 3 - 1
.gitignore

@@ -53,4 +53,6 @@ dkms.conf
 /.directory
 /nbproject
 /mysh
-/mysh.log
+/mysh.log
+*.log
+/bug.txt

+ 236 - 12
command.c

@@ -4,6 +4,7 @@
  *
  * Created on 9 novembre 2018
  */
+#define _POSIX_C_SOURCE 200112L
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -11,19 +12,30 @@
 #include "error.h"
 #include "str.h"
 #include "parser.h"
-#include "mysh.h"
 #include "execute.h"
+#include "ipc.h"
+#include "variable.h"
 #include "command.h"
+#include "mysh.h"
 
 /* --- Extern --- */
 extern Error error;
 extern pid_t last;
 extern int status_cmd;
 extern int result_cmd;
+extern char base_path[];
+extern pid_list pidlist;
 char* cmdlist[] = {
     "cd",
     "exit",
     "status",
+    "setenv",
+    "unsetenv",
+    "set",
+    "unset",
+    "myls",
+    "myps",
+    "myjobs",
     NULL
 };
 boolean exitsh = false;
@@ -34,10 +46,18 @@ void ini_pid_list(pid_list* pl) {
     pl->last = NULL;
 }
 
-pid_node* add_pid(pid_list* pl, pid_t pid, int job) {
+pid_node* add_pid(pid_list* pl, pid_t pid, int job, char* cmd) {
+    int length;
+    //Creation noeud
     pid_node* pn = malloc(sizeof (pid_node));
     pn->pid = pid;
     pn->job = job;
+    //Copie nom commande
+    length = strlen(cmd) + 1;
+    pn->cmd = malloc(sizeof(char) * length);
+    memset(pn->cmd, 0, length);
+    strncpy(pn->cmd, cmd, length - 1);
+    //Setup chainement
     pn->next = NULL;
     if (pl->first == NULL) {
         pn->prev = NULL;
@@ -63,21 +83,22 @@ pid_node* search_pid(pid_list* pl, pid_t pid) {
 }
 
 void remove_pid(pid_list* pl, pid_node* pn) {
+    free(pn->cmd);
     //Si 1er et seul
     if (pn->prev == NULL && pn->next == NULL) {
         pl->first = NULL;
         pl->last = NULL;
-    }        
+    }
     //Si 1er et non seul
     else if (pn->prev == NULL && pn->next != NULL) {
         pn->next->prev = NULL;
         pl->first = pn->next;
-    }        
+    }
     //Si dernier
     else if (pn->next == NULL) {
         pn->prev->next = NULL;
         pl->last = pn->prev;
-    }        
+    }
     //Sinon si il est au milieu
     else {
         pn->prev->next = pn->next;
@@ -91,6 +112,7 @@ void clean_pid(pid_list* pl) {
     pid_node* tmp, * pn = pl->first;
     while (pn != NULL) {
         tmp = pn->next;
+        free(pn->cmd);
         free(pn);
         pn = tmp;
     }
@@ -114,17 +136,52 @@ int launch_internal_command(Command* cmd) {
     if (strncmp(cmd->name, cmdlist[0], length) == 0) {
         result = cd(cmd->argc, cmd->argv);
         return result;
-    } 
+    }
     //exit
     else if (strncmp(cmd->name, cmdlist[1], length) == 0) {
         result = exit_sh(cmd->argc, cmd->argv);
         return result;
-    }
+    }        
     //status
     else if (strncmp(cmd->name, cmdlist[2], length) == 0) {
         result = status(cmd->argc, cmd->argv);
         return result;
+    }        
+    //setenv
+    else if (strncmp(cmd->name, cmdlist[3], length) == 0) {
+        result = set_env(cmd->argc, cmd->argv);
+        return result;
+    }        
+    //unsetenv
+    else if (strncmp(cmd->name, cmdlist[4], length) == 0) {
+        result = unset_env(cmd->argc, cmd->argv);
+        return result;
     }
+    //set
+    else if (strncmp(cmd->name, cmdlist[5], length) == 0) {
+        result = set_local(cmd->argc, cmd->argv);
+        return result;
+    }        
+    //unset
+    else if (strncmp(cmd->name, cmdlist[6], length) == 0) {
+        result = unset_local(cmd->argc, cmd->argv);
+        return result;
+    }
+    //myls
+    else if (strncmp(cmd->name, cmdlist[7], length) == 0) {
+        result = myls(cmd->argc, cmd->argv);
+        return result;
+    }        
+    //myps
+    else if (strncmp(cmd->name, cmdlist[8], length) == 0) {
+        result = myps(cmd->argc, cmd->argv);
+        return result;
+    }   
+    //myjobs
+    else if (strncmp(cmd->name, cmdlist[9], length) == 0) {
+        result = myjobs(cmd->argc, cmd->argv);
+        return result;
+    }   
     //Aucune commande
     else {
         return SHELL_FAIL;
@@ -144,7 +201,7 @@ int cd(int argc, char** argv) {
                 addperror("Erreur chdir()");
                 return EXIT_FAILURE;
             }
-        }
+        }            
         //Sinon on va dans le dossier indiqué par l'utilisateur
         else {
             if (chdir(argv[1]) == ERR) {
@@ -157,21 +214,188 @@ int cd(int argc, char** argv) {
     //show_current_dir("current working directory is: ", "\n");
 }
 
-int exit_sh(int argc, char** argv){
+int exit_sh(int argc, char** argv) {
     exitsh = true;
     return EXIT_SUCCESS;
 }
 
-int status(int argc, char** argv){
-    if(!(last != -1 && status_cmd != -1)){
+int status(int argc, char** argv) {
+    if (!(last != -1 && status_cmd != -1)) {
         error.print("Aucune commande executée\n");
         return EXIT_FAILURE;
     }
     //En fonction du status
-    if(result_cmd == SHELL_FAIL){
+    if (result_cmd == SHELL_FAIL) {
         printf("%d terminé anormalement\n", last);
     } else {
         printf("%d terminé avec comme code de retour %d\n", last, status_cmd);
     }
     return EXIT_SUCCESS;
+}
+
+int set_env(int argc, char** argv) {
+    char* str, * key, * val;
+    int length, pos = 0;
+    //Verif les arguments
+    if (argc < 2) {
+        show_shm_data();
+        return EXIT_SUCCESS;
+    }
+    if (argc > 2) {
+        error.print("too many arguments : 1 required, %d given\n", argc - 1);
+        return EXIT_FAILURE;
+    }
+    str = argv[1];
+    length = strlen(str);
+    //Verif que chaine est correcte
+    for (int i = 0; i < length; i++) {
+        if (str[i] == '=') {
+            break;
+        }
+        pos++;
+    }
+    if (pos >= length - 1) {
+        error.print("Argument invalide : clef=valeur attendu, %s donnée\n", str);
+        return EXIT_FAILURE;
+    }
+    //Decoupe la chaine
+    key = malloc(sizeof (char) * (pos + 1));
+    memset(key, 0, pos + 1);
+    strncpy(key, str, pos);
+    val = str + pos + 1;
+    //Ajoute la chaine en shm
+    if (!add_shm_data(str)) {
+        error.print("Erreur interne impossible d'ajouter la variable\n");
+        free(key);
+        return EXIT_FAILURE;
+    }
+    //Ajoute sur le système
+    if (setenv(key, val, true) == ERR) {
+        addperror("Impossible d'ajouter la variable d'environnement");
+        error.print("Erreur interne impossible d'ajouter la variable\n");
+        free(key);
+        return EXIT_FAILURE;
+    }
+    free(key);
+    return EXIT_SUCCESS;
+}
+
+int unset_env(int argc, char** argv) {
+    //Verif les arguments
+    if (argc < 2) {
+        error.print("too few arguments : 1 required, 0 given\n");
+        return EXIT_FAILURE;
+    }
+    if (argc > 2) {
+        error.print("too many arguments : 1 required, %d given\n", argc - 1);
+        return EXIT_FAILURE;
+    }
+    //Supprime de la shm
+    if (!remove_shm_data(argv[1])) {
+        error.print("Erreur interne impossible de supprimer la variable\n");
+        return EXIT_FAILURE;
+    }
+    //Supprime du systeme
+    if (unsetenv(argv[1]) == ERR) {
+        addperror("Impossible de supprimer la variable d'environnement");
+        error.print("Erreur interne impossible de supprimer la variable\n");
+        return EXIT_FAILURE;
+    }
+    return EXIT_SUCCESS;
+}
+
+int set_local(int argc, char** argv){
+    char* str;
+    int length, pos = 0;
+    //Verif les arguments
+    if (argc < 2) {
+        show_local_data();
+        return EXIT_SUCCESS;
+    }
+    if (argc > 2) {
+        error.print("too many arguments : 1 required, %d given\n", argc - 1);
+        return EXIT_FAILURE;
+    }
+    str = argv[1];
+    length = strlen(str);
+    //Verif que chaine est correcte
+    for (int i = 0; i < length; i++) {
+        if (str[i] == '=') {
+            break;
+        }
+        pos++;
+    }
+    if (pos >= length - 1) {
+        error.print("Argument invalide : clef=valeur attendu, %s donnée\n", str);
+        return EXIT_FAILURE;
+    }
+    //Ajoute la chaine en shm
+    if (!add_local_data(str)) {
+        error.print("Erreur interne impossible d'ajouter la variable\n");
+        return EXIT_FAILURE;
+    }
+    return EXIT_SUCCESS;
+}
+
+int unset_local(int argc, char** argv){
+    //Verif les arguments
+    if (argc < 2) {
+        error.print("too few arguments : 1 required, 0 given\n");
+        return EXIT_FAILURE;
+    }
+    if (argc > 2) {
+        error.print("too many arguments : 1 required, %d given\n", argc - 1);
+        return EXIT_FAILURE;
+    }
+    //Supprime de la shm
+    if (!remove_local_data(argv[1])) {
+        error.print("Erreur interne impossible de supprimer la variable\n");
+        return EXIT_FAILURE;
+    }
+    return EXIT_SUCCESS;
+}
+
+int myls(int argc, char** argv){
+    //Preparation nom cmd
+    int length = strlen(base_path);
+    char* path = malloc(sizeof(char) * (length + 4 + 1));
+    memset(path, 0, length + 4 + 1);
+    strncpy(path, base_path, length);
+    path[length] = '/';
+    path[length + 1] = 'm';
+    path[length + 2] = 'y';
+    path[length + 3] = 'l';
+    path[length + 4] = 's';
+    //Execution
+    //return exec_file(path, argv);
+    return 0;
+}
+
+int myps(int argc, char** argv){
+    //Preparation nom cmd
+    int length = strlen(base_path);
+    char* path = malloc(sizeof(char) * (length + 4 + 1));
+    memset(path, 0, length + 4 + 1);
+    strncpy(path, base_path, length);
+    path[length] = '/';
+    path[length + 1] = 'm';
+    path[length + 2] = 'y';
+    path[length + 3] = 'p';
+    path[length + 4] = 's';
+    //Execution
+    //return exec_file(path, argv);
+    return 0;
+}
+
+int myjobs(int argc, char** argv){
+    pid_node* pn = pidlist.first;
+    if(pn == NULL){
+        printf("Aucun job\n");
+        return EXIT_SUCCESS;
+    }
+    while(pn != NULL){
+        printf("[%d] %d En cours %s\n", pn->job, pn->pid, pn->cmd);
+        pn = pn->next;
+    }
+    return EXIT_SUCCESS;
 }

+ 116 - 1
command.h

@@ -17,6 +17,7 @@ typedef struct pid_node pid_node;
 struct pid_node{
     pid_t pid;
     int job;
+    char* cmd;
     pid_node* prev;
     pid_node* next;
 };
@@ -30,12 +31,55 @@ extern char* cmdlist[];
 extern boolean exitsh;
 
 /* --- Fonctions --- */
+/**
+ * Initialise la liste de PID
+ * @param pid_list* La liste de PID
+ */
 void ini_pid_list(pid_list*);
-pid_node* add_pid(pid_list*, pid_t, int);
+
+/**
+ * Ajoute un PID dans la liste
+ * @param pid_list* La liste de PID
+ * @param pid_t Le pid
+ * @param int Le numero de job
+ * @param char* Le nom de la commande
+ * @return Le noeud crée
+ */
+pid_node* add_pid(pid_list*, pid_t, int, char*);
+
+/**
+ * Cherche un PID dans la liste
+ * @param pid_list* La liste de PID
+ * @param pid_t le PID
+ * @return Le noeud du pid
+ */
 pid_node* search_pid(pid_list*, pid_t);
+
+/**
+ * Supprime un PID de la liste
+ * @param pid_list* La liste de PID
+ * @param pid_node* Le noeud à supprimer
+ */
 void remove_pid(pid_list*, pid_node*);
+
+/**
+ * Vide la liste de PID
+ * @param pid_list* La liste de PID
+ */
 void clean_pid(pid_list*);
+
+/**
+ * Indique si un commande est une commande interne
+ * @param char* La commande
+ * @return Truu : oui / False : non
+ */
 boolean is_internal_cmd(const char*);
+
+/**
+ * Lance une commande intene
+ * @param Commande* La structure de la commande
+ * @return Le statut
+ */
 int launch_internal_command(Command*);
 
 /* --- Commandes --- */
@@ -43,10 +87,81 @@ int launch_internal_command(Command*);
  * Change le dossier de travail actuel
  * @param int argc
  * @param char** argv
+ * @return Statut
  */
 int cd(int, char**);
+
+/**
+ * Quitte le shell
+ * @param int argc
+ * @param char** argv
+ * @return Statut
+ */
 int exit_sh(int, char**);
+
+/**
+ * Statut de la dernière éxecution
+ * @param int argc
+ * @param char** argv
+ * @return Statut
+ */
 int status(int, char**);
 
+/**
+ * AJoute une variable d'environnement
+ * @param int argc
+ * @param char** argv
+ * @return Statut
+ */
+int set_env(int, char**);
+
+/**
+ * Supprime une variable d'environnement
+ * @param int argc
+ * @param char** argv
+ * @return Statut
+ */
+int unset_env(int, char**);
+
+/**
+ * Ajoute une variable locale
+ * @param int argc
+ * @param char** argv
+ * @return Statut
+ */
+int set_local(int, char**);
+
+/**
+ * Supprime une variable locale
+ * @param int argc
+ * @param char** argv
+ * @return Statut
+ */
+int unset_local(int, char**);
+
+/**
+ * Execute le programme myls
+ * @param int argc
+ * @param char** argv
+ * @return Statut
+ */
+int myls(int, char**);
+
+/**
+ * Execute le programma myps
+ * @param int argc
+ * @param char** argv
+ * @return Statut
+ */
+int myps(int, char**);
+
+/**
+ * Affiche tous les jobs
+ * @param int argc
+ * @param char** argv
+ * @return Statut
+ */
+int myjobs(int, char**);
+
 #endif /* COMMAND_H */
 

+ 8 - 0
constante.h

@@ -10,6 +10,7 @@
 
 /* --- General --- */
 #define BUFFER_SIZE 512
+#define MEM_SIZE 8192
 #define SHELL_ERR -1
 #define SHELL_FAIL 0
 #define SHELL_OK 1
@@ -39,6 +40,13 @@
 #define SHELLR_ALL 5 // >>&
 #define SHELLRE_ALL 6 // >&
 
+/* --- IPC --- */
+#define IPCKEYPATH "/bin/ls"
+#define SEMCODE 8426
+#define SHMCODEMEM 8520 //Code shm zone des variables
+#define SHMCODEGEST 8521 //Code shm du gestionnaire de la zone des variables
+#define SHMCODEGLOB 8522 //Code shm des varaibles globales entre tous les processus mysh
+
 /* --- Boolean --- */
 #define boolean int
 #define true 1

+ 6 - 1
execute.c

@@ -10,6 +10,7 @@
 #include <unistd.h>
 #include <sys/types.h>
 #include <wait.h>
+#include <string.h>
 #include "error.h"
 #include "execute.h"
 
@@ -48,7 +49,11 @@ int exec_shell(char* name, char** argv){
         //Execute commande
         execvp(name, argv);
         //Si on arrive ici alors erreur
-        addperror("Impossible d'executer la commande");
+        char* errmsg = "Erreur dans le fichier execute.c, fonction exec_shell : Impossible d'executer la commande\n";
+        if(write(result, errmsg, sizeof(char) * strlen(errmsg)) == ERR){
+            addperror("Impossible d'écrire dans le fichier de log");
+        }
+        fprintf(stderr, "Commande introuvable\n");
         exit(EXIT_FAILURE);
     }
     //Pere

+ 66 - 0
expreg.c

@@ -0,0 +1,66 @@
+/* 
+ * File:   expreg.c
+ * Author: Arthur Brandao
+ *
+ * Created on 21 décembre 2018
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "expreg.h"
+
+/* --- Fonctions publiques --- */
+boolean ini_expreg(expreg* er, char* str, char* regex) {
+    //Setup regex
+    if (regcomp(&er->regex, regex, REG_EXTENDED) != 0) {
+        return false;
+    }
+    //Copie la chaine
+    int length = strlen(str);
+    er->str = malloc(sizeof (char) * (length + 1));
+    memset(er->str, 0, length + 1);
+    strncpy(er->str, str, length);
+    //Setup structure
+    er->pos = 0;
+    er->nmatch = er->regex.re_nsub;
+    er->pmatch = malloc(sizeof (regmatch_t) * er->nmatch);
+    return true;
+}
+
+char* get_match_expreg(expreg* er, int* deb, int* fin) {
+    if (regexec(&er->regex, er->str + er->pos, er->nmatch, er->pmatch, 0) != 0) {
+        if(deb != NULL){
+            *deb = -1;
+        }
+        if(fin != NULL){
+            *fin = -1;
+        }
+        return NULL;
+    }
+    //Recup info regex
+    int start = er->pmatch[0].rm_so;
+    int end = er->pmatch[0].rm_eo;
+    int length = end - start;
+    //Indique les positions
+    if(deb != NULL){
+        *deb = er->pos + start;
+    }
+    if(fin != NULL){
+        *fin = er->pos + end;
+    }
+    //Recup la chaine
+    char* str;
+    str = malloc(sizeof(char) * (length + 1));
+    memset(str, 0, length + 1);
+    strncpy(str, &er->str[er->pos + start], length);
+    //On avance dans la chaine
+    er->pos += end;
+    return str;
+}
+
+void clean_expreg(expreg* er) {
+    regfree(&er->regex);
+    free(er->str);
+    free(er->pmatch);
+}

+ 50 - 0
expreg.h

@@ -0,0 +1,50 @@
+/* 
+ * File:   expreg.h
+ * Author: Arthur Brandao
+ *
+ * Created on 21 décembre 2018
+ */
+
+#ifndef EXPREG_H
+#define EXPREG_H
+
+/* --- Include --- */
+#include <regex.h>
+#include "constante.h"
+
+/* --- Structure --- */
+typedef struct{
+    char* str; //La chaine à vérifier
+    int pos; //Position actuel dans la chaine à verifier
+    regex_t regex;
+    size_t nmatch;
+    regmatch_t* pmatch;
+}expreg;
+
+/* --- Fonctions --- */
+/**
+ * Initialise la structure de gestion du regex
+ * @param expreg* La structure de l'expression reguliere
+ * @param char* La chaine à analyser
+ * @param char* Le regex
+ * @return Reussite
+ */
+boolean ini_expreg(expreg*, char*, char*);
+
+/**
+ * Recupere la prochaine correspondance dans la chaine
+ * @param expreg* La structure de l'expression reguliere
+ * @param int* La position de debut de la correspondance
+ * @param int* La postion de fin de la correspondance
+ * @return La correspondance ou NULL si il n'y en à plus
+ */
+char* get_match_expreg(expreg*, int*, int*);
+
+/**
+ * Vide la structure de l'expression reguliere
+ * @param expreg* La structure de l'expression reguliere
+ */
+void clean_expreg(expreg*);
+
+#endif /* EXPREG_H */
+

+ 150 - 0
ipc.c

@@ -0,0 +1,150 @@
+/* 
+ * File:   ipc.c
+ * Author: Arthur Brandao
+ *
+ * Created on 21 décembre 2018
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "ipc.h"
+#include "variable.h"
+
+/* --- Extern --- */
+ipc_mysh ipc;
+extern int errno;
+
+/* --- Fonctions publiques --- */
+boolean setup_ipc(char** envp){
+    //boolean setup = true;
+    //SHM pour variable environnement
+    if(!create_shm(&ipc.memoire, SHMCODEMEM, MEM_SIZE)){
+        return false;
+    }
+    //SHM pour gestionnaire variable env
+    if(!create_shm(&ipc.gestionnaire, SHMCODEGEST, sizeof(subdiv))){
+        return false;
+    }
+    //SHM pour variable globale
+    if(!create_shm(&ipc.global, SHMCODEGLOB, sizeof(int))){
+        return false;
+    }
+    //Si creation alors on remplie les segments
+    if(errno != EEXIST){
+        subdiv* sd = (subdiv*) ipc.gestionnaire.adr;
+        char* mem = (char*) ipc.memoire.adr;
+        int* nb = (int*) ipc.global.adr;
+        ini_subdiv(sd);
+        int i = 0;
+	while(envp[i] != NULL){
+            add_fdata_subdiv(sd, mem, envp[i]);
+            i++;
+	}
+        *nb = 0;
+    }
+    //Semaphore
+    int ini[] = {1, 1, 1};
+    if(!create_sem(&ipc.sem, SEMCODE, 3, ini)){
+        return false;
+    }
+    return true;
+}
+
+boolean end_ipc(){
+    //Detache les shm
+    if(!unset_shm(&ipc.memoire)){
+        return false;
+    }
+    if(!unset_shm(&ipc.gestionnaire)){
+        return false;
+    }
+    if(!unset_shm(&ipc.global)){
+        return false;
+    }
+    //Tente de supprimer shm
+    if(delete_shm(&ipc.global)){
+        //Si on est le dernier processus en vie on supprime tous
+        if(!delete_shm(&ipc.memoire)){
+            return false;
+        }
+        if(!delete_shm(&ipc.gestionnaire)){
+            return false;
+        }
+        if(!delete_sem(&ipc.sem)){
+            return false;
+        }
+    }
+    return true;
+}
+
+char* parse_shm_var(char* str){
+    //Recup variable globale
+    subdiv* sd = (subdiv*) ipc.gestionnaire.adr;
+    char* mem = (char*) ipc.memoire.adr;
+    int* buf = (int*) ipc.global.adr;
+    int nb = *buf;
+    char* res;
+    //Regarde si l'ecrivain veut ecrire
+    P(&ipc.sem, SEMECRIRE);
+    V(&ipc.sem, SEMECRIRE);
+    //Modification variable globale
+    P(&ipc.sem, SEMMUTEX);
+    nb++;
+    if(nb == 1){
+        P(&ipc.sem, SEMWAIT);
+    }
+    V(&ipc.sem, SEMMUTEX);
+    //Lecture
+    res = parse_var(str, sd, mem);
+    //Modification variable globale
+    P(&ipc.sem, SEMMUTEX);
+    nb--;
+    if(nb == 0){
+        V(&ipc.sem, SEMWAIT);
+    }
+    V(&ipc.sem, SEMMUTEX);
+    return res;
+}
+
+boolean add_shm_data(char* data){
+    //Recup variable globale
+    subdiv* sd = (subdiv*) ipc.gestionnaire.adr;
+    char* mem = (char*) ipc.memoire.adr;
+    boolean res;
+    //Indique que l'on veut ecrire
+    P(&ipc.sem, SEMECRIRE);
+    //Attend que les lecteurs finissent
+    P(&ipc.sem, SEMWAIT);
+    //Ecriture
+    res = add_fdata_subdiv(sd, mem, data);
+    //Libere les semaphores
+    V(&ipc.sem, SEMWAIT);
+    V(&ipc.sem, SEMECRIRE);
+    return res;
+}
+
+boolean remove_shm_data(char* key){
+    //Recup variable globale
+    subdiv* sd = (subdiv*) ipc.gestionnaire.adr;
+    char* mem = (char*) ipc.memoire.adr;
+    boolean res;
+    //Indique que l'on veut ecrire
+    P(&ipc.sem, SEMECRIRE);
+    //Attend que les lecteurs finissent
+    P(&ipc.sem, SEMWAIT);
+    //Ecriture
+    res = remove_data_subdiv(sd, mem, key);
+    //Libere les semaphores
+    V(&ipc.sem, SEMWAIT);
+    V(&ipc.sem, SEMECRIRE);
+    return res;
+}
+
+void show_shm_data(){
+    //Recup variable globale
+    subdiv* sd = (subdiv*) ipc.gestionnaire.adr;
+    char* mem = (char*) ipc.memoire.adr;
+    //Affiche
+    show_data_subdiv(sd, mem);
+}

+ 74 - 0
ipc.h

@@ -0,0 +1,74 @@
+/* 
+ * File:   ipc.h
+ * Author: Arthur Brandao
+ *
+ * Created on 21 décembre 2018
+ */
+
+#ifndef IPC_H
+#define IPC_H
+
+/* --- Include --- */
+#include "constante.h"
+#include "sem.h"
+#include "shm.h"
+#include "subdiv.h"
+
+/* --- Constantes --- */
+#define SEMMUTEX 0 //Mutex d'accès aux variables globales
+#define SEMECRIRE 1 //Sem pour indiquer qu'un processus veut ecrire
+#define SEMWAIT 2 //Sem pour faire attendre l'ecrivain
+
+/* --- Structure --- */
+typedef struct{
+    shared_mem memoire;
+    shared_mem gestionnaire;
+    shared_mem global;
+    semaphore sem;
+}ipc_mysh;
+
+/* --- Extern --- */
+extern ipc_mysh ipc;
+
+/* --- Fonctions --- */
+/**
+ * Création/Récupération SHM et SEM
+ * @param char** Envp pour la création
+ * @return Réussite
+ */
+boolean setup_ipc(char**);
+
+/**
+ * Destruction des SHM et SEM
+ * @return Reussite
+ */
+boolean end_ipc();
+
+/**
+ * Remplace les variables d'une chaine par leurs valeurs
+ * @param char* La chaine à analyser
+ * @return La chaine avec les variables remplacées par leur valeurs
+ */
+char* parse_shm_var(char*);
+
+/**
+ * Ajoute une données dans le segment de mémoire
+ * @param char* Les données à ajouter
+ * @return Reussite
+ */
+boolean add_shm_data(char*);
+
+/**
+ * Supprime une donnée dans le segment de mémoire
+ * @param char* La clef
+ * @return Reussite
+ */
+boolean remove_shm_data(char*);
+
+/**
+ * Affiche les variables dans la mémoire
+ */
+void show_shm_data();
+
+#endif /* IPC_H */
+

+ 18 - 4
makefile

@@ -3,7 +3,7 @@
 #
 
 EXEC = mysh
-OBJETS = error.o str.o parser.o wildcard.o command.o execute.o
+OBJETS = error.o str.o parser.o wildcard.o command.o execute.o sem.o shm.o subdiv.o ipc.o expreg.o variable.o
 NOM_PROJET = mini-shell
 
 #
@@ -67,6 +67,7 @@ clean:
 	@rm -f *~ *#
 	@rm -f $(EXEC)
 	@rm -f dependances
+	@rm -f *.log
 	@echo "Termine."
 
 depend:
@@ -79,6 +80,11 @@ depend:
 	@cat dependances > makefile
 	@rm dependances
 	@echo "Termine."
+	
+rm-log:
+	@echo "Suppression log..."
+	@rm -f *.log
+	@echo "Termine."
 
 #
 # CREATION ARCHIVE
@@ -94,9 +100,17 @@ archive: clean
 # DEPENDANCES
 error.o: error.c str.h error.h
 str.o: str.c str.h
-parser.o: parser.c error.h str.h wildcard.h constante.h parser.h
+parser.o: parser.c error.h str.h wildcard.h constante.h ipc.h sem.h shm.h \
+ subdiv.h variable.h parser.h
 wildcard.o: wildcard.c error.h wildcard.h constante.h
-command.o: command.c error.h str.h parser.h constante.h command.h
+command.o: command.c error.h str.h parser.h constante.h execute.h ipc.h \
+ sem.h shm.h subdiv.h variable.h command.h mysh.h
 execute.o: execute.c error.h execute.h constante.h
+sem.o: sem.c error.h sem.h constante.h
+shm.o: shm.c error.h shm.h constante.h
+subdiv.o: subdiv.c subdiv.h constante.h
+ipc.o: ipc.c ipc.h constante.h sem.h shm.h subdiv.h variable.h
+expreg.o: expreg.c expreg.h constante.h
+variable.o: variable.c str.h expreg.h constante.h variable.h subdiv.h
 mysh.o: mysh.c error.h str.h parser.h constante.h command.h execute.h \
- mysh.h
+ ipc.h sem.h shm.h subdiv.h mysh.h

+ 39 - 91
mysh.c

@@ -19,6 +19,7 @@
 #include "parser.h"
 #include "command.h"
 #include "execute.h"
+#include "ipc.h"
 #include "mysh.h"
 
 /* --- Extern --- */
@@ -27,81 +28,12 @@ extern boolean exitsh;
 extern pid_t active;
 int status_cmd = -1;
 int result_cmd = -1;
-
-/* --- Global --- */
+char base_path[BUFFER_SIZE];
 pid_list pidlist;
-boolean fond = false;
 
+/* --- Globale --- */
 int job = 1;
 
-/* --- Fonctions privées --- */
-void test_write() {
-    char* a = "azerty\n";
-    int tmp = write(1, a, strlen(a));
-    printf("%d\n", tmp);
-}
-
-void test_tmp_file(){
-    int a;
-    FILE* f = tmpfile();
-    printf("F : %d\n", f == NULL);
-    int fd = fileno(f);
-    printf("%d : %ld\n", fd, write(fd, "bonjour", 8));
-    a = lseek(fd, 0L, SEEK_SET);
-    sleep(2);
-    char buf[10];
-    memset(buf, 0 , 10);
-    a = read(fd, buf, 10);
-    printf("%d : %s\n", a, buf);
-    close(fd);
-}
-
-void test(){
-    CommandTab ct;
-    char str[BUFFER_SIZE];
-    int a;
-    //Initialisation structures
-    error_finit("mysh.log");
-    ini_pid_list(&pidlist);
-    
-    //Recup ligne
-    //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);
-    if(a == SHELL_ERR){
-        addserror("Erreur lors du parse de la ligne");
-        error.exit_err();
-    }
-    //Parse les commandes
-    a = parse_all_command(&ct);
-    if(a == SHELL_FAIL){
-        addserror("Erreur lors du parse des commandes");
-        error.exit_err();
-    }
-    //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("Commande en fond : %d\n\n", ct.bck);
-        //Si c'est une commande interne on l'execute
-        if(is_internal_cmd(ct.cmd[i]->name)){
-            show_current_dir(NULL, "\n");
-            printf("Result : %d\n", launch_internal_command(ct.cmd[i]));
-            show_current_dir(NULL, "\n");
-        }
-    }
-    //Nettoyage structures
-    clean_command(&ct);
-    clean_pid(&pidlist);
-    error.exit();
-}
-
 /* --- Fonctions utilitaires --- */
 void show_current_dir(const char* before, const char* after) {
     char buffer[BUFFER_SIZE];
@@ -140,15 +72,28 @@ int get_tmp_file(){
 }
 
 /* --- Main --- */
-int main(int argc, char* argv[]) { 
+int main(int argc, char* argv[], char* envp[]) {
     //Declaration variables
     CommandTab ct;
     int result;
     char line[BUFFER_SIZE], before[BUFFER_SIZE];
     sigset_t sigs_new, sigs_old, sigs_block;
     //Initialisation structures
-    error_finit("mysh.log");
+    error_init();
     ini_pid_list(&pidlist);
+    //Recup chemain de base de l'application
+    if (getcwd(base_path, sizeof (base_path)) == NULL) {
+        addperror("Impossible de récuperer le chemin actuel");
+        error.print("Erreur pendant l'initialisation\n");
+        clean_pid(&pidlist);
+        error.exit_err();
+    }
+    //Lancement ipc
+    if(!setup_ipc(envp)){
+        error.print("Erreur pendant l'initialisation\n");
+        clean_pid(&pidlist);
+        error.exit_err();
+    }
     //Preparation affichage
     sprintf(before, "\x1b[32m%s:\x1b[36m", getlogin());
     //Traitement des signeaux
@@ -161,14 +106,14 @@ int main(int argc, char* argv[]) {
     }
     //On bloque que sigchld
     result = sigaddset(&sigs_new, SIGCHLD);
-    if(result == -1){
+    if(result == ERR){
 	addperror("Impossible d'ajouter SIGCHLD à l'ensemble de signaux");
         error.print("Erreur pendant l'initialisation\n");
         clean_pid(&pidlist);
         error.exit_err();
     }
     result = sigprocmask(SIG_BLOCK, &sigs_new, &sigs_old);
-    if(result == -1){
+    if(result == -ERR){
 	addperror("Impossible de bloquer les signaux de l'ensemble");
         error.print("Erreur pendant l'initialisation\n");
         clean_pid(&pidlist);
@@ -179,11 +124,11 @@ int main(int argc, char* argv[]) {
     //Boucle infini de lecture
     while(!exitsh){
         //On regarde si un fils en fond est mort
-	if(sigpending(&sigs_block) == ERR){
-            addperror("Impossible de recuperer les signaux en attentes");
-	} else if(sigismember(&sigs_block, SIGCHLD)){
-            job--;
-	}
+    	if(sigpending(&sigs_block) == ERR){
+                addperror("Impossible de recuperer les signaux en attentes");
+    	} else if(sigismember(&sigs_block, SIGCHLD)){
+                job--;
+    	}
         //Affichage repertoire
         show_current_dir(before, ">\x1b[0m ");      
         //Lecture ligne
@@ -199,7 +144,6 @@ int main(int argc, char* argv[]) {
             continue;
         }
         //Si aucune commande on passe
-        printf("Nb cmd : %d\n", ct.length);
         if(ct.length == 0){
             clean_command(&ct);
             continue;
@@ -213,11 +157,13 @@ int main(int argc, char* argv[]) {
         }
         //Execute
         result_cmd = run(ct, &status_cmd);
-        printf("Result : %d\n", result_cmd);
         //Vide le resultat du parse de la ligne de commande
         clean_command(&ct);
     }
     //Nettoyage
+    if(!end_ipc()){
+        adderror("Impossible de terminer correctement les IPC");
+    }
     clean_pid(&pidlist);
     error.end();
     return EXIT_SUCCESS;
@@ -227,7 +173,6 @@ int run(CommandTab ct, int* status){
     pid_t pid;
     int result = 0;
     //Si en fond creation d'un fork pour executer les commandes
-    printf("bck : %d\n", ct.bck);
     if(ct.bck){
         pid = fork();
         if(pid == ERR){
@@ -239,7 +184,9 @@ int run(CommandTab ct, int* status){
         if(pid == 0){
             int stat = 0;
             ct.bck = 0;
-            fond = true;
+            //Ignore les sigint
+            signal(SIGINT, SIG_IGN);
+            //Lance commande
             result = run(ct, &stat);
             //Message de fin + retour
             if(result == SHELL_FAIL){
@@ -251,7 +198,7 @@ int run(CommandTab ct, int* status){
         }
         printf("[%d] %d\n", job, pid);
         //Ajout du fils dans la liste des pid
-        add_pid(&pidlist, pid, job++);
+        add_pid(&pidlist, pid, job++, ct.line);
         //Pour le pere c'est fini
         return SHELL_OK;
     }
@@ -379,12 +326,7 @@ void handler(int sig){
     pid_node* pn;
     //Repositionne le gestionnaire (Ne marche plus apres 1 utilisation)
     signal(SIGINT, handler);
-    //Si on est en fond on est non concerné
-    if(fond){
-        return;
-    }
     //Si il y a un process actif on le coupe
-    printf("Active : %d\n", active);
     if(active != -1){
         if(kill(active, SIGINT) == ERR){
             addperror("Impossible de tuer le processus en cours");
@@ -394,10 +336,13 @@ void handler(int sig){
     }
     //Sinon demande comfirmation pour finir le programme
     while(reponse != 'o' && reponse != 'O' && reponse != 'n' && reponse != 'N'){
+        //Recup la valeur
         printf("Voulez vous vraiment quitter ? [O/N] ");
-        if(scanf("%c", &reponse) == 0){
+        if((reponse = getchar()) == EOF){
             reponse = ' ';
         }
+        //Vide l'entrée standard
+        while(getchar() != '\n');
     }
     //Si oui
     if(reponse == 'n' || reponse == 'N'){
@@ -412,6 +357,9 @@ void handler(int sig){
         pn = pn->next;
     }
     //Termine l'execution
+    if(!end_ipc()){
+        adderror("Impossible de terminer correctement les IPC");
+    }
     clean_pid(&pidlist);
     error.exit();
 }

+ 7 - 1
mysh.h

@@ -11,6 +11,8 @@
 /* --- Extern --- */
 extern int status_cmd;
 extern int result_cmd;
+extern char base_path[];
+extern pid_list pidlist;
 
 /* --- Fonctions --- */
 /**
@@ -23,10 +25,14 @@ void show_current_dir(const char*, const char*);
 /**
  * Execute l'ensemble des commandes d'une ligne
  * @param CommandTab La ligne de commande parser
- * @return 
+ * @return Result
  */
 int run(CommandTab, int*);
 
+/**
+ * Gestionnaire de signaux
+ * @param int Le type de singal reçu
+ */
 void handler(int);
 
 #endif /* MYSH_H */

+ 14 - 1
parser.c

@@ -15,6 +15,8 @@
 #include "error.h"
 #include "str.h"
 #include "wildcard.h"
+#include "ipc.h"
+#include "variable.h"
 #include "parser.h"
 
 /* --- Extern --- */
@@ -553,7 +555,7 @@ int parse_line(CommandTab* ct, char* line){
 int parse_command(Command* c){
     //Declaration variable
     int length, nbWildcard = 0, res;
-    char* cmd, **wildcardTab;
+    char* cmd, * str, **wildcardTab;
     //Parse les redirections
     length = set_redirection(c);
     if(length == SHELL_ERR || length == 0){
@@ -565,6 +567,17 @@ int parse_command(Command* c){
     strncpy(cmd, c->cmd, length);
     //Split la commande
     split_command(c, cmd);
+    //Remplace variables
+    for(int i = 0; i < c->argc; i++){
+        str = parse_local_var(c->argv[i]);
+        free(c->argv[i]);
+        c->argv[i] = str;
+    }
+    for(int i = 0; i < c->argc; i++){
+        str = parse_shm_var(c->argv[i]);
+        free(c->argv[i]);
+        c->argv[i] = str;
+    }
     //Analyse wildcard
     for(int i = 0; i < c->argc; i++){
         //Regarde si il faut remplacer l'argument par une suite de fichier

+ 140 - 0
sem.c

@@ -0,0 +1,140 @@
+#define _XOPEN_SOURCE
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h> /* Constante option */
+#include <errno.h>
+#include "error.h"
+#include "sem.h"
+
+/* --- Extern --- */
+extern int errno;
+
+/* --- Fonctions privées --- */
+/**
+ * Initialise les semaphores
+ * @param semaphore* Le tableau de semaphore
+ * @param int La taille du tableau
+ * @param int* Valeur à initialiser
+ * @return boolean Reussite
+ */
+boolean ini_sem(semaphore* sem, int size, int* iniVal) {
+    /* Initialisation des valeurs */
+    for(int i = 0; i < size; i++){
+        if(semctl(sem->id, i, SETVAL, iniVal[i]) == ERR){
+            addperror("Impossible d'initialiser le tableau de semaphore");
+            return false;
+        }
+    }
+    /* Retour */
+    return true;
+}
+
+/* --- Fonctions publiques --- */
+boolean create_sem(semaphore* sem, int code, int nb, int* iniVal) {
+    int id;
+    /* Création du tableau */
+    key_t key = ftok(IPCKEYPATH, code);
+    if(key == ERR){
+        addperror("Impossible de générer la clef");
+        return false;
+    }
+    id = semget(key, nb, S_IRUSR | S_IWUSR | IPC_CREAT | IPC_EXCL);
+    if (id == ERR) {
+        /* Si le tableau existe deja */
+        if (errno == EEXIST) {
+            adderror("Le tableau de sémaphore existe deja, tentaive de récupération");
+            return get_sem(sem, code);
+        }
+        /* Sinon erreur */
+        addperror("Impossible de créer le tableau de sémaphore");
+        return false;
+    }
+    /* Paramétrage de la structure */
+    sem->id = id;
+    sem->key = key;
+    sem->nb = nb;
+    /* Initialise semaphore */
+    return ini_sem(sem, nb, iniVal);
+}
+
+boolean get_sem(semaphore* sem, int code) {
+    int id;
+    struct semid_ds sem_buf;
+    /* Création du tableau */
+    key_t key = ftok(IPCKEYPATH, code);
+    if(key == ERR){
+        addperror("Impossible de générer la clef");
+        return false;
+    }
+    id = semget(key, 0, S_IRUSR | S_IWUSR);
+    if (id == ERR) {
+        /* Sinon erreur */
+        addperror("Impossible de récupèrer le tableau de sémaphore");
+        return false;
+    }
+    /* Récupération du nombre de semaphore */
+    if (semctl(id, 0, IPC_STAT, &sem_buf) == ERR) {
+        addperror("Impossible de récupèrer les informations du tableau de sémaphore");
+        return false;
+    }
+    /* Paramétrage de la structure */
+    sem->id = id;
+    sem->key = key;
+    sem->nb = sem_buf.sem_nsems;
+    /* Retour */
+    return true;
+}
+
+boolean P(semaphore* sem, int num) {
+    struct sembuf action;
+    /* Le num valide */
+    if (num < 0 || num > (sem->nb - 1)) {
+        adderror("Index tableau semaphore invalide");
+        return false;
+    }
+    /* Parametre sembuf */
+    action.sem_num = num;
+    action.sem_op = -1;
+    /* Puis je */
+    if (semop(sem->id, &action, 1) == ERR) {
+        addperror("Impossible d'effectuer P");
+        return false;
+    }
+    return true;
+}
+
+boolean V(semaphore* sem, int num) {
+    struct sembuf action;
+    /* Le num valide */
+    if (num < 0 || num > (sem->nb - 1)) {
+        adderror("Index tableau semaphore invalide");
+        return false;
+    }
+    /* Parametre sembuf */
+    action.sem_num = num;
+    action.sem_op = 1;
+    /* Vas y */
+    if (semop(sem->id, &action, 1) == ERR) {
+        addperror("Impossible d'effectuer V");
+        return false;
+    }
+    return true;
+}
+
+boolean delete_sem(semaphore* sem) {
+    /* Suppr */
+    if (semctl(sem->id, 0, IPC_RMID) == ERR) {
+        addperror("Impossible de supprimer le tableau de semaphore");
+        return false;
+    }
+    /* Reset struct */
+    sem->id = 0;
+    sem->key = 0;
+    sem->nb = 0;
+    return true;
+}
+
+int get_sem_value(semaphore* sem, int num){
+    return semctl(sem->id, num, GETVAL);
+}

+ 71 - 0
sem.h

@@ -0,0 +1,71 @@
+#ifndef SEM_H
+#define SEM_H
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include "constante.h"
+
+/* --- Structures --- */
+
+typedef struct{
+	/* Id retourner par semget */
+	int id;
+	/* Clef d'acces au semaphores */
+	key_t key;
+	/* Nombre de semaphore */
+	int nb;
+}semaphore;
+
+/* --- Fonctions --- */
+
+/**
+ * Creation d'un tableau de semaphores
+ * @param semaphore* Le tableau de semaphore
+ * @param int La clef
+ * @param int Le nombre semaphores
+ * @param int* Valeur à initialiser
+ * @return boolean Reussite
+ */
+boolean create_sem(semaphore*, int, int, int*);
+
+/**
+ * Récuperation d'un tableau de semaphores
+ * @param semaphore* Le tableau de semaphore
+ * @param int La clef
+ * @return boolean Reussite
+ */
+boolean get_sem(semaphore*, int);
+
+/**
+ * Demande l'acces et decremente le semaphore (Puis je)
+ * @param semaphore* Le tableau de semaphore
+ * @param int Le numero de la semaphore
+ * @return boolean Reussite
+ */
+boolean P(semaphore*, int);
+
+/**
+ * Augmente le compteur d'une semaphore (Vas y)
+ * @param semaphore* Le tableau de semaphore
+ * @param int Le numero de la semaphore
+ * @return boolean Reussite
+ */
+boolean V(semaphore*, int);
+
+/**
+ * Supprime un tableau de semaphores
+ * @param semaphore* Le tableau de semaphore
+ * @return boolean Reussite
+ */
+boolean delete_sem(semaphore*);
+
+/**
+ * Récupère la valeur d'un semaphore
+ * @param semaphore* Le tableau de semaphore
+ * @param int Le numero du semaphore dans le tableau
+ * @return int La valeur actuel du semaphore
+ */
+int get_sem_value(semaphore*, int);
+
+#endif

+ 126 - 0
shm.c

@@ -0,0 +1,126 @@
+/* 
+ * File:   shm.c
+ * Author: Arthur Brandao
+ *
+ * Created on 21 décembre 2018
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h> /* Constante option */
+#include <errno.h>
+#include "error.h"
+#include "shm.h"
+
+/* --- Extern --- */
+extern int errno;
+
+/* --- Fonctions prviées --- */
+
+/**
+ * Indique si il reste des processus utilsant le segment
+ * @param shared_mem* La mémoire partagée
+ * @return Peut ont supprimer ou non
+ */
+boolean can_delete_shm(shared_mem* shm){
+    struct shmid_ds buf;
+    /* Recup les infos de la mémoire */
+    if (shmctl(shm->id, IPC_STAT, &buf) == ERR) {
+        addperror("Impossible de récupérer les données du segment");
+        return false;
+    }
+    /* Verifie qu'il n'y a plus d'utilisateur actif */
+    return buf.shm_nattch == 0;
+}
+
+/* --- Fonctions publiques --- */
+boolean create_shm(shared_mem* shm, int code, int size) {
+    int id;
+    void* adr;
+    /* Création de la shm */
+    key_t key = ftok(IPCKEYPATH, code);
+    if (key == ERR) {
+        addperror("Impossible de générer la clef");
+        return false;
+    }
+    id = shmget(key, size, S_IRUSR | S_IWUSR | IPC_CREAT | IPC_EXCL);
+    if (id == ERR) {
+        /* Si erreur existe deja appel get_shm */
+        if (errno == EEXIST) {
+            adderror("Le segment existe deja, tentative de récupération");
+            return get_shm(shm, code, size);
+        } else {
+            addperror("Impossible de créer la mémoire partagée");
+            return false;
+        }
+    }
+    /* On attache */
+    adr = shmat(id, NULL, 0);
+    if (adr == (void*) ERR) {
+        addperror("Impossible d'attacher le segment");
+        return false;
+    }
+    /* Initialisation de la structure */
+    shm->id = id;
+    shm->key = key;
+    shm->size = size;
+    shm->adr = adr;
+    return true;
+}
+
+boolean get_shm(shared_mem* shm, int code, int size) {
+    int id;
+    void* adr;
+    /* Création de la shm */
+    key_t key = ftok(IPCKEYPATH, code);
+    if (key == ERR) {
+        addperror("Impossible de générer la clef");
+        return false;
+    }
+    id = shmget(key, size, S_IRUSR | S_IWUSR);
+    if (id == ERR) {
+        addperror("Impossible de récupérer la mémoire partagée");
+        return false;
+    }
+    /* On attache */
+    adr = shmat(id, NULL, 0);
+    if (adr == (void*) ERR) {
+        addperror("Impossible d'attacher le segment");
+        return false;
+    }
+    /* Initialisation de la structure */
+    shm->id = id;
+    shm->key = key;
+    shm->size = size;
+    shm->adr = adr;
+    return true;
+}
+
+boolean unset_shm(shared_mem* shm){
+	/* On détache la shm */
+	if(shmdt(shm->adr) == ERR){
+		perror("Erreur lors du détachement de la mémoire ");
+		return false;
+	}
+	shm->adr = NULL;
+        shm->size = 0;
+	/* Retour */
+	return true;
+}
+
+boolean delete_shm(shared_mem* shm) {
+    /* Regarde si on peut supprimer */
+    if(!can_delete_shm(shm)){
+        adderror("Des processus utilisent encore le segment");
+        return false;
+    }
+    /* Supprime */
+    if (shmctl(shm->id, IPC_RMID, 0) == ERR) {
+        addperror("Impossible de supprimer le segment");
+        return false;
+    }
+    /* Reset la structure */
+    shm->id = 0;
+    shm->key = 0;
+    return true;
+}

+ 63 - 0
shm.h

@@ -0,0 +1,63 @@
+/* 
+ * File:   shm.h
+ * Author: Arthur Brandao
+ *
+ * Created on 21 décembre 2018
+ */
+
+#ifndef SHM_H
+#define SHM_H
+
+/* --- Include --- */
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "constante.h"
+
+/* --- Structure --- */
+typedef struct{
+    //Id de shmget
+    int id;
+    //Clef d'accés à la shm
+    key_t key;
+    //Taille de la zone mémoire
+    int size;
+    //Pointeur vers la zone mémoire
+    void* adr;
+}shared_mem;
+
+/* --- Fonctions --- */
+/**
+ * Création d'un segment de mémoire partagée
+ * @param shared_mem* La mémoire partagée
+ * @param int La clef
+ * @param int La taille de la zone
+ * @return boolean Reussite
+ */
+boolean create_shm(shared_mem*, int, int);
+
+/**
+ * Création d'un segment de mémoire partagée
+ * @param shared_mem* La mémoire partagée
+ * @param int La clef
+ * @param int La taille de la zone
+ * @return boolean Reussite
+ */
+boolean get_shm(shared_mem*, int, int);
+
+/**
+ * Retire le segment de mémoire partagée
+ * @param shared_mem* La mémoire partagée
+ * @return boolean Reussite
+ */
+boolean unset_shm(shared_mem*);
+
+/**
+ * Supprime le segment de memoire partagée
+ * @param shared_mem* La mémoire partagée
+ * @return boolean Reussite
+ */
+boolean delete_shm(shared_mem*);
+
+#endif /* SHM_H */
+

+ 322 - 0
subdiv.c

@@ -0,0 +1,322 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "subdiv.h" 
+
+/* --- Fonctions privées traitement valeurs --- */
+/**
+ * Indique si une chaine est la clef d'un noeud
+ * @param node* Le noeud
+ * @param char* La mémoire
+ * @param char* La clef
+ * @return true - Oui/false - Non
+ */
+boolean is_key(node* n, char* mem, char* key) {
+    int i, length = strlen(key);
+    //Verif que la clef correspond à celle en param
+    for (i = 0; i < length; i++) {
+        if (mem[i + n->start] != key[i]) {
+            return false;
+        }
+    }
+    //Verif que le caractere suivant est bien un =
+    if (mem[i + n->start] != '=') {
+        return false;
+    }
+    return true;
+}
+
+/**
+ * Cherche une clef
+ * @param subdiv* Le gestionnaire de mémoire par subdivision
+ * @param char* La mémoire
+ * @param char* La clef
+ * @return La node correspondante ou NULL si introuvable
+ */
+node* find_key(subdiv* sd, char* mem, char* key) {
+    int length = strlen(key) + 2; //Clef + = + taille min mot
+    node* n = NULL;
+    //Cherche la clef
+    for (int i = 0; i < MEM_SIZE / 2; i++) {
+        if (sd->use[i] && sd->mem[i].type == MEMSET && sd->mem[i].length >= length) {
+            //Regarde si la clef correspond
+            if (is_key(&sd->mem[i], mem, key)) {
+                n = &sd->mem[i];
+                break;
+            }
+        }
+    }
+    return n;
+}
+
+/**
+ * Récupère la valeur d'un noeid
+ * @param node* La noeud
+ * @param char* La mémoire
+ */
+char* parse_val(node* n, char* mem) {
+    int pos = 0;
+    //Cherche la postion du =
+    while (mem[pos + n->start] != '=') {
+        pos++;
+    }
+    pos++;
+    //Creation chaine
+    char* str = mem + n->start + pos;
+    char* val = malloc(sizeof (char) * (n->length - pos + 1));
+    memset(val, 0, n->length - pos + 1);
+    strncpy(val, str, n->length - pos);
+    //Retour
+    return val;
+}
+
+/* --- Fonctions privées nodes --- */
+
+boolean div_node(subdiv* sd, node* n) {
+    node* newn = NULL;
+    int i;
+    //Verif que la node à diviser est bien libre
+    if (n->type != MEMEMPTY) {
+        return false;
+    }
+    //Cherche une node libre
+    for (i = 0; i < MEM_SIZE; i++) {
+        if (sd->use[i] == 0) {
+            newn = &sd->mem[i];
+            break;
+        }
+    }
+    //Plus de place
+    if (newn == NULL) {
+        return false;
+    }
+    //Setup node
+    newn->index = i;
+    newn->start = n->start + (n->length / 2);
+    newn->end = n->end;
+    newn->length = n->length / 2;
+    newn->type = MEMEMPTY;
+    newn->prev = n->index;
+    newn->next = n->next;
+    //Modifie node suivant la nouvelle
+    if (n->next != -1 || n->next == n->index) {
+        sd->mem[n->next].prev = newn->index;
+    }
+    //Modifie node origine
+    n->end = n->start + (n->length / 2);
+    n->length /= 2;
+    n->next = newn->index;
+    //Indique que la node est utilisé
+    sd->use[i] = true;
+    return true;
+}
+
+boolean fusion_node(subdiv* sd, node* n) {
+    //Verif que la node et la node suivante sont vide
+    if (!(n->type == MEMEMPTY && n->next != -1 && sd->mem[n->next].type == MEMEMPTY)) {
+        return false;
+    }
+    node* n2 = &sd->mem[n->next];
+    //Verif qu'elles ont la meme taille
+    if (n->length != n2->length) {
+        return false;
+    }
+    //Met à jour la node
+    n->end = n2->end;
+    n->length *= 2;
+    n->next = n2->next;
+    if (n2->next != -1 || n2->next == n2->index) {
+        sd->mem[n2->next].prev = n->index;
+    }
+    //Indique que l'autre node n'est plus utilisée
+    sd->use[n2->index] = false;
+    return true;
+}
+
+/* --- Fonctions publiques --- */
+
+void ini_subdiv(subdiv* sd) {
+    sd->mem[0] = (node){0, 0, MEM_SIZE, MEM_SIZE, MEMEMPTY, -1, -1};
+    sd->use[0] = true;
+    for (int i = 1; i < MEM_SIZE / 2; i++) {
+        sd->use[i] = false;
+    }
+}
+
+boolean add_data_subdiv(subdiv* sd, char* mem, char* key, char* data) {
+    //Recup taille data
+    int length = strlen(data) + strlen(key) + 1;
+    //Cherche un espace ou mettre la données
+    node* n = &sd->mem[0];
+    while (n != NULL) {
+        if (n->type == MEMEMPTY && n->length >= length) {
+            break;
+        }
+        //Charge le prochain noeud
+        if(n->next == -1 || n->next == n->index){
+            n = NULL;
+        } else {
+            n = &sd->mem[n->next];
+        }
+    }
+    //Si plus de place
+    if (n == NULL) {
+        return false;
+    }
+    //Si on peut diviser par deux la place libre et stocker dedans
+    if ((n->length / 2) >= length) {
+        //On divise la zone en 2
+        if (!div_node(sd, n)) {
+            return false;
+        }
+        return add_data_subdiv(sd, mem, key, data);
+    }
+    //Genere chaine à mettre en mémoire
+    char* str = malloc(sizeof (char) * (length + 1));
+    memset(str, 0, length + 1);
+    snprintf(str, length + 1, "%s=%s", key, data);
+    //On maj la node
+    n->type = MEMSET;
+    n->length = length;
+    //On met dans la mémoire
+    for (int i = 0; i < length; i++) {
+        mem[i + n->start] = str[i];
+    }
+    //Nettoyage
+    free(str);
+    return true;
+}
+
+boolean add_fdata_subdiv(subdiv* sd, char* mem, char* data) {
+    //Recup taille data
+    int length = strlen(data);
+    //Cherche un espace ou mettre la données
+    node* n = &sd->mem[0];
+    while (n != NULL) {
+        if (n->type == MEMEMPTY && n->length >= length) {
+            break;
+        }
+        //Charge le prochain noeud
+        if(n->next == -1 || n->next == n->index){
+            n = NULL;
+        } else {
+            n = &sd->mem[n->next];
+        }
+    }
+    //Si plus de place
+    if (n == NULL) {
+        return false;
+    }
+    //Si on peut diviser par deux la place libre et stocker dedans
+    if ((n->length / 2) >= length) {
+        //On divise la zone en 2
+        if (!div_node(sd, n)) {
+            return false;
+        }
+        return add_fdata_subdiv(sd, mem, data);
+    }
+    //On maj la node
+    n->type = MEMSET;
+    n->length = length;
+    //On met dans la mémoire
+    for (int i = 0; i < length; i++) {
+        mem[i + n->start] = data[i];
+    }
+    return true;
+}
+
+char* get_data_subdiv(subdiv* sd, char* mem, char* key) {
+    node* n = find_key(sd, mem, key);
+    //Si pas trouvé la clef
+    if (n == NULL) {
+        return NULL;
+    }
+    //Recup valeur
+    return parse_val(n, mem);
+}
+
+boolean remove_data_subdiv(subdiv* sd, char* mem, char* key) {
+    node* n = find_key(sd, mem, key);
+    //Si pas trouvé la clef
+    if (n == NULL) {
+        return false;
+    }
+    //Marque la node comme vide
+    n->length = n->end - n->start;
+    n->type = MEMEMPTY;
+    //Tente la fusion des noeuds (Algo imparfait)
+    n = &sd->mem[0];
+    while (n != NULL) {
+        //On fusionne avec celui d'après si celui d'avant à une taille différente
+        if (n == &sd->mem[0]) {
+            if (fusion_node(sd, n)) {
+                n = &sd->mem[0];
+            } else {
+                //Charge le prochain noeud
+                if(n->next == -1 || n->next == n->index){
+                    n = NULL;
+                } else {
+                    n = &sd->mem[n->next];
+                }
+            }
+        } else if (sd->mem[n->prev].length != n->length) {
+            if (fusion_node(sd, n)) {
+                n = &sd->mem[0];
+            } else {
+                //Charge le prochain noeud
+                if(n->next == -1 || n->next == n->index){
+                    n = NULL;
+                } else {
+                    n = &sd->mem[n->next];
+                }
+            }
+        } else {
+            //Charge le prochain noeud
+            if(n->next == -1 || n->next == n->index){
+                n = NULL;
+            } else {
+                n = &sd->mem[n->next];
+            }
+        }
+    }
+    return true;
+}
+
+void show_subdiv(subdiv* sd) {
+    node* n = &sd->mem[0];
+    while (n != NULL) {
+        printf("Deb : %d, Fin : %d, Length : %d, Real length : %d, Use : %d\n", n->start, n->end, n->length, n->end - n->start, (int) n->type);
+        //Charge le prochain noeud
+        if(n->next == -1){
+            n = NULL;
+        } else {
+            n = &sd->mem[n->next];
+        }
+    }
+}
+
+void show_data_subdiv(subdiv* sd, char* mem){
+    boolean vide = true;
+    node* n = &sd->mem[0];
+    while (n != NULL) {
+        if(n->type == MEMSET){
+            vide = false;
+            char* str = malloc(sizeof(char) * (n->length + 1));
+            char* deb = mem + n->start;
+            memset(str, 0, n->length + 1);
+            strncpy(str, deb, n->length);
+            printf("%s\n", str);
+            free(str);
+        }
+        //Charge le prochain noeud
+        if(n->next == -1 || n->next == n->index){
+            n = NULL;
+        } else {
+            n = &sd->mem[n->next];
+        }
+    }
+    //Si vide
+    if(vide){
+        printf("Aucune variable en mémoire\n");
+    }
+}

+ 85 - 0
subdiv.h

@@ -0,0 +1,85 @@
+#ifndef subdiv_h
+#define subdiv_h
+
+/* --- Include --- */
+#include "constante.h"
+
+/* --- Constante --- */
+#define MEMEMPTY 0
+#define MEMSET 1
+
+/* --- Structures --- */
+typedef struct node node;
+struct node{
+	int index; //Index dans le tableau mem de subdiv
+	int start; //Pos debut (incluse)
+	int end; //Pos fin (non incluse)
+	int length; //Taille réellement utilisée
+	unsigned char type;
+	int prev; //Position de noeud d'avant
+	int next; //Position du prochain noeud
+};
+
+typedef struct{
+	node mem[MEM_SIZE / 2];
+	boolean use[MEM_SIZE / 2];
+}subdiv;
+
+/* --- Fonctions --- */
+/**
+ * Initialise la structure de gestion
+ * @param subdiv* Le gestionnaire de mémoire par subdivision
+ */
+void ini_subdiv(subdiv*);
+
+/**
+ * Ajoute une donnée dans la mémoire
+ * @param subdiv* Le gestionnaire de mémoire par subdivision
+ * @param char* La mémoire
+ * @param char* La clef
+ * @param char* La valeur
+ * @return Réussite
+ */
+boolean add_data_subdiv(subdiv*, char*, char*, char*);
+
+/**
+ * Ajoute une donnée déjà formatée sour la forme clef=valeur en mémoire
+ * @param subdiv* Le gestionnaire de mémoire par subdivision
+ * @param char* La mémoire
+ * @param char* La donnée
+ * @return Réussite
+ */
+boolean add_fdata_subdiv(subdiv*, char*, char*); //add formated data
+
+/**
+ * Récupère une donnée dans la mémoire
+ * @param subdiv* Le gestionnaire de mémoire par subdivision
+ * @param char* La mémoire
+ * @param char* La clef
+ * @return Réussite
+ */
+char* get_data_subdiv(subdiv*, char*, char*);
+
+/**
+ * Supprime une donnée de la mémoire
+ * @param subdiv* Le gestionnaire de mémoire par subdivision
+ * @param char* La mémoire
+ * @param char* La clef
+ * @return Réussite
+ */
+boolean remove_data_subdiv(subdiv*, char*, char*);
+
+/**
+ * Affiche la répartition de la mémoire
+ * @param subdiv* Le gestionnaire de mémoire par subdivision
+ */
+void show_subdiv(subdiv*);
+
+/**
+ * Affiche toutes les données de la mémoire
+ * @param subdiv* Le gestionnaire de mémoire par subdivision
+ * @param char* La mémoire
+ */
+void show_data_subdiv(subdiv*, char*);
+
+#endif 

+ 164 - 0
variable.c

@@ -0,0 +1,164 @@
+/* 
+ * File:   variable.c
+ * Author: Arthur Brandao
+ *
+ * Created on 21 décembre 2018
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "str.h"
+#include "expreg.h"
+#include "variable.h"
+
+/* --- Extern --- */
+subdiv localsd;
+char localmem[MEM_SIZE];
+boolean ini = false;
+
+/* --- Fonctions publiques --- */
+char* parse_var(char* s, subdiv* sd, char* mem) {
+    expreg er;
+    int length, deb, fin, fin2 = 0, compteur = 0, index = 0;
+    boolean first = true;
+    char* str, * newstr;
+    //Cherche le nombre de clefs dans la chaine
+    length = strlen(s);
+    ini_expreg(&er, s, "(\\$[[:alnum:]_]+)");
+    while ((str = get_match_expreg(&er, &deb, &fin)) != NULL) {
+        //1er tour
+        if (first) {
+            //Si il y a du texte avant 
+            if (deb != 0) {
+                compteur++;
+            }
+            compteur++;
+            //Garde en memoire la pos de fin
+            fin2 = fin;
+            first = false;
+        }            
+        //Autre tours
+        else {
+            //Si il y a eu du texte entre les deux correspondances
+            if (deb != fin2) {
+                compteur++;
+            }
+            compteur++;
+            //Garde en memoire la pos de fin
+            fin2 = fin;
+        }
+        free(str);
+    }
+    //Si on n'est pas à la fin
+    if (fin2 != length) {
+        compteur++;
+    }
+    clean_expreg(&er);
+    //Création tableau
+    char** tab = malloc(sizeof(char*) * compteur);
+    //Sécoupe la chaine
+    first = true;
+    ini_expreg(&er, s, "(\\$[[:alnum:]_]+)");
+    while ((str = get_match_expreg(&er, &deb, &fin)) != NULL) {
+        //1er tour
+        if (first) {
+            //Si il y a du texte avant 
+            if (deb != 0) {
+                tab[index] = malloc(sizeof(char) * (deb + 1));
+                memset(tab[index], 0, deb + 1);
+                strncpy(tab[index], s, deb);
+                index++;
+            }
+            tab[index] = malloc(sizeof(char) * (fin - deb + 1));
+            memset(tab[index], 0, fin - deb + 1);
+            strncpy(tab[index], s + deb, fin - deb);
+            index++;
+            //Garde en memoire la pos de fin
+            fin2 = fin;
+            first = false;
+        }            
+        //Autre tours
+        else {
+            //Si il y a eu du texte entre les deux correspondances
+            if (deb != fin2) {
+                tab[index] = malloc(sizeof(char) * (deb - fin2 + 1));
+                memset(tab[index], 0, deb - fin2 + 1);
+                strncpy(tab[index], s + fin2, deb - fin2);
+                index++;
+            }
+            tab[index] = malloc(sizeof(char) * (fin - deb + 1));
+            memset(tab[index], 0, fin - deb + 1);
+            strncpy(tab[index], s + deb, fin - deb);
+            index++;
+            //Garde en memoire la pos de fin
+            fin2 = fin;
+        }
+        free(str);
+    }
+    //Si on n'est pas à la fin
+    if (fin2 != length) {
+        tab[index] = malloc(sizeof(char) * (length - fin2 + 1));
+        memset(tab[index], 0, length - fin2 + 1);
+        strncpy(tab[index], s + fin2, length - fin2);
+        index++;
+    }
+    clean_expreg(&er);
+    //Remplace les clef par leurs valeurs
+    for(int i = 0; i < compteur; i++){
+        if(tab[i][0] == '$'){
+            char* val = get_data_subdiv(sd, mem, tab[i] + 1);
+            if(val != NULL){
+                free(tab[i]);
+                tab[i] = val;
+            }
+        }
+    }
+    //Reconstruit la chaine
+    length = 0;
+    for(int i = 0; i < compteur; i++){
+        length += strlen(tab[i]);
+    }
+    newstr = malloc(sizeof(char) * (length + 1));
+    memset(newstr, 0, length + 1);
+    index = 0;
+    for(int i = 0; i < compteur; i++){
+        length = strlen(tab[i]);
+        for(int j = 0; j < length; j++){
+            newstr[index] = tab[i][j];
+            index++;
+        }
+        free(tab[i]);
+    }
+    free(tab);
+    return newstr;
+}
+
+char* parse_local_var(char* str){
+    if(!ini){
+        int length = strlen(str) + 1;
+        char* newstr = malloc(sizeof(char) * length);
+        memset(newstr, 0, length);
+        strncpy(newstr, str, length - 1);
+        return newstr;
+    }
+    return parse_var(str, &localsd, localmem);
+}
+
+boolean add_local_data(char* data){
+    if(!ini){
+        ini_subdiv(&localsd);
+        ini = true;
+    }
+    return add_fdata_subdiv(&localsd, localmem, data);
+}
+
+boolean remove_local_data(char* key){
+    if(!ini){
+        return false;
+    }
+    return remove_data_subdiv(&localsd, localmem, key);
+}
+
+void show_local_data(){
+    show_data_subdiv(&localsd, localmem);
+}

+ 54 - 0
variable.h

@@ -0,0 +1,54 @@
+/* 
+ * File:   variable.h
+ * Author: Arthur Brandao
+ *
+ * Gestion des variables locales
+ * 
+ * Created on 21 décembre 2018
+ */
+
+#ifndef VARIABLE_H
+#define VARIABLE_H
+
+/* --- Include --- */
+#include "constante.h"
+#include "subdiv.h"
+
+/* --- Fonctions --- */
+/**
+ * Remplace les variables par leur valeur dans une chaine
+ * @param char* La chaine à traiter
+ * @param subdiv* Le gestionnaire de memoir epar subdivision ou sont stocker les valeur
+ * @param char* La mémoire ou sont les valeurs
+ * @return La chaine avec les valeurs replacées
+ */
+char* parse_var(char*, subdiv*, char*);
+
+/**
+ * Remplace les variables d'une chaine par leurs valeurs
+ * @param char* La chaine à analyser
+ * @return La chaine avec les variables remplacées par leur valeurs
+ */
+char* parse_local_var(char*);
+
+/**
+ * Ajoute une données dans la mémoire locale
+ * @param char* Les données à ajouter
+ * @return Reussite
+ */
+boolean add_local_data(char*);
+
+/**
+ * Supprime une donnée dans la mémoire locale
+ * @param char* La clef
+ * @return Reussite
+ */
+boolean remove_local_data(char*);
+
+/**
+ * Affiche les variables dans la mémoire
+ */
+void show_local_data();
+
+#endif /* VARIABLE_H */
+