diff --git a/Makefile b/Makefile index 913e393..26dd8b2 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ READLINE = $(READLINE_DIR)/libreadline.a _SRC_LIB_STATIC = parser.c executer.c cleaner.c lexer.c lexer_get_tokens.c error.c parser_get_commands.c parser_clean_commands1.c parser_clean_commands2.c lexer_count_tokens.c lexer_get_token_size.c parser_get_commands_populate.c \ utils.c executer_getpath.c environment.c signals.c + _SRC = main.c $(_SRC_LIB_STATIC) _OBJ = $(_SRC:.c=.o) _OBJ_LIB_STATIC = $(_SRC_LIB_STATIC:.c=.o) diff --git a/includes/minishell.h b/includes/minishell.h index aac5228..20b599c 100644 --- a/includes/minishell.h +++ b/includes/minishell.h @@ -38,6 +38,7 @@ # define IS_DIR 4 # define OPEN_ERROR 5 # define SIGNAL_ERROR 6 +# define EXPORT_ERROR 7 typedef struct s_redirections { @@ -68,8 +69,9 @@ size_t get_env_var_len(char **env_var); char **get_env_list(char *token, char **env); size_t get_new_token_size(char *token, char **var_env); -int ms_execute(t_command *commnands, char **env); +int ms_execute(t_command *commnands, char ***env); char *get_command_path(char *command, char **env); +int set_redirections(t_command command, int *pipe_fd, int last); // Environment management char *ms_getenv(char **env, char *var); @@ -79,6 +81,9 @@ char **remove_var(char **env, char *var); char **update_var(char **env, char *var, char *new_content); int is_var(char **env, char *var); +//Builtin +int exec_builtin(t_command cmd, char ***env); + // Signal management int ms_init_signals(void); int ms_reset_signals(void); diff --git a/src/builtin.c b/src/builtin.c new file mode 100644 index 0000000..9582526 --- /dev/null +++ b/src/builtin.c @@ -0,0 +1,91 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* buildin.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: maxpelle +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2023/11/13 12:16:43 by eguefif #+# #+# */ +/* Updated: 2023/11/22 10:24:48 by maxpelle ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "minishell.h" + +static char **builtin_unset(t_command cmd, char **env); +static int builtin_export(t_command cmd, char ***env); +static int is_valid_identifier(char *id); + +int exec_builtin(t_command cmd, char ***env) +{ + if (ft_strcmp(cmd.args[0], "export") == 0) + return (builtin_export(cmd, env)); + else if (ft_strcmp(cmd.args[0], "unset") == 0) + { + *env = builtin_unset(cmd, *env); + return (0); + } + return (-1); +} + +static char **builtin_unset(t_command cmd, char **env) +{ + int i; + + i = 1; + while (cmd.args[i]) + { + if (is_var(env, cmd.args[i])) + env = remove_var(env, cmd.args[i]); + i++; + } + return (env); +} + +static int builtin_export(t_command cmd, char ***env) +{ + int i; + int retval; + char **splits; + + i = 1; + retval = 0; + while (cmd.args[i]) + { + if (is_valid_identifier(cmd.args[i])) + { + splits = ft_split(cmd.args[i], '='); + if (is_var(*env, cmd.args[i])) + *env = update_var(*env, splits[0], splits[1]); + else + *env = add_var(*env, splits[0], splits[1]); + ft_cleansplits(splits); + } + else + { + ft_error_message(cmd.args[i], EXPORT_ERROR); + if (ft_strchr(cmd.args[i], '=')) + retval = 1; + } + i++; + } + return (retval); +} + +static int is_valid_identifier(char *id) +{ + int i; + + if (!ft_strchr(id, '=')) + return (0); + if (ft_isdigit(id[0])) + return (0); + i = 1; + while (id[i] != '=') + { + if (!(ft_isalnum(id[i]) || id[i] == '_')) + return (0); + i++; + } + return (1); +} diff --git a/src/environment.c b/src/environment.c index 9cfed04..0cafab5 100644 --- a/src/environment.c +++ b/src/environment.c @@ -140,10 +140,13 @@ char **update_var(char **env, char *var, char *new_content) int is_var(char **env, char *var) { int i; + char *tmp; i = 0; - while (env[i] && ft_strstr(env[i], var) == 0) + tmp = ft_strjoin(var, "="); + while (env[i] && ft_strstr(env[i], tmp) == 0) i++; + free(tmp); if (env[i]) return (1); return (0); diff --git a/src/error.c b/src/error.c index 402c498..f4bdd98 100644 --- a/src/error.c +++ b/src/error.c @@ -31,4 +31,6 @@ void ft_error_message(char *s, int error_type) ft_dprintf(2, "%s: %s: is a directory\n", PROG_NAME, s); else if (error_type == OPEN_ERROR || error_type == SIGNAL_ERROR) ft_dprintf(2, "%s: %s: %s\n", PROG_NAME, s, strerror(errno)); + else if (error_type == EXPORT_ERROR) + ft_dprintf(2, "%s: export: \'%s\': not a valid identifier\n", PROG_NAME, s); } diff --git a/src/executer.c b/src/executer.c index f65bd8b..c66765e 100644 --- a/src/executer.c +++ b/src/executer.c @@ -12,12 +12,11 @@ #include "minishell.h" -static int run(t_command *commands, char **env); +static int run(t_command *commands, char ***env); static int handle_child(t_command *commands, char **env); static int get_exit_code(int status); -static int set_redirections(t_command command, int *pipe_fd, int last); -int ms_execute(t_command *commands, char **env) +int ms_execute(t_command *commands, char ***env) { int stdin_save; int stdout_save; @@ -35,46 +34,56 @@ int ms_execute(t_command *commands, char **env) return (retval); } -static int run(t_command *commands, char **env) +static int run(t_command *commands, char ***env) { int pipe_fd[2]; int retval; + int pid; int stat_loc; int i; i = -1; + pid = -1; while (!commands[++i].last) { - if (pipe(pipe_fd) == -1) - return (ft_error()); - retval = fork(); - if (retval < 0) - return (ft_error()); - else if (!retval) + retval = exec_builtin(commands[i], env); + if (retval == -1) { - if (ms_reset_signals() != 0) - return (1); - if (set_redirections(commands[i], pipe_fd, - commands[i + 1].last)) - return (1); - if (!commands[i].args[0]) - return (0); - ft_exit_nb(commands, handle_child(&commands[i], env)); + if (pipe(pipe_fd) == -1) + return (ft_error()); + pid = fork(); + if (pid < 0) + return (ft_error()); + else if (!pid) + { + if (ms_reset_signals() != 0) + return (1); + if (set_redirections(commands[i], pipe_fd, + commands[i + 1].last)) + return (1); + if (!commands[i].args[0]) + return (0); + ft_exit_nb(commands, handle_child(&commands[i], *env)); + } + if (dup2(pipe_fd[0], 0) == -1) + return (ft_error()); + close(pipe_fd[0]); + close(pipe_fd[1]); } + i++; + } + if (pid >= 0) + { + waitpid(pid, &stat_loc, 0); + retval = get_exit_code(stat_loc); + while (waitpid(-1, &stat_loc, 0) > 0) + ; ms_ignore_signals(); - if (dup2(pipe_fd[0], 0) == -1) - return (ft_error()); - close(pipe_fd[0]); - close(pipe_fd[1]); } - waitpid(retval, &stat_loc, 0); - retval = get_exit_code(stat_loc); - while (waitpid(-1, &stat_loc, 0) > 0) - ; return (retval); } -static int set_redirections(t_command command, int *pipe_fd, int last) +int set_redirections(t_command command, int *pipe_fd, int last) { int fd; int retval; diff --git a/src/executer_getpath.c b/src/executer_getpath.c index 61b4821..95a9f9b 100644 --- a/src/executer_getpath.c +++ b/src/executer_getpath.c @@ -12,6 +12,8 @@ #include "minishell.h" +static int is_relative_path(char *command); + char *get_command_path(char *command, char **env) { char *path; @@ -20,8 +22,9 @@ char *get_command_path(char *command, char **env) char *retval; char *tab[3]; - if (access(command, F_OK) == 0) - return (ft_strdup(command)); + if (is_relative_path(command)) + if (access(command, F_OK) == 0) + return (ft_strdup(command)); path = ms_getenv(env, "PATH"); if (!path) return (0); @@ -43,3 +46,10 @@ char *get_command_path(char *command, char **env) ft_cleansplits(paths); return (retval); } + +static int is_relative_path(char *command) +{ + if (command[0]== '.' && command[1] == '/') + return (1); + return (0); +} diff --git a/src/main.c b/src/main.c index 4bcd0bc..5bd0691 100644 --- a/src/main.c +++ b/src/main.c @@ -51,7 +51,7 @@ char **non_interactive_mode(char **env) break ; if (commands) { - retval = ms_execute(commands, env); + retval = ms_execute(commands, &env); env = handle_exit_code(env, retval); } line = get_next_line(0); @@ -80,12 +80,17 @@ char **interactive_mode(char **env) if (check_valid_line_for_history(line)) { add_history(line); + if (ft_strcmp(line, "exit") == 0) + { + free(line); + break ; + } commands = ms_parser(line, env); if (errno == ENOMEM) break ; if (commands) { - retval = ms_execute(commands, env); + retval = ms_execute(commands, &env); env = handle_exit_code(env, retval); } else