diff --git a/Makefile b/Makefile index d39a39c..18f196e 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ L_FLG = -lreadline -lft # 1.Add more directories as they are added. SRC_DIR = src/ PARSER_SRC_DIR = src/parser/ +COMMON_SRC_DIR = src/common/ TOKENIZER_SRC_DIR = src/tokenizer/ INVOKE_CMD_SRC_DIR = src/invoke_cmd/ BUILTIN_SRC_DIR = src/builtin/ @@ -46,18 +47,21 @@ endef # 2.Add the source code when it is added ROOT_SRC = main.c minish_signal.c initialize.c error.c +COMMON_SRC = validate_key.c error_mes.c INVOKE_CMD_SRC = create_envp.c exec_pipeline.c execute_cmd.c \ execute_cmd_helper.c invoke_command.c pipeline_helper.c \ redirect.c fds.c wait_pipeline.c TOKENIZER_SRC = tokenizer.c tokenizer_error.c read_token.c \ is_quote_closed.c get_token_capa.c is_redirect_validate.c PARSER_SRC = allocate_cmds.c parser.c parser_utils.c setup_cmds.c \ - expand_env.c expand_env_utils.c -BUILTIN_SRC = cd.c exit.c pwd.c echo.c env.c unset.c \ - env_utils.c env_utils_2.c builtin_utils.c + expand_env.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 # 3.Add more directories as they are added. $(eval $(call add_module,root)) +$(eval $(call add_module,common)) $(eval $(call add_module,invoke_cmd)) $(eval $(call add_module,tokenizer)) $(eval $(call add_module,parser)) diff --git a/inc/builtin.h b/inc/builtin.h index 854b1ae..f7959b5 100644 --- a/inc/builtin.h +++ b/inc/builtin.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/13 17:19:01 by ttsubo #+# #+# */ -/* Updated: 2025/04/20 19:48:02 by ttsubo ### ########.fr */ +/* Updated: 2025/04/21 11:20:16 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,5 +24,6 @@ int builtin_exit(int argc, char *argv[]); int builtin_cd(int argc, char *argv[]); int builtin_env(int argc, char **argv, t_minish *minish); int builtin_unset(int argc, char *argv[], t_minish *minish); +int builtin_export(int argc, char **argv, t_minish *minish); #endif diff --git a/inc/builtin_utils.h b/inc/builtin_utils.h index c2f09b4..26eadcc 100644 --- a/inc/builtin_utils.h +++ b/inc/builtin_utils.h @@ -6,13 +6,26 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/20 19:47:50 by ttsubo #+# #+# */ -/* Updated: 2025/04/20 19:55:44 by ttsubo ### ########.fr */ +/* Updated: 2025/04/29 14:48:10 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef BUILTIN_UTILS_H # define BUILTIN_UTILS_H -void error_mes(char *name, char *mes); +# include +# include + +typedef struct s_export_exec_bool +{ + bool exists; + bool has_plus; + bool has_eq; +} t_export_exec_bool; + +char *ft_strndup(const char *s1, size_t n); +int export_exec(int argc, char **argv, t_minish *minish); +int print_sorted_env(t_env *head); +void export_err_invalid(char *sh, char *arg); #endif \ No newline at end of file diff --git a/inc/common.h b/inc/common.h new file mode 100644 index 0000000..9a19ba2 --- /dev/null +++ b/inc/common.h @@ -0,0 +1,25 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* common.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/29 11:44:19 by ttsubo #+# #+# */ +/* Updated: 2025/04/29 14:12:51 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef COMMON_H +# define COMMON_H + +# include +# include +# include "libft.h" + +bool is_key_start(int c); +bool is_key_char(int c); +bool is_valid_key(char *str); +void error_mes(char *name, char *mes); + +#endif \ No newline at end of file diff --git a/inc/env_utils.h b/inc/env_utils.h index 74b6985..483ecad 100644 --- a/inc/env_utils.h +++ b/inc/env_utils.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/17 10:25:47 by dayano #+# #+# */ -/* Updated: 2025/04/26 10:19:56 by ttsubo ### ########.fr */ +/* Updated: 2025/04/28 15:47:53 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,7 +15,6 @@ # include "struct.h" -char *get_env_value(t_env *current, const char *key); void free_env_content(char *value); void remove_env_node(t_env **env_lst, t_env *target); diff --git a/inc/env_utils_2.h b/inc/env_utils_2.h index feccdc5..27d7505 100644 --- a/inc/env_utils_2.h +++ b/inc/env_utils_2.h @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* env_utils_2.h :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dayano +#+ +:+ +#+ */ +/* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/17 11:40:36 by dayano #+# #+# */ -/* Updated: 2025/04/17 11:42:07 by dayano ### ########.fr */ +/* Updated: 2025/04/21 12:14:53 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,5 +18,6 @@ void free_env_list(t_env *head); void cleanup_minish(t_minish *minish); void handle_error_and_exit(const char *func_name, t_minish *minish); +int split_key_value(char *str, char **key_out, char **val_out); #endif diff --git a/inc/env_utils_3.h b/inc/env_utils_3.h new file mode 100644 index 0000000..ec2e8ff --- /dev/null +++ b/inc/env_utils_3.h @@ -0,0 +1,23 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* env_utils_3.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/17 11:40:36 by dayano #+# #+# */ +/* Updated: 2025/04/28 16:51:16 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef ENV_UTILS_3_H +# define ENV_UTILS_3_H + +# include "struct.h" + +void add_env_back(t_env **lst, t_env *new); +t_env *get_env_node(t_env *current, const char *key); +char *get_env_value(t_env *current, const char *key); +bool has_env_key(t_env *current, const char *key); + +#endif diff --git a/inc/expand_env.h b/inc/expand_env.h index 5b6e5ef..43dc24e 100644 --- a/inc/expand_env.h +++ b/inc/expand_env.h @@ -6,14 +6,15 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/26 11:24:25 by ttsubo #+# #+# */ -/* Updated: 2025/04/26 11:50:18 by ttsubo ### ########.fr */ +/* Updated: 2025/04/29 11:45:55 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef EXPAND_ENV_H # define EXPAND_ENV_H -# include "env_utils.h" +# include "common.h" +# include "env_utils_3.h" # include "struct.h" # include @@ -34,7 +35,5 @@ typedef struct s_expand_temp } t_expand_temp; char *expand_env(char *token, t_minish *minish); -bool is_key_start(int c); -bool is_key_char(int c); #endif \ No newline at end of file diff --git a/inc/main.h b/inc/main.h index fd50d89..436f85c 100644 --- a/inc/main.h +++ b/inc/main.h @@ -19,6 +19,7 @@ # include "create_envp.h" # include "env_utils.h" # include "env_utils_2.h" +# include "env_utils_3.h" # include "error.h" # include "exec_pipeline.h" # include "execute_cmd.h" diff --git a/inc/struct.h b/inc/struct.h index a34fa2a..33198a4 100644 --- a/inc/struct.h +++ b/inc/struct.h @@ -17,6 +17,7 @@ typedef struct s_env { char *key; char *value; + int is_exported; struct s_env *next; } t_env; diff --git a/src/builtin/builtin_utils.c b/src/builtin/builtin_utils.c index b536371..65dea73 100644 --- a/src/builtin/builtin_utils.c +++ b/src/builtin/builtin_utils.c @@ -6,21 +6,28 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/20 19:46:40 by ttsubo #+# #+# */ -/* Updated: 2025/04/27 14:55:58 by ttsubo ### ########.fr */ +/* Updated: 2025/04/29 14:12:25 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #include "main.h" /** - * @brief Output to STDERR in the format ": \n". - * - * @param name - * @param mes + * @brief TODO: Retrieve as utils function later + * + * @param s1 + * @param n + * @return char* */ -void error_mes(char *name, char *mes) +char *ft_strndup(const char *s1, size_t n) { - ft_putstr_fd(name, STDERR_FILENO); - ft_putstr_fd(": ", STDERR_FILENO); - ft_putendl_fd(mes, STDERR_FILENO); + char *d; + + if (!s1) + return (NULL); + d = malloc(n + 1); + if (!d) + return (NULL); + ft_strlcpy(d, s1, n + 1); + return (d); } diff --git a/src/builtin/env.c b/src/builtin/env.c index 0a162c2..4a5db39 100644 --- a/src/builtin/env.c +++ b/src/builtin/env.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/14 16:19:11 by dayano #+# #+# */ -/* Updated: 2025/04/20 19:53:20 by ttsubo ### ########.fr */ +/* Updated: 2025/04/29 11:25:22 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -23,8 +23,9 @@ int builtin_env(int argc, char **argv, t_minish *minish) while (current) { next = current->next; - if (printf("%s=%s\n", current->key, current->value) < 0) - handle_error_and_exit("printf", minish); + if (current->is_exported) + if (printf("%s=%s\n", current->key, current->value) < 0) + handle_error_and_exit("printf", minish); current = next; } return (EXIT_SUCCESS); diff --git a/src/builtin/env_utils.c b/src/builtin/env_utils.c index 053dc19..dd3a485 100644 --- a/src/builtin/env_utils.c +++ b/src/builtin/env_utils.c @@ -6,33 +6,12 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/17 10:26:59 by dayano #+# #+# */ -/* Updated: 2025/04/26 10:19:02 by ttsubo ### ########.fr */ +/* Updated: 2025/04/28 16:32:43 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #include "main.h" -/** - * @brief Get the env value - * - * @param lst - * @param key - * @return char* - * @return NULL: if the key is not found or the key is NULL - */ -char *get_env_value(t_env *current, const char *key) -{ - if (!current || !key) - return (NULL); - while (current) - { - if (!ft_strcmp(current->key, key)) - return (current->value); - current = current->next; - } - return (NULL); -} - void free_env_content(char *value) { free(value); diff --git a/src/builtin/env_utils_2.c b/src/builtin/env_utils_2.c index 0eb7167..c02ffa6 100644 --- a/src/builtin/env_utils_2.c +++ b/src/builtin/env_utils_2.c @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/17 11:17:22 by dayano #+# #+# */ -/* Updated: 2025/04/20 19:36:26 by ttsubo ### ########.fr */ +/* Updated: 2025/04/28 16:32:00 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -40,3 +40,51 @@ void handle_error_and_exit(const char *func_name, t_minish *minish) perror(func_name); exit(EXIT_FAILURE); } + +static void _set_len_and_pos(char *str, size_t *key_len, size_t *val_start) +{ + const char *sep; + + sep = ft_strnstr(str, "+=", ft_strlen(str)); + if (sep) + { + *key_len = sep - str; + *val_start = *key_len + 2; + } + else + { + sep = ft_strchr(str, '='); + if (sep) + { + *key_len = sep - str; + *val_start = *key_len + 1; + } + else + { + *key_len = ft_strlen(str); + *val_start = 0; + } + } +} + +int split_key_value(char *str, char **key_out, char **val_out) +{ + size_t key_len; + size_t val_start; + + if (!str || !key_out || !val_out) + return (1); + *key_out = NULL; + *val_out = NULL; + _set_len_and_pos(str, &key_len, &val_start); + *key_out = ft_substr(str, 0, key_len); + if (!*key_out) + return (1); + if (val_start > 0) + { + *val_out = ft_substr(str, val_start, ft_strlen(str) - val_start); + if (!*val_out) + return (free(*key_out), *key_out = NULL, 1); + } + return (0); +} diff --git a/src/builtin/env_utils_3.c b/src/builtin/env_utils_3.c new file mode 100644 index 0000000..0b88417 --- /dev/null +++ b/src/builtin/env_utils_3.c @@ -0,0 +1,83 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* env_utils_3.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/17 11:17:22 by dayano #+# #+# */ +/* Updated: 2025/04/29 13:53:40 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "main.h" + +void add_env_back(t_env **lst, t_env *new) +{ + t_env *node; + + if (*lst != NULL) + { + node = *lst; + while (node->next != NULL) + node = node->next; + node->next = new; + } + else + *lst = new; +} + +/** + * @brief Get the env node object + * + * @param current + * @param key + * @return t_env* + * @return NULL: if the key is not found or the key is NULL + */ +t_env *get_env_node(t_env *current, const char *key) +{ + if (!current || !key) + return (NULL); + while (current) + { + if (!ft_strcmp(current->key, key)) + return (current); + current = current->next; + } + return (NULL); +} + +/** + * @brief Get the env value + * + * @param lst + * @param key + * @return char* + * @return NULL: if the key is not found or the key is NULL + */ +char *get_env_value(t_env *current, const char *key) +{ + if (!current || !key) + return (NULL); + while (current) + { + if (!ft_strcmp(current->key, key)) + return (current->value); + current = current->next; + } + return (NULL); +} + +bool has_env_key(t_env *current, const char *key) +{ + if (!current || !key) + return (false); + while (current) + { + if (!ft_strcmp(current->key, key)) + return (true); + current = current->next; + } + return (false); +} diff --git a/src/builtin/export.c b/src/builtin/export.c new file mode 100644 index 0000000..f91a246 --- /dev/null +++ b/src/builtin/export.c @@ -0,0 +1,22 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/15 11:35:46 by dayano #+# #+# */ +/* Updated: 2025/04/29 13:56:56 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "main.h" + +int builtin_export(int argc, char *argv[], t_minish *minish) +{ + if (argc == 1) + return (print_sorted_env(minish->env)); + 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 new file mode 100644 index 0000000..f5972f3 --- /dev/null +++ b/src/builtin/export_error.c @@ -0,0 +1,21 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export_error.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 14:11:06 by ttsubo #+# #+# */ +/* Updated: 2025/04/29 14:52:17 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "main.h" + +void export_err_invalid(char *sh, char *arg) +{ + ft_putstr_fd(sh, STDERR_FILENO); + ft_putstr_fd(": export: `", STDERR_FILENO); + ft_putstr_fd(arg, STDERR_FILENO); + ft_putendl_fd("': not a valid identifier", STDERR_FILENO); +} diff --git a/src/builtin/export_exec.c b/src/builtin/export_exec.c new file mode 100644 index 0000000..86ca39d --- /dev/null +++ b/src/builtin/export_exec.c @@ -0,0 +1,116 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export_exec.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 14:11:06 by ttsubo #+# #+# */ +/* Updated: 2025/04/29 14:52:09 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); + if (!join_str) + return (EXIT_FAILURE); + free(node->value); + node->value = join_str; + 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; + + i = 1; + while (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++; + } + return (EXIT_SUCCESS); +} diff --git a/src/builtin/export_print_sorted_env.c b/src/builtin/export_print_sorted_env.c new file mode 100644 index 0000000..c1de7d9 --- /dev/null +++ b/src/builtin/export_print_sorted_env.c @@ -0,0 +1,98 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* export_print_sorted_env.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/28 11:44:15 by ttsubo #+# #+# */ +/* Updated: 2025/04/28 13:07:14 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "main.h" + +static int compare_keys(const t_env *a, const t_env *b) +{ + return (ft_strcmp(a->key, b->key)); +} + +static void _qsort(t_env **array, size_t count) +{ + t_env *tmp; + size_t i; + size_t j; + + if (!array || count < 2) + return ; + i = 0; + while (i < count - 1) + { + j = 0; + while (j < count - 1 - i) + { + if (compare_keys(array[j], array[j + 1]) > 0) + { + tmp = array[j]; + array[j] = array[j + 1]; + array[j + 1] = tmp; + } + j++; + } + i++; + } +} + +static size_t _count_size(t_env *head) +{ + size_t count; + + count = 0; + while (head) + { + count++; + head = head->next; + } + return (count); +} + +static void _show_env(t_env **array, size_t count) +{ + size_t i; + + i = 0; + while (i < count) + { + if (array[i]->is_exported) + printf("declare -x %s=\"%s\"\n", array[i]->key, array[i]->value); + else + printf("declare -x %s\n", array[i]->key); + i++; + } +} + +int print_sorted_env(t_env *head) +{ + size_t i; + size_t count; + t_env *current; + t_env **array; + + count = _count_size(head); + if (count == 0) + return (EXIT_FAILURE); + array = ft_calloc(count, sizeof(t_env *)); + if (!array) + return (EXIT_FAILURE); + current = head; + i = 0; + while (i < count) + { + array[i++] = current; + current = current->next; + } + _qsort(array, count); + _show_env(array, count); + free(array); + return (EXIT_SUCCESS); +} diff --git a/src/common/error_mes.c b/src/common/error_mes.c new file mode 100644 index 0000000..d848586 --- /dev/null +++ b/src/common/error_mes.c @@ -0,0 +1,26 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* error_mes.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/29 14:11:52 by ttsubo #+# #+# */ +/* Updated: 2025/04/29 14:12:05 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "common.h" + +/** + * @brief Output to STDERR in the format ": \n". + * + * @param name + * @param mes + */ +void error_mes(char *name, char *mes) +{ + ft_putstr_fd(name, STDERR_FILENO); + ft_putstr_fd(": ", STDERR_FILENO); + ft_putendl_fd(mes, STDERR_FILENO); +} diff --git a/src/parser/expand_env_utils.c b/src/common/validate_key.c similarity index 67% rename from src/parser/expand_env_utils.c rename to src/common/validate_key.c index 6eb8571..4df1308 100644 --- a/src/parser/expand_env_utils.c +++ b/src/common/validate_key.c @@ -1,16 +1,16 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* expand_env_utils.c :+: :+: :+: */ +/* validate_key.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2025/04/26 11:15:24 by ttsubo #+# #+# */ -/* Updated: 2025/04/26 11:49:30 by ttsubo ### ########.fr */ +/* Created: 2025/04/29 11:43:40 by ttsubo #+# #+# */ +/* Updated: 2025/04/29 13:53:52 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ -#include "parser.h" +#include "common.h" bool is_key_start(int c) { @@ -21,3 +21,16 @@ bool is_key_char(int c) { return (ft_isalnum(c) || c == '_'); } + +bool is_valid_key(char *str) +{ + size_t i; + + if (!str || !is_key_start(str[0])) + return (false); + i = 1; + while (str[i]) + if (!is_key_char(str[i++])) + return (false); + return (true); +} diff --git a/src/initialize.c b/src/initialize.c index 569a8e4..e613131 100644 --- a/src/initialize.c +++ b/src/initialize.c @@ -6,27 +6,46 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/15 15:42:46 by dayano #+# #+# */ -/* Updated: 2025/04/20 18:39:53 by ttsubo ### ########.fr */ +/* Updated: 2025/04/21 11:17:11 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #include "main.h" -static void _split_key_value(char *env_val, char **key_out, char **val_out) +/** + * @brief envpの構造体の値をセットします。 + * + * @param env_val + * @param node + * @return 0: 失敗 + * @return 1: 成功 + */ +static int _set_envp(char *env_val, t_env *node) { size_t env_len; size_t eq_pos; env_len = ft_strlen(env_val); eq_pos = ft_strlen_until(env_val, '='); - *key_out = NULL; - *val_out = NULL; + node->key = NULL; + node->value = NULL; if (eq_pos == ft_strlen(env_val)) - return ; - *key_out = ft_substr(env_val, 0, eq_pos); - *val_out = ft_substr(env_val, eq_pos + 1, env_len - eq_pos - 1); + return (0); + node->key = ft_substr(env_val, 0, eq_pos); + node->value = ft_substr(env_val, eq_pos + 1, env_len - eq_pos - 1); + if (!node->key || !node->value) + return (0); + node->is_exported = 1; + return (1); } +/** + * @brief Create a envp list object + * + * @param envp + * @return t_env* + * @note TODO: _set_envp失敗時のメモリ開放処理が不足している。envp_list全体のメモリ開放が必要 + */ static t_env *create_envp_list(char **envp) { t_env *head; @@ -42,8 +61,7 @@ static t_env *create_envp_list(char **envp) node = ft_calloc(1, sizeof(t_env)); if (!node) return (NULL); - _split_key_value(envp[i], &(node->key), &(node->value)); - if (!node->key || !node->value) + if (!_set_envp(envp[i], node)) return (free(node), NULL); node->next = NULL; if (!head) diff --git a/test.mk b/test.mk index f10e448..5025bb3 100644 --- a/test.mk +++ b/test.mk @@ -6,7 +6,7 @@ # By: ttsubo +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/04/14 11:48:18 by ttsubo #+# #+# # -# Updated: 2025/04/26 12:06:35 by ttsubo ### ########.fr # +# Updated: 2025/04/29 14:14:45 by ttsubo ### ########.fr # # # # **************************************************************************** # @@ -22,26 +22,29 @@ I_FLG = -Iinc -Ilib/libft L_FLG = -Llib/libft -lft -lreadline # testを追加する場合はSRCにファイル名を追加してください。 -SRC = cd.c exit.c echo.c env.c unset.c tokenizer.c parser.c create_envp.c +SRC = cd.c exit.c echo.c env.c unset.c tokenizer.c export.c OUT = $(addprefix test_, $(SRC:.c=.out)) all: $(OUT) test_%.out: tests/builtin/test_%.c src/builtin/%.c - $(CC) $^ src/builtin/builtin_utils.c $(L_FLG) $(I_FLG) -o $@ + $(CC) $^ src/builtin/builtin_utils.c src/common/*.c $(L_FLG) $(I_FLG) -o $@ test_%.out: tests/tokenizer/test_%.c $(CC) $^ src/tokenizer/*.c $(L_FLG) $(I_FLG) -o $@ +test_export.out: tests/builtin/test_export.c + $(CC) $< src/initialize.c src/builtin/*.c src/common/*.c $(L_FLG) $(I_FLG) -o $@ + test_%.out: tests/parser/test_%.c $(CC) $^ src/parser/*.c src/tokenizer/*.c src/builtin/*.c src/initialize.c $(L_FLG) $(I_FLG) -o $@ test_unset.out: tests/builtin/test_unset.c - $(CC) $< src/initialize.c src/builtin/*.c $(L_FLG) $(I_FLG) -o $@ + $(CC) $< src/initialize.c src/builtin/*.c src/common/*.c $(L_FLG) $(I_FLG) -o $@ test_env.out: tests/builtin/test_env.c - $(CC) $< src/initialize.c src/builtin/*.c $(L_FLG) $(I_FLG) -o $@ + $(CC) $< src/initialize.c src/builtin/*.c src/common/*.c $(L_FLG) $(I_FLG) -o $@ test_create_envp.out: tests/invoke_cmd/test_create_envp.c $(CC) $< src/initialize.c src/invoke_cmd/create_envp.c src/builtin/*.c $(L_FLG) $(I_FLG) -o $@ diff --git a/tests/builtin/test_export.c b/tests/builtin/test_export.c new file mode 100644 index 0000000..76d9bf6 --- /dev/null +++ b/tests/builtin/test_export.c @@ -0,0 +1,75 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* test_export.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/15 11:53:38 by dayano #+# #+# */ +/* Updated: 2025/04/29 13:52:37 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "main.h" +#include +#include + +static size_t _count_words(char **cmds) +{ + size_t i; + + i = 0; + while (cmds[i]) + i++; + return (i); +} + +static void cmds_free(char **cmds) +{ + size_t i; + size_t length; + + i = 0; + length = _count_words(cmds); + while (i < length) + free(cmds[i++]); + free(cmds); +} + +static void _exec_cmd(char **cmds, t_minish *minish) +{ + if (!ft_strcmp(cmds[0], "env")) + builtin_env(_count_words(cmds), cmds, minish); + if (!ft_strcmp(cmds[0], "export")) + builtin_export(_count_words(cmds), cmds, minish); + if (!ft_strcmp(cmds[0], "unset")) + builtin_unset(_count_words(cmds), cmds, minish); +} + +int main(int argc, char **argv, char **envp) +{ + char *line; + char **cmds; + t_minish *minish; + + (void)argc; + (void)argv; + minish = initialize(envp); + while (1) + { + line = readline("minish>"); + if (!line) + break ; + if (line[0] == '\0') + continue ; + cmds = ft_split(line, ' '); + _exec_cmd(cmds, minish); + add_history(line); + cmds_free(cmds); + free(line); + } + cleanup_minish(minish); + rl_clear_history(); + free(line); + return (EXIT_SUCCESS); +}