extFS-Seyshell/src/parsing.c

159 lines
3.6 KiB
C

/** @file */
#include "parsing.h"
#include "disk.h"
#include "exec.h"
#include "struct.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/**
* @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 *));
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 + 1] = NULL;
idx_cmd++;
cmd_lines[idx_cmd] = malloc(sizeof(command));
cmd_lines[idx_cmd]->argv = malloc(sizeof(char *));
nbr_args_in_actual_cmd = 0;
} 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 + 1] = malloc(sizeof(command));
cmd_lines[idx_cmd + 1] = NULL;
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 {
// ça aussi c'est pas bien, ça sera à changer une fois le sgf fonctionnel
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);
}
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);
}