diff --git a/.gitignore b/.gitignore index 9c0689d..a9f1739 100644 --- a/.gitignore +++ b/.gitignore @@ -53,4 +53,5 @@ dkms.conf # minishell custom minishell -.vscode/ \ No newline at end of file +.vscode/ +*.log \ No newline at end of file diff --git a/Makefile b/Makefile index 18be972..75dfa5f 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: ttsubo +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/04/03 12:55:20 by ttsubo #+# #+# # -# Updated: 2025/05/08 18:21:27 by ttsubo ### ########.fr # +# Updated: 2025/05/12 10:00:36 by ttsubo ### ########.fr # # # # **************************************************************************** # @@ -60,10 +60,10 @@ 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 is_quote.c free_functions.c free_functions_2.c +COMMON_SRC = validate_key.c close_fd.c error_mes.c is_quote.c free_functions.c free_functions_2.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 + redirect.c fds.c wait_pipeline.c pipeline_exit.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 \ diff --git a/inc/common/common.h b/inc/common/common.h index deb9201..c919e96 100644 --- a/inc/common/common.h +++ b/inc/common/common.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/29 11:44:19 by ttsubo #+# #+# */ -/* Updated: 2025/05/06 19:19:56 by ttsubo ### ########.fr */ +/* Updated: 2025/05/11 16:33:36 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,5 +27,6 @@ bool is_valid_key(char *str); bool is_quote(char c); bool has_closing_quote(const char *s, char quote, size_t i); void error_mes(char *name, char *mes); +void close_fd(int std_fileno, int minish_std); #endif \ No newline at end of file diff --git a/inc/common/struct.h b/inc/common/struct.h index ecf04b1..3e6c0bf 100644 --- a/inc/common/struct.h +++ b/inc/common/struct.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/15 17:10:22 by dayano #+# #+# */ -/* Updated: 2025/05/08 16:53:17 by ttsubo ### ########.fr */ +/* Updated: 2025/05/11 16:24:51 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -41,6 +41,8 @@ typedef struct s_env typedef struct s_minish { + int org_stdin; + int org_stdout; t_env *env; int last_status; } t_minish; diff --git a/inc/invoke_cmd/invoke_command.h b/inc/invoke_cmd/invoke_command.h index 7bdd327..f1bac9b 100644 --- a/inc/invoke_cmd/invoke_command.h +++ b/inc/invoke_cmd/invoke_command.h @@ -6,7 +6,7 @@ /* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/20 21:21:13 by dayano #+# #+# */ -/* Updated: 2025/05/04 20:45:51 by ttsubo ### ########.fr */ +/* Updated: 2025/05/12 09:56:59 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,10 +17,11 @@ # include "create_envp.h" # include "exec_pipeline.h" # include "execute_cmd.h" +# include "pipeline_exit.h" # include "pipeline_helper.h" # include "redirect.h" -# include # include +# include int invoke_commands(t_cmd *cmd_head, t_minish *minish); int exec_unit_builtin(t_cmd *cmd, t_minish *minish); diff --git a/inc/invoke_cmd/pipeline_exit.h b/inc/invoke_cmd/pipeline_exit.h new file mode 100644 index 0000000..3f38421 --- /dev/null +++ b/inc/invoke_cmd/pipeline_exit.h @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* pipeline_exit.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/12 09:56:19 by ttsubo #+# #+# */ +/* Updated: 2025/05/12 10:01:23 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef PIPELINE_EXIT_H +# define PIPELINE_EXIT_H + +# include "struct.h" + +void pipeline_exit(unsigned int status, t_minish *minish); + +#endif \ No newline at end of file diff --git a/src/builtin/exit.c b/src/builtin/exit.c index 409c370..4d1a2f6 100644 --- a/src/builtin/exit.c +++ b/src/builtin/exit.c @@ -3,15 +3,22 @@ /* ::: :::::::: */ /* exit.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dayano +#+ +:+ +#+ */ +/* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/13 21:20:48 by dayano #+# #+# */ -/* Updated: 2025/05/04 18:34:59 by dayano ### ########.fr */ +/* Updated: 2025/05/11 16:47:12 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ #include "main.h" +static void _exec_exit(unsigned int status, t_minish *minish) +{ + close_fd(STDIN_FILENO, minish->org_stdin); + close_fd(STDOUT_FILENO, minish->org_stdout); + exit(status); +} + int builtin_exit(int argc, char *argv[], t_minish *minish) { long status; @@ -23,14 +30,15 @@ int builtin_exit(int argc, char *argv[], t_minish *minish) if (printf("exit\n") < 0) return (perror("printf"), EXIT_FAILURE); if (argc == 1) - exit(EXIT_SUCCESS); + _exec_exit(EXIT_SUCCESS, minish); errno = 0; status = ft_strtol(argv[1], &endptr, 10); if (errno != 0 || *endptr != '\0') { ft_putstr_fd("minishell: exit: ", STDERR_FILENO); error_mes(argv[1], "numeric argument required"); - exit(INCORRECT_USAGE); + _exec_exit(INCORRECT_USAGE, minish); } - exit((unsigned int)status); + _exec_exit((unsigned int)status, minish); + return (EXIT_SUCCESS); } diff --git a/src/common/close_fd.c b/src/common/close_fd.c new file mode 100644 index 0000000..5259b45 --- /dev/null +++ b/src/common/close_fd.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* close_fd.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/11 16:29:20 by ttsubo #+# #+# */ +/* Updated: 2025/05/11 16:33:17 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "common.h" + +void close_fd(int std_fileno, int minish_std) +{ + close(std_fileno); + dup2(minish_std, std_fileno); + close(minish_std); +} diff --git a/src/invoke_cmd/exec_pipeline.c b/src/invoke_cmd/exec_pipeline.c index aa64f9d..30578a5 100644 --- a/src/invoke_cmd/exec_pipeline.c +++ b/src/invoke_cmd/exec_pipeline.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* exec_pipeline.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dayano +#+ +:+ +#+ */ +/* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/21 13:14:15 by dayano #+# #+# */ -/* Updated: 2025/05/09 16:49:12 by dayano ### ########.fr */ +/* Updated: 2025/05/12 10:00:14 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -59,7 +59,7 @@ static pid_t _fork_command(t_cmd *cmd, t_cmd *cmd_head, t_pipe_io *pipefds, if (pid < 0) { print_error(cmd->argv[0]); - exit(EX_OSERR); + pipeline_exit(EX_OSERR, minish); } if (pid > 0) return (_setup_process_signals(SIG_IGN), pid); @@ -68,12 +68,13 @@ static pid_t _fork_command(t_cmd *cmd, t_cmd *cmd_head, t_pipe_io *pipefds, _setup_process_signals(SIG_DFL); if ((cmd->next != NULL) && is_redirect(cmd->next)) if (!redirect(cmd->next)) - exit(EXIT_FAILURE); + pipeline_exit(EXIT_FAILURE, minish); if (is_builtin(cmd)) - exit(execute_builtin(cmd, minish)); + pipeline_exit(execute_builtin(cmd, minish), minish); execute_cmd(cmd, minish); print_error(cmd->argv[0]); - exit(EXIT_FAILURE); + pipeline_exit(EXIT_FAILURE, minish); + return (EXIT_FAILURE); } /** diff --git a/src/invoke_cmd/invoke_command.c b/src/invoke_cmd/invoke_command.c index c89c643..1a08f1e 100644 --- a/src/invoke_cmd/invoke_command.c +++ b/src/invoke_cmd/invoke_command.c @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* invoke_command.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: dayano +#+ +:+ +#+ */ +/* By: ttsubo +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/20 21:19:33 by dayano #+# #+# */ -/* Updated: 2025/05/09 16:14:34 by dayano ### ########.fr */ +/* Updated: 2025/05/11 16:32:46 by ttsubo ### ########.fr */ /* */ /* ************************************************************************** */ @@ -95,12 +95,10 @@ int exec_unit_builtin(t_cmd *cmd, t_minish *minish) int invoke_commands(t_cmd *cmd_head, t_minish *minish) { int status; - int original_stdin; - int original_stdout; status = 0; - original_stdin = dup(STDIN_FILENO); - original_stdout = dup(STDOUT_FILENO); + minish->org_stdin = dup(STDIN_FILENO); + minish->org_stdout = dup(STDOUT_FILENO); if (is_unit_builtin(cmd_head)) status = exec_unit_builtin(cmd_head, minish); else @@ -109,11 +107,7 @@ int invoke_commands(t_cmd *cmd_head, t_minish *minish) status = wait_pipeline(cmd_head); minish_signal(); } - close(STDIN_FILENO); - dup2(original_stdin, STDIN_FILENO); - close(original_stdin); - close(STDOUT_FILENO); - dup2(original_stdout, STDOUT_FILENO); - close(original_stdout); + close_fd(STDIN_FILENO, minish->org_stdin); + close_fd(STDOUT_FILENO, minish->org_stdout); return (status); } diff --git a/src/invoke_cmd/pipeline_exit.c b/src/invoke_cmd/pipeline_exit.c new file mode 100644 index 0000000..bceb7bb --- /dev/null +++ b/src/invoke_cmd/pipeline_exit.c @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* pipeline_exit.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: ttsubo +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/24 14:29:29 by dayano #+# #+# */ +/* Updated: 2025/05/12 09:55:49 by ttsubo ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "main.h" + +void pipeline_exit(unsigned int status, t_minish *minish) +{ + close_fd(STDIN_FILENO, minish->org_stdin); + close_fd(STDOUT_FILENO, minish->org_stdout); + exit(status); +} diff --git a/tests/invoke_cmd/test_fd_closed.sh b/tests/invoke_cmd/test_fd_closed.sh new file mode 100755 index 0000000..49922a9 --- /dev/null +++ b/tests/invoke_cmd/test_fd_closed.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +TARGET="./minishell" + +has_noninherited_fd() { + local log="$1" + local prev_line + + while IFS= read -r line; do + # "Open file descriptor" を見つけたら次の行をチェック + if [[ "$line" == *"Open file descriptor"* ]]; then + read -r next_line || break + if [[ "$next_line" != *""* ]]; then + return 1 # NG + fi + fi + done < "$log" + + return 0 # OK(inheritedなものしかなかった) +} + + +run_test() { + name="$1" + input="$2" + LOG="$(mktemp)" + + echo -n "$name ... " + + echo -e "$input" | valgrind --track-fds=yes --log-file="$LOG" "$TARGET" > /dev/null + + if has_noninherited_fd "$LOG"; then + echo "OK" + else + echo "NG" + grep -A 1 "Open file descriptor" "$LOG" + fi +} + +echo "== FD Leak Test ==" + +run_test "test1: Ctrl+D で終了" "" +run_test "test2: exit コマンドで終了" "exit" +run_test "test3: echo hello → exit" "echo hello\nexit" +run_test "test4: ls | cat → exit" "ls | cat\nexit" +run_test "test5: echo 1 | cat | wc → exit" "echo 1 | cat | wc\nexit"