diff --git a/Makefile b/Makefile index 3d0e1a8..18be972 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: ttsubo +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/04/03 12:55:20 by ttsubo #+# #+# # -# Updated: 2025/05/06 13:15:51 by ttsubo ### ########.fr # +# Updated: 2025/05/08 18:21:27 by ttsubo ### ########.fr # # # # **************************************************************************** # @@ -72,7 +72,8 @@ PARSER_SRC = allocate_cmds.c parser.c parser_utils.c setup_cmds.c \ split_by_quote.c join_expanded_parts.c BUILTIN_SRC = cd.c exit.c pwd.c echo.c env.c unset.c export.c \ env_utils.c env_utils_2.c env_utils_3.c builtin_utils.c \ - export_exec.c export_print_sorted_env.c export_error.c split_key_value.c + export_exec.c export_exec_utils.c \ + export_print_sorted_env.c export_error.c split_key_value.c # 3.Add more directories as they are added. $(eval $(call add_module,root)) diff --git a/inc/builtin/builtin.h b/inc/builtin/builtin.h index 7d2b6c8..0a83a07 100644 --- a/inc/builtin/builtin.h +++ b/inc/builtin/builtin.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* builtin.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dayano +#+ +:+ +#+ */ +/* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/13 17:19:01 by ttsubo #+# #+# */ -/* Updated: 2025/05/01 16:59:28 by dayano ### ########.fr */ +/* Updated: 2025/05/08 17:44:03 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,6 +14,8 @@ # define BUILTIN_H # define PATH_MAX 4096 +# define EXIT_EXPORT_NOT_A_VALID 1 +# define EXIT_EXPORT_INVALID_OPT 2 # include "builtin_utils.h" # include "struct.h" diff --git a/inc/builtin/builtin_utils.h b/inc/builtin/builtin_utils.h index ef6dcf5..5b2e010 100644 --- a/inc/builtin/builtin_utils.h +++ b/inc/builtin/builtin_utils.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* builtin_utils.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dayano +#+ +:+ +#+ */ +/* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/20 19:47:50 by ttsubo #+# #+# */ -/* Updated: 2025/05/01 16:15:02 by dayano ### ########.fr */ +/* Updated: 2025/05/08 18:22:30 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,17 +17,24 @@ # include # include -typedef struct s_export_exec_bool +typedef struct s_export_exec_vars { + int i; + char *key; + char *value; bool exists; bool has_plus; bool has_eq; -} t_export_exec_bool; + int exit_sts; + int last_exit_sts; +} t_export_exec_vars; char *ft_strndup(const char *s1, size_t n); int export_exec(int argc, char **argv, t_minish *minish); +int select_export_exec(t_export_exec_vars vars, t_minish *minish); int print_sorted_env(t_env *head); -void export_err_invalid(char *sh, char *arg); +int export_err_invalid(char *sh, char *key, char *value); +int export_err_invalid_opt(char *sh, char c); int split_key_value(char *str, char **key_out, char **val_out); #endif diff --git a/src/builtin/echo.c b/src/builtin/echo.c index b1b4efe..0f6d5fd 100644 --- a/src/builtin/echo.c +++ b/src/builtin/echo.c @@ -3,15 +3,27 @@ /* ::: :::::::: */ /* echo.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dayano +#+ +:+ +#+ */ +/* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/14 11:12:37 by ttsubo #+# #+# */ -/* Updated: 2025/05/01 15:48:48 by dayano ### ########.fr */ +/* Updated: 2025/05/08 17:30:38 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #include "main.h" +static int _echo_putchar_fd(char c, int fd) +{ + return (write(fd, &c, 1)); +} + +static int _echo_putstr_fd(char *s, int fd) +{ + if (s == NULL) + return (0); + return (write(fd, s, ft_strlen(s))); +} + /** * @brief Determines if the option is n only. * @@ -40,7 +52,7 @@ static int _has_only_n_option(char *arg) * * @param argc * @param argv - * @return 0: Always returns 0. + * @return 0: success. 1: output failed. */ int builtin_echo(int argc, char *argv[], t_minish *minish) { @@ -60,11 +72,12 @@ int builtin_echo(int argc, char *argv[], t_minish *minish) } while (i < argc) { - ft_putstr_fd(argv[i++], STDOUT_FILENO); - if (i != argc) - ft_putchar_fd(' ', STDOUT_FILENO); + if (_echo_putstr_fd(argv[i++], STDOUT_FILENO) == -1) + return (1); + if (i != argc && _echo_putchar_fd(' ', STDOUT_FILENO) == -1) + return (1); } - if (nl_flg) - ft_putchar_fd('\n', STDOUT_FILENO); + if (nl_flg && _echo_putchar_fd('\n', STDOUT_FILENO) == -1) + return (1); return (0); } diff --git a/src/builtin/export.c b/src/builtin/export.c index f91a246..eafd9f1 100644 --- a/src/builtin/export.c +++ b/src/builtin/export.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/15 11:35:46 by dayano #+# #+# */ -/* Updated: 2025/04/29 13:56:56 by ttsubo ### ########.fr */ +/* Updated: 2025/05/08 17:45:09 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,6 +16,11 @@ int builtin_export(int argc, char *argv[], t_minish *minish) { if (argc == 1) return (print_sorted_env(minish->env)); + if (argv[1][0] == '-' && argv[1][1] != '\0') + { + export_err_invalid_opt("minish", argv[1][1]); + return (EXIT_EXPORT_INVALID_OPT); + } if (argc >= 2) return (export_exec(argc, argv, minish)); return (EXIT_SUCCESS); diff --git a/src/builtin/export_error.c b/src/builtin/export_error.c index f5972f3..88e4665 100644 --- a/src/builtin/export_error.c +++ b/src/builtin/export_error.c @@ -6,16 +6,31 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/28 14:11:06 by ttsubo #+# #+# */ -/* Updated: 2025/04/29 14:52:17 by ttsubo ### ########.fr */ +/* Updated: 2025/05/08 17:58:36 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #include "main.h" -void export_err_invalid(char *sh, char *arg) +int export_err_invalid_opt(char *sh, char c) +{ + ft_putstr_fd(sh, STDERR_FILENO); + ft_putstr_fd(": export: -", STDERR_FILENO); + ft_putchar_fd(c, STDERR_FILENO); + ft_putendl_fd(": invalid option", STDERR_FILENO); + return (EXIT_EXPORT_INVALID_OPT); +} + +int export_err_invalid(char *sh, char *key, char *value) { ft_putstr_fd(sh, STDERR_FILENO); ft_putstr_fd(": export: `", STDERR_FILENO); - ft_putstr_fd(arg, STDERR_FILENO); + ft_putstr_fd(key, STDERR_FILENO); + if (value) + { + ft_putchar_fd('=', STDERR_FILENO); + ft_putstr_fd(value, STDERR_FILENO); + } ft_putendl_fd("': not a valid identifier", STDERR_FILENO); + return (EXIT_EXPORT_NOT_A_VALID); } diff --git a/src/builtin/export_exec.c b/src/builtin/export_exec.c index 819a9b2..0411bf4 100644 --- a/src/builtin/export_exec.c +++ b/src/builtin/export_exec.c @@ -6,114 +6,31 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/28 14:11:06 by ttsubo #+# #+# */ -/* Updated: 2025/05/01 14:04:19 by ttsubo ### ########.fr */ +/* Updated: 2025/05/08 18:20:43 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #include "main.h" -static int _update_value(char *key, char *value, t_minish *minish) -{ - t_env *node; - - if (!is_valid_key(key)) - return (export_err_invalid("minish", key), EXIT_FAILURE); - node = get_env_node(minish->env, key); - if (!node) - return (EXIT_FAILURE); - if (node->value) - free(node->value); - node->value = ft_strdup(value); - node->is_exported = 1; - return (EXIT_SUCCESS); -} - -static int _append_value(char *key, char *value, t_minish *minish) -{ - t_env *node; - char *join_str; - - if (!is_valid_key(key)) - return (export_err_invalid("minish", key), EXIT_FAILURE); - node = get_env_node(minish->env, key); - join_str = NULL; - if (!node) - return (EXIT_FAILURE); - if (node->value) - join_str = ft_strjoin(node->value, value); - else - join_str = ft_strdup(value); - if (!join_str) - return (EXIT_FAILURE); - free(node->value); - node->value = join_str; - node->is_exported = 1; - return (EXIT_SUCCESS); -} - -static int _add_key_value(char *key, char *value, t_minish *minish) -{ - t_env *node; - - if (!is_valid_key(key)) - return (export_err_invalid("minish", key), EXIT_FAILURE); - node = ft_calloc(1, sizeof(t_env)); - if (!node) - return (EXIT_FAILURE); - node->key = ft_strdup(key); - if (!node->key) - return (free(node), EXIT_FAILURE); - node->value = ft_strdup(value); - if (!node->value) - return (free(node->key), free(node), EXIT_FAILURE); - node->is_exported = 1; - add_env_back(&minish->env, node); - return (EXIT_SUCCESS); -} - -static int _add_key(char *key, t_minish *minish) -{ - t_env *node; - - if (!is_valid_key(key)) - return (export_err_invalid("minish", key), EXIT_FAILURE); - node = ft_calloc(1, sizeof(t_env)); - if (!node) - return (EXIT_FAILURE); - node->key = ft_strdup(key); - if (!node->key) - return (free(node), EXIT_FAILURE); - node->value = NULL; - node->is_exported = 0; - add_env_back(&minish->env, node); - return (EXIT_SUCCESS); -} - int export_exec(int argc, char **argv, t_minish *minish) { - int i; - char *key; - char *value; - t_export_exec_bool bools; + t_export_exec_vars vars; - i = 1; - while (i < argc) + vars.i = 1; + vars.last_exit_sts = 0; + while (vars.i < argc) { - split_key_value(argv[i], &key, &value); - bools.exists = has_env_key(minish->env, key); - bools.has_plus = ft_strnstr(argv[i], "+=", ft_strlen(argv[i])) != NULL; - bools.has_eq = ft_strchr(argv[i], '=') != NULL; - if (bools.exists && bools.has_plus) - _append_value(key, value, minish); - else if (bools.exists && !bools.has_plus && bools.has_eq) - _update_value(key, value, minish); - else if (!bools.exists && (bools.has_plus || bools.has_eq)) - _add_key_value(key, value, minish); - else if (!bools.exists) - _add_key(key, minish); - free(key); - free(value); - i++; + split_key_value(argv[vars.i], &vars.key, &vars.value); + vars.exists = has_env_key(minish->env, vars.key); + vars.has_plus = ft_strnstr(argv[vars.i], "+=", + ft_strlen(argv[vars.i])) != NULL; + vars.has_eq = ft_strchr(argv[vars.i], '=') != NULL; + vars.exit_sts = select_export_exec(vars, minish); + free_str(&vars.key); + free_str(&vars.value); + if (vars.exit_sts) + vars.last_exit_sts = vars.exit_sts; + vars.i++; } - return (EXIT_SUCCESS); + return (vars.last_exit_sts); } diff --git a/src/builtin/export_exec_utils.c b/src/builtin/export_exec_utils.c new file mode 100644 index 0000000..ff009d6 --- /dev/null +++ b/src/builtin/export_exec_utils.c @@ -0,0 +1,103 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export_exec_utils.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 14:11:06 by ttsubo #+# #+# */ +/* Updated: 2025/05/08 18:19:12 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "main.h" + +static int _update_value(char *key, char *value, t_minish *minish) +{ + t_env *node; + + if (!is_valid_key(key)) + return (export_err_invalid("minish", key, value)); + node = get_env_node(minish->env, key); + if (!node) + return (EXIT_FAILURE); + if (node->value) + free(node->value); + node->value = ft_strdup(value); + node->is_exported = 1; + return (EXIT_SUCCESS); +} + +static int _append_value(char *key, char *value, t_minish *minish) +{ + t_env *node; + char *join_str; + + if (!is_valid_key(key)) + return (export_err_invalid("minish", key, value)); + node = get_env_node(minish->env, key); + join_str = NULL; + if (!node) + return (EXIT_FAILURE); + if (node->value) + join_str = ft_strjoin(node->value, value); + else + join_str = ft_strdup(value); + if (!join_str) + return (EXIT_FAILURE); + free(node->value); + node->value = join_str; + node->is_exported = 1; + return (EXIT_SUCCESS); +} + +static int _add_key_value(char *key, char *value, t_minish *minish) +{ + t_env *node; + + if (!is_valid_key(key)) + return (export_err_invalid("minish", key, value)); + node = ft_calloc(1, sizeof(t_env)); + if (!node) + return (EXIT_FAILURE); + node->key = ft_strdup(key); + if (!node->key) + return (free(node), EXIT_FAILURE); + node->value = ft_strdup(value); + if (!node->value) + return (free(node->key), free(node), EXIT_FAILURE); + node->is_exported = 1; + add_env_back(&minish->env, node); + return (EXIT_SUCCESS); +} + +static int _add_key(char *key, t_minish *minish) +{ + t_env *node; + + if (!is_valid_key(key)) + return (export_err_invalid("minish", key, NULL)); + node = ft_calloc(1, sizeof(t_env)); + if (!node) + return (EXIT_FAILURE); + node->key = ft_strdup(key); + if (!node->key) + return (free(node), EXIT_FAILURE); + node->value = NULL; + node->is_exported = 0; + add_env_back(&minish->env, node); + return (EXIT_SUCCESS); +} + +int select_export_exec(t_export_exec_vars vars, t_minish *minish) +{ + if (vars.exists && vars.has_plus) + vars.exit_sts = _append_value(vars.key, vars.value, minish); + else if (vars.exists && !vars.has_plus && vars.has_eq) + vars.exit_sts = _update_value(vars.key, vars.value, minish); + else if (!vars.exists && (vars.has_plus || vars.has_eq)) + vars.exit_sts = _add_key_value(vars.key, vars.value, minish); + else if (!vars.exists) + vars.exit_sts = _add_key(vars.key, minish); + return (vars.exit_sts); +}