/** @file */ #include "parsing.h" #include "disk.h" #include "exec.h" #include "struct.h" #include #include #include #include /** * @brief Attend que l'utilisateur appuie sur entrée pour récupérer la ligne * écrite puis la renvoi * @return La ligne écrite par l'utilisateur */ char *read_line() { char c; int i = 0; int j = 1; char *buffer = malloc(j * BUFSIZE * sizeof(char)); if (buffer == NULL) { dprintf(STDERR_FILENO, "Line read buffer allocation error !"); exit(EXIT_FAILURE); } while (1) { c = getchar(); if (i == BUFSIZE - 1) { j++; buffer = realloc(buffer, j * BUFSIZE); } if (c == EOF || c == '\n') { buffer[i] = '\0'; return buffer; } else { buffer[i] = c; } i++; } } /** * @brief * @param char *line la ligne à parser * @return la liste des arguments de la commande */ command **split_line(char *line) { char **args = malloc(BUFSIZE * sizeof(char *)); int i = 0; if (args == NULL) { dprintf(STDERR_FILENO, "Allocation error"); exit(EXIT_FAILURE); } char *token = strtok(line, " "); while (token != NULL) { args[i] = token; i++; token = strtok(NULL, " "); } args[i++] = NULL; if (args[0] == NULL) { return NULL; } command **cmd_lines = malloc(sizeof(command *)); if (cmd_lines == NULL) { dprintf(STDERR_FILENO, "Command struct allocation error !"); exit(EXIT_FAILURE); } cmd_lines[0] = malloc(sizeof(command)); cmd_lines[0]->argv = malloc(sizeof(char *)); cmd_lines[0]->redirect_out = NULL; cmd_lines[0]->append_mode = 0; i = 0; int idx_cmd = 0; int nbr_args_in_actual_cmd = 0; while (args[i] != NULL) { if (strcmp(args[i], "|") == 0) { cmd_lines[idx_cmd]->argv[nbr_args_in_actual_cmd] = NULL; idx_cmd++; cmd_lines = realloc(cmd_lines, (idx_cmd + 1) * sizeof(command *)); if (cmd_lines == NULL) exit(EXIT_FAILURE); cmd_lines[idx_cmd] = malloc(sizeof(command)); cmd_lines[idx_cmd]->argv = malloc(sizeof(char *)); cmd_lines[idx_cmd]->redirect_out = NULL; cmd_lines[idx_cmd]->append_mode = 0; nbr_args_in_actual_cmd = 0; } else if (strcmp(args[i], ">") == 0 || strcmp(args[i], ">>") == 0) { cmd_lines[idx_cmd]->append_mode = (strcmp(args[i], ">>") == 0); if (args[i + 1] != NULL) { cmd_lines[idx_cmd]->redirect_out = strdup(args[i + 1]); i++; } else { dprintf(STDERR_FILENO, "syntax error near unexpected token 'newline'\n"); } } else { cmd_lines[idx_cmd]->argv = realloc(cmd_lines[idx_cmd]->argv, (nbr_args_in_actual_cmd + 1) * sizeof(char *)); cmd_lines[idx_cmd]->argv[nbr_args_in_actual_cmd] = strdup(args[i]); nbr_args_in_actual_cmd++; } i++; } cmd_lines[idx_cmd]->argv = realloc( cmd_lines[idx_cmd]->argv, (nbr_args_in_actual_cmd + 1) * sizeof(char *)); cmd_lines[idx_cmd]->argv[nbr_args_in_actual_cmd] = NULL; cmd_lines = realloc(cmd_lines, (idx_cmd + 2) * sizeof(command *)); cmd_lines[idx_cmd + 1] = NULL; free(args); return cmd_lines; } /** * @brief La boucle du shell, elle consiste en trois étapes : * - Quand l'utilisateur appui sur entrer pour récupérer son entrée standard * - Parser la ligne en fonction de ses espaces * - Exécuter la commande demandée * @see char* read_line() * @see char** split_line(char *line) * @see int execute_cmd(char **args) */ void shell_loop(disk *disk) { char *user = get_env_value("USER"); if (user == NULL) { exit(EXIT_FAILURE); } char *hostname = get_env_value("HOST"); char *line; command **args; int status = 1; do { dprintf(STDOUT_FILENO, "%s@%s %s> ", user, hostname, get_env_value("PWD")); line = read_line(); args = split_line(line); status = execute_cmd(disk, args); free(line); free(args); } while (status != 67); } void signal_handler(int sig) { (void)sig; char *user = get_env_value("USER"); if (user == NULL) { exit(EXIT_FAILURE); } char *hostname = get_env_value("HOST"); dprintf(STDOUT_FILENO, "\n"); dprintf(STDOUT_FILENO, "%s@%s %s> ", user, hostname, get_env_value("PWD")); } void open_seyshell(disk *disk) { signal(SIGINT, signal_handler); // le processus père ne s'arrête pas quand il // y a un SIGINT = sigma boy env *envs = init_envs(); shell_loop(disk); free(envs); }