From 0e520ef31e5d0db4689c335f175baeda3f14a817 Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Sat, 18 Dec 2021 13:45:20 +0100 Subject: [PATCH 1/2] fixed crash in builtin export with "" argument + builtin unset now update PATH --- srcs/builtins/unset.c | 4 +++- srcs/generic/ft_is_posix_name.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/srcs/builtins/unset.c b/srcs/builtins/unset.c index 474417c..813d208 100644 --- a/srcs/builtins/unset.c +++ b/srcs/builtins/unset.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/12/05 17:05:05 by lperrey #+# #+# */ -/* Updated: 2021/12/05 18:14:28 by lperrey ### ########.fr */ +/* Updated: 2021/12/18 13:41:15 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,6 +27,8 @@ int builtin_unset(int argc, char *argv[], t_all *c) { if (unset_env_var(argv[i]) == EXIT_FAILURE) exit_value = EXIT_FAILURE; + if (ft_strncmp(argv[i], "PATH", 4 + 1) == 0) + c->path = retrieve_path(); i++; } return (exit_value); diff --git a/srcs/generic/ft_is_posix_name.c b/srcs/generic/ft_is_posix_name.c index 20d9df4..e2c91e7 100644 --- a/srcs/generic/ft_is_posix_name.c +++ b/srcs/generic/ft_is_posix_name.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/08 09:25:35 by lperrey #+# #+# */ -/* Updated: 2021/12/16 03:50:43 by lperrey ### ########.fr */ +/* Updated: 2021/12/18 13:31:11 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,6 +16,8 @@ int ft_is_posix_name(char *str) { unsigned int i; + if (!str) + return (0); if (str[0] != '_' && !ft_isalpha(str[0])) return (0); i = 1; From 49099a0abd583d29a66107f1e4a9e018fb4d7bfa Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Sat, 18 Dec 2021 15:25:45 +0100 Subject: [PATCH 2/2] shell _script() use gnl() instead of readline() to prevent copy of input to terminal. + here_doc_write_script() for nontty STDIN --- srcs/init/init.c | 4 +- srcs/misc/free.c | 7 +- srcs/misc/signals.c | 3 +- srcs/parsing/redirections/here_doc.c | 151 +++++++++++++++++---------- srcs/shell_script.c | 22 ++-- 5 files changed, 122 insertions(+), 65 deletions(-) diff --git a/srcs/init/init.c b/srcs/init/init.c index 70277fc..8410826 100644 --- a/srcs/init/init.c +++ b/srcs/init/init.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/08 09:22:12 by lperrey #+# #+# */ -/* Updated: 2021/12/18 04:53:11 by lperrey ### ########.fr */ +/* Updated: 2021/12/18 14:22:20 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,6 +19,7 @@ int handle_argv(t_all *c, char *argv[]); int init(t_all *c, char *argv[]) { ft_bzero(c, sizeof (*c)); + set_signals_behaviour(); init_readline(); environ = ft_dup_2d_arr(environ, (t_dup_f)ft_strdup); if (!environ) @@ -28,6 +29,5 @@ int init(t_all *c, char *argv[]) return (ft_reti_perror(0, "init_shlvl()")); if (!handle_argv(c, argv)) return (0); - set_signals_behaviour(); return (1); } diff --git a/srcs/misc/free.c b/srcs/misc/free.c index 0e8c95b..c950522 100644 --- a/srcs/misc/free.c +++ b/srcs/misc/free.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/10 23:53:17 by lperrey #+# #+# */ -/* Updated: 2021/12/16 06:35:03 by lperrey ### ########.fr */ +/* Updated: 2021/12/18 14:15:13 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -20,7 +20,10 @@ int exit_free(t_all *c, int exit_status) ft_free_2d_arr(environ); ft_free_2d_arr(c->path); free_pipeline(&c->pipeline); - rl_clear_history(); + if (!isatty(STDIN_FILENO)) + gnl(STDIN_FILENO, NULL, 1); + else + rl_clear_history(); close_stdio(); exit(exit_status); } diff --git a/srcs/misc/signals.c b/srcs/misc/signals.c index e21e689..a15e6e6 100644 --- a/srcs/misc/signals.c +++ b/srcs/misc/signals.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/23 18:56:53 by lperrey #+# #+# */ -/* Updated: 2021/11/26 21:45:22 by lperrey ### ########.fr */ +/* Updated: 2021/12/18 14:21:47 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -35,4 +35,5 @@ void set_signals_behaviour(void) ft_bzero(&signal_behaviour, sizeof signal_behaviour); signal_behaviour.sa_handler = SIG_IGN; sigaction(SIGQUIT, &signal_behaviour, NULL); + sigaction(SIGINT, &signal_behaviour, NULL); } diff --git a/srcs/parsing/redirections/here_doc.c b/srcs/parsing/redirections/here_doc.c index f705bc8..c5d9693 100644 --- a/srcs/parsing/redirections/here_doc.c +++ b/srcs/parsing/redirections/here_doc.c @@ -6,25 +6,22 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */ -/* Updated: 2021/12/11 20:42:27 by lperrey ### ########.fr */ +/* Updated: 2021/12/18 15:24:25 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ #include "minishell.h" -#define TMP_HERE_DOC "/tmp/minishell_here_doc" - static int here_doc_write(char *delimiter, int doc_fd); +static int here_doc_write_interactive(char *delimiter, int doc_fd); +static int here_doc_write_script(char *delimiter, int doc_fd); +static int event_hook_empty(void); + +#define TMP_HERE_DOC "/tmp/minishell_here_doc" +#define WARNING_EOF "warning: here-document delimited by end-of-file (wanted `" int here_doc(char *delimiter) { - // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04 - // https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02 - /* If any part of word is quoted, - the delimiter shall be formed by performing quote removal on word, - and the here-document lines shall not be expanded. - Otherwise, the delimiter shall be the word itself. */ - // TODO : A voir si on fait les expansions de variables dans le here_doc. int here_doc; int ret; @@ -52,65 +49,113 @@ int here_doc(char *delimiter) return (here_doc); } -int void_func_return_readline(void) -{ - return (0); -} - -// rl_done -// Setting this to a non-zero value causes Readline to return the current line -// immediately -// rl_event_hook -// If non-zero, this is the address of a function to call periodically when Readline -// is waiting for terminal input. By default, this will be called at most ten times -// a second if there is no keyboard input -// from stackoverflow (https://stackoverflow.com/questions/53165704/readline-c-force-return-of-certain-text-in-readline) -// "rl_done is only checked in the event loop. When you give it a null event hook -// function, it checks the rl_done and exits" -// -// rl_signal_event_hook -// If non-zero, this is the address of a function to call if a read system call is -// interrupted when Readline is reading terminal input. static int here_doc_write(char *delimiter, int doc_fd) { - char *line; - size_t line_count; + int ret; struct sigaction signal_action; - ft_bzero(&signal_action, sizeof(signal_action)); - signal_action.sa_handler = sigint_handler_heredoc; - sigaction(SIGINT, &signal_action, NULL); + if (isatty(STDIN_FILENO)) + { + ft_bzero(&signal_action, sizeof(signal_action)); + signal_action.sa_handler = sigint_handler_heredoc; + sigaction(SIGINT, &signal_action, NULL); + rl_event_hook = event_hook_empty; + ret = here_doc_write_interactive(delimiter, doc_fd); + rl_event_hook = NULL; + signal_action.sa_handler = SIG_IGN; + sigaction(SIGINT, &signal_action, NULL); + } + else + { + ret = here_doc_write_script(delimiter, doc_fd); + } + return (ret); +} + +static int here_doc_write_interactive(char *delimiter, int doc_fd) +{ + char *line; + + line = NULL; g_switch_heredoc_sigint = 0; - rl_event_hook = void_func_return_readline; - //rl_signal_event_hook = void_func_return_readline; - line_count = 0; while (1) { - line_count++; - line = NULL; line = readline("> "); if (g_switch_heredoc_sigint == 1) return (set_last_exit_status(EXIT_SIGNAL + SIGINT)); if (!line) - { // TODO : error print wrapper - ft_putstr_fd("minishell: ", 2); - ft_putstr_fd("warning: here-document at line ", 2); - ft_putnbr_fd(line_count, 2); - ft_putstr_fd(" delimited by end-of-file (wanted `", 2); - ft_putstr_fd(delimiter, 2); - ft_putstr_fd("')\n", 2); - return (0); - } + return (shell_error(WARNING_EOF, delimiter, "')", 0)); if (ft_strncmp(line, delimiter, ft_strlen(line) + 1) == 0) // Ou ft_strlen(delimiter) + 1 ? Ça devrais être identique et ça peux se calculer une seul fois. break ; if (write(doc_fd, line, ft_strlen(line)) == -1) - return (ft_reti_perror_free(-1, line, free, "write() "TMP_HERE_DOC)); + return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC)); if (write(doc_fd, "\n", 1) == -1) - return (ft_reti_perror_free(-1, line, free, "write() "TMP_HERE_DOC)); - free(line); + return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC)); + ft_free_null(&line); } free(line); - signal_action.sa_handler = SIG_IGN; - sigaction(SIGINT, &signal_action, NULL); return (0); } + +static int here_doc_write_script(char *delimiter, int doc_fd) +{ + char *line; + int ret; + + line = NULL; + ret = 1; + while (ret) + { + ret = gnl(STDIN_FILENO, &line, 0); + if (ret == -1) + return (ft_reti_perror_free(-1, line, free, "gnl() STDIN")); + if (ft_strncmp(line, delimiter, ft_strlen(line) + 1) == 0) // Ou ft_strlen(delimiter) + 1 ? Ça devrais être identique et ça peux se calculer une seul fois. + break ; + if (write(doc_fd, line, ft_strlen(line)) == -1) + return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC)); + if ((ret || line[0]) && write(doc_fd, "\n", 1) == -1) + return (ft_reti_perror_free(-1, line, free, "write "TMP_HERE_DOC)); + ft_free_null(&line); + } + if (!line && ret == 0) + shell_error(WARNING_EOF, delimiter, "')", 0); + free(line); + return (0); +} + +static int event_hook_empty(void) +{ + return (0); +} + +/* +https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html +#tag_18_07_04 +https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html +#tag_18_02 +*/ +/* If any part of word is quoted, +the delimiter shall be formed by performing quote removal on word, +and the here-document lines shall not be expanded. +Otherwise, the delimiter shall be the word itself. */ +// TODO Bonus: expansions in here_doc. + +/* +** rl_done +** Setting this to a non-zero value causes Readline +** to return the current line immediately. +** rl_event_hook +** If non-zero, this is the address of a function to call periodically +** when Readline is waiting for terminal input. +** By default, this will be called at most +** ten times a second if there is no keyboard input. +** +** https://stackoverflow.com/questions/53165704/ +** readline-c-force-return-of-certain-text-in-readline +** "rl_done is only checked in the event loop. When you give it +** a null event hook function, it checks the rl_done and exits" +** +** rl_signal_event_hook +** If non-zero, this is the address of a function to call if a read +** system call is interrupted when Readline is reading terminal input. +*/ diff --git a/srcs/shell_script.c b/srcs/shell_script.c index 23e28a4..bc8e1e6 100644 --- a/srcs/shell_script.c +++ b/srcs/shell_script.c @@ -6,7 +6,7 @@ /* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2021/10/26 23:47:44 by lperrey #+# #+# */ -/* Updated: 2021/12/18 08:51:46 by lperrey ### ########.fr */ +/* Updated: 2021/12/18 15:15:30 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -24,6 +24,8 @@ void shell_script(t_all *c) { free(line_input); line_input = read_input_script(c); + if (!line_input) + break ; if (line_input && *line_input) { c->token_list = lexing(line_input); @@ -39,7 +41,6 @@ void shell_script(t_all *c) exit_signal(c); } } - free(line_input); exit_free(c, get_last_exit_status()); } @@ -47,16 +48,23 @@ static char *read_input_script(t_all *c) { char *line_input; struct sigaction signal_behaviour; + int ret; ft_bzero(&signal_behaviour, sizeof signal_behaviour); - signal_behaviour.sa_handler = sigint_handler_interactive; - sigaction(SIGINT, &signal_behaviour, NULL); - rl_event_hook = NULL; - line_input = readline(NULL); signal_behaviour.sa_handler = SIG_IGN; sigaction(SIGINT, &signal_behaviour, NULL); - if (!line_input) + line_input = NULL; + ret = gnl(STDIN_FILENO, &line_input, 0); + if (ret == -1) + { + free(line_input); + return (NULL); + } + if (!line_input[0] && ret == 0) + { + free(line_input); exit_free(c, get_last_exit_status()); + } return (line_input); }