diff --git a/Makefile b/Makefile index be8b7f6..22d1a51 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ BUILTIN_PATH = builtin SRC_PATHS = $(CURRENT_PATH) $(EXPANDER_PATH) $(BUILTIN_PATH) $(EXECUTE_PATH) $(PARSER_PATH) $(LEXER_PATH) $(AST_PATH) $(UTILS_PATH) SRCS = $(foreach path, $(SRC_PATHS), $(wildcard $(path)/*.c)) -VPATH = $(CURRENT_PATH):$(BUILTIN_PATH):$(EXECUTE_PATH):$(PARSER_PATH):$(LEXER_PATH):$(AST_PATH):$(UTILS_PATH) +VPATH = $(CURRENT_PATH):$(BUILTIN_PATH):$(EXECUTE_PATH):$(PARSER_PATH):$(LEXER_PATH):$(AST_PATH):$(UTILS_PATH):$(EXPANDER_PATH) OBJDIR = ./obj OBJS = $(addprefix $(OBJDIR)/, $(notdir $(SRCS:.c=.o))) diff --git a/builtin/builtin.h b/builtin/builtin.h index 4bf86e0..2147532 100644 --- a/builtin/builtin.h +++ b/builtin/builtin.h @@ -4,9 +4,13 @@ #include #include #include + #include "../libft/libft.h" +#include "../utils/utils.h" +#include "../execute/execute.h" int cd(int argc, char **argv); int pwd(); +int builtin_exit(int argc, char **argv, int last_exit_status); #endif //BUILTIN_H diff --git a/builtin/builtin_exit.c b/builtin/builtin_exit.c new file mode 100644 index 0000000..e4baab4 --- /dev/null +++ b/builtin/builtin_exit.c @@ -0,0 +1,23 @@ +#include "builtin.h" + +int builtin_exit(int argc, char **argv, int last_exit_status) +{ + int num; + + ft_putendl_fd("exit", STDERR_FILENO); + if (argc == 1) + exit(last_exit_status); + if (argc == 2) + { + if (!atoi_strict(argv[1], &num)) + { + ft_putendl_fd("minishell: exit: ", STDERR_FILENO); + ft_putendl_fd(argv[1], STDERR_FILENO); + ft_putendl_fd(": numeric argument required", STDERR_FILENO); + return (EXIT_FAILURE); + } + exit((unsigned char)num); //todo: free? + } + ft_putendl_fd("minishell: exit: too many arguments", STDERR_FILENO); + return (EXIT_FAILURE); +} \ No newline at end of file diff --git a/execute/execute_utils.c b/execute/execute_utils.c index 9b350fb..f858191 100644 --- a/execute/execute_utils.c +++ b/execute/execute_utils.c @@ -72,6 +72,14 @@ bool execute_builtin(t_executor *e, int argc, char **argv, bool islast) pwd(argc, argv); return (true); } + else if (!ft_strcmp(argv[0], "exit")) + { + if (islast) + e->exit_status = builtin_exit(argc, argv, e->exit_status); + else + builtin_exit(argc, argv, e->exit_status); + return (true); + } return (false); } diff --git a/libft/ft_isdigit.c b/libft/ft_isdigit.c new file mode 100644 index 0000000..2ee5686 --- /dev/null +++ b/libft/ft_isdigit.c @@ -0,0 +1,4 @@ +int ft_isdigit(int c) +{ + return ('0' <= c && c <= '9'); +} diff --git a/minishell.c b/minishell.c index 91cf10c..1887b1c 100644 --- a/minishell.c +++ b/minishell.c @@ -42,13 +42,9 @@ int minishell(char *line) while (1) { line = readline("minishell> "); - // line can be NULL when Ctrl+d - if (!line || ft_strncmp(line, "exit", 4) == 0) - { - free(line); - ft_putendl_fd("exit", STDERR_FILENO); + if (!line) break ; - } + // line can be NULL when Ctrl+d t_token *token = lex(line); t_ast_node *node = parse(token); if (!node) @@ -63,7 +59,7 @@ int minishell(char *line) add_history(line); free(line); } - return (0); + return (EXIT_SUCCESS); } int main(int argc, char **argv) diff --git a/test/cases/exit.txt b/test/cases/exit.txt new file mode 100644 index 0000000..ee7f7f1 --- /dev/null +++ b/test/cases/exit.txt @@ -0,0 +1,3 @@ +exit 0 +exit 1 +exit -1 diff --git a/utils/atoi_strict.c b/utils/atoi_strict.c new file mode 100644 index 0000000..9825ab7 --- /dev/null +++ b/utils/atoi_strict.c @@ -0,0 +1,29 @@ +#include "utils.h" + +bool atoi_strict(const char *str, int *num) +{ + long long converted; + int sign; + + converted = 0; + sign = 1; + while (('\t' <= *str && *str <= '\r') || *str == ' ') + str++; + if ((*str == '+' || *str == '-') && *str++ == '-') + sign = -1; + if (*str == '\0') + return (false); + while (ft_isdigit(*str)) + { + if ((converted * 10 + *str - '0') / 10 != converted) + return (false); + converted = converted * 10 + *str - '0'; + str++; + } + if (*str == '\0') + { + *num = (int)(sign * converted); + return (true); + } + return (false); +} diff --git a/utils/utils.h b/utils/utils.h index ca63d54..80faabc 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -10,5 +10,6 @@ char *strappend(char *dst, const char *src, size_t l); char *ft_strndup(const char *str, size_t size); void free_2d_array(void ***array); char **split_by_delims(char const *str, const char *delims); +bool atoi_strict(const char *str, int *num); # endif //UTILS_H