/* * File: command.c * Author: Arthur Brandao * * Created on 9 novembre 2018 */ #define _POSIX_C_SOURCE 200112L #include #include #include #include "command.h" #include "error.h" #include "str.h" #include "parser.h" #include "execute.h" #include "ipc.h" #include "variable.h" /* --- Extern --- */ extern Error error; extern pid_t last; int status_cmd = -1; int result_cmd = -1; char base_path[BUFFER_SIZE]; pid_list pidlist; char* cmdlist[] = { "cd", "exit", "status", "setenv", "unsetenv", "set", "unset", "myls", "myps", "myjobs", NULL }; boolean exitsh = false; /* --- Fonctions publiques --- */ void ini_pid_list(pid_list* pl) { pl->first = NULL; pl->last = NULL; } 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; pl->first = pn; pl->last = pn; } else { pn->prev = pl->last; pl->last->next = pn; pl->last = pn; } return pn; } pid_node* search_pid(pid_list* pl, pid_t pid) { pid_node* pn = pl->first; while (pn != NULL) { if (pn->pid == pid) { return pn; } pn = pn->next; } return NULL; } 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; pn->next->prev = pn->prev; } //Free free(pn); } 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; } pl->first = NULL; pl->last = NULL; } boolean is_internal_cmd(const char* cmd) { //Parcours tableau pour trouver correspondance for (int i = 0; cmdlist[i] != NULL; i++) { if (strncmp(cmd, cmdlist[i], strlen(cmd)) == 0) { return true; } } return false; } int launch_internal_command(Command* cmd) { int result, length = strlen(cmd->name) + 1; //cd 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; } } /* --- Commandes --- */ int cd(int argc, char** argv) { //Si trop d'arguments if (argc > 2) { error.print("too many arguments : 1 required, %d given\n", argc - 1); return EXIT_FAILURE; } else { //Si aucun argument on va à la racine if (argc == 1) { if (chdir("/") == ERR) { addperror("Erreur chdir()"); return EXIT_FAILURE; } } //Sinon on va dans le dossier indiqué par l'utilisateur else { if (chdir(argv[1]) == ERR) { error.print("path does not exist\n"); return EXIT_FAILURE; } } } return EXIT_SUCCESS; //show_current_dir("current working directory is: ", "\n"); } int exit_sh(int argc, char** argv) { exitsh = true; return EXIT_SUCCESS; } 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) { 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); } 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); } 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; }