|
@@ -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){
|