From ce8e06f66549e29f34071c1f8e5f6fe0d020f253 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kha=C3=AFs=20COLIN?= Date: Mon, 21 Apr 2025 08:25:49 +0200 Subject: [PATCH] feat(redir): fieldsplit redir target, and handle ambiguous redirects --- Makefile | 1 + src/executing/simple_cmd/simple_cmd_execute.c | 5 +- src/minishell.h | 4 +- src/parser/cmd/cmd_destroy.c | 3 +- src/postprocess/expansion/expand_vars.c | 10 +-- src/postprocess/fieldsplit/fieldsplit.c | 7 +- src/postprocess/fieldsplit/fieldsplit.h | 6 +- .../fieldsplit/redirect_fieldsplit.c | 71 +++++++++++++++++++ .../fieldsplit/redirect_fieldsplit.h | 20 ++++++ test.sh | 21 ++++++ 10 files changed, 136 insertions(+), 12 deletions(-) create mode 100644 src/postprocess/fieldsplit/redirect_fieldsplit.c create mode 100644 src/postprocess/fieldsplit/redirect_fieldsplit.h diff --git a/Makefile b/Makefile index e5d657f..276cdf6 100644 --- a/Makefile +++ b/Makefile @@ -96,6 +96,7 @@ srcs = \ src/postprocess/expansion/expand_vars.c \ src/postprocess/expansion/expand_wildcard.c \ src/postprocess/fieldsplit/fieldsplit.c \ + src/postprocess/fieldsplit/redirect_fieldsplit.c \ src/sig/sig.c \ src/sig/sig_handlers.c \ src/subst/path_split.c \ diff --git a/src/executing/simple_cmd/simple_cmd_execute.c b/src/executing/simple_cmd/simple_cmd_execute.c index 79043a0..5e7d59b 100644 --- a/src/executing/simple_cmd/simple_cmd_execute.c +++ b/src/executing/simple_cmd/simple_cmd_execute.c @@ -6,7 +6,7 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/27 16:21:56 by khais #+# #+# */ -/* Updated: 2025/04/18 14:03:39 by khais ### ########.fr */ +/* Updated: 2025/04/21 08:45:05 by khais ### ########.fr */ /* */ /* ************************************************************************** */ @@ -44,7 +44,10 @@ static t_simple_cmd *post_process_command(t_simple_cmd *cmd, t_minishell *app) if (simple_cmd_expand_vars(cmd, app) == NULL) return (NULL); if (simple_cmd_fieldsplit(cmd) == NULL) + { + app->last_return_value = 1; return (NULL); + } if (simple_cmd_expand_wildcards(cmd) == NULL) return (NULL); if (simple_cmd_remove_quotes(cmd) == NULL) diff --git a/src/minishell.h b/src/minishell.h index 983760a..e7ff80a 100644 --- a/src/minishell.h +++ b/src/minishell.h @@ -6,7 +6,7 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/09 14:02:47 by khais #+# #+# */ -/* Updated: 2025/04/17 11:08:59 by khais ### ########.fr */ +/* Updated: 2025/04/21 10:59:33 by khais ### ########.fr */ /* */ /* ************************************************************************** */ @@ -43,6 +43,8 @@ typedef struct s_redirect int open_flags; int c_flags; // flags for third arg of open (case O_CREAT). t_redirectee redirectee; // fd or filename where to redirect source. + // used between var expansion and fieldsplit + char *unexpanded_filename; char *here_doc_eof; // The here-document limiter if relevant. } t_redirect; diff --git a/src/parser/cmd/cmd_destroy.c b/src/parser/cmd/cmd_destroy.c index dbc0494..387603d 100644 --- a/src/parser/cmd/cmd_destroy.c +++ b/src/parser/cmd/cmd_destroy.c @@ -6,7 +6,7 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/09 16:53:02 by khais #+# #+# */ -/* Updated: 2025/04/17 10:20:38 by khais ### ########.fr */ +/* Updated: 2025/04/21 10:55:02 by khais ### ########.fr */ /* */ /* ************************************************************************** */ @@ -25,6 +25,7 @@ void redirect_destroy(t_redirect *redirect) free(redirect->here_doc_eof); if (redirect->type != FT_HEREDOC) worddesc_destroy(redirect->redirectee.filename); + free(redirect->unexpanded_filename); free(redirect); redirect = next; } diff --git a/src/postprocess/expansion/expand_vars.c b/src/postprocess/expansion/expand_vars.c index 4117c14..43036cc 100644 --- a/src/postprocess/expansion/expand_vars.c +++ b/src/postprocess/expansion/expand_vars.c @@ -6,7 +6,7 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/01 13:34:51 by khais #+# #+# */ -/* Updated: 2025/04/21 08:15:45 by khais ### ########.fr */ +/* Updated: 2025/04/21 11:09:04 by khais ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,23 +14,23 @@ #include "../../ft_errno.h" #include "../../subst/subst.h" #include "../../parser/redirect/redirect.h" +#include "../../parser/redirect/redirect_debug.h" #include "../../parser/cmd/cmd_destroy.h" -static t_redirect *redirection_var_expansion(t_redirect *redirects, +static t_redirect *redirection_var_expansion(t_redirect *in_list, t_minishell *app) { - t_redirect *in_list; t_redirect *out_list; t_redirect *current; - in_list = redirects; out_list = NULL; - (void)app; while (in_list) { current = redirect_pop(&in_list); if (current->type != FT_HEREDOC) { + current->unexpanded_filename + = ft_strdup(current->redirectee.filename->word); current->redirectee.filename = word_var_expansion(current->redirectee.filename, app); if (current->redirectee.filename == NULL diff --git a/src/postprocess/fieldsplit/fieldsplit.c b/src/postprocess/fieldsplit/fieldsplit.c index d592d69..b8d9fcf 100644 --- a/src/postprocess/fieldsplit/fieldsplit.c +++ b/src/postprocess/fieldsplit/fieldsplit.c @@ -6,13 +6,14 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/03 15:48:52 by khais #+# #+# */ -/* Updated: 2025/04/15 11:59:23 by khais ### ########.fr */ +/* Updated: 2025/04/21 11:56:26 by khais ### ########.fr */ /* */ /* ************************************************************************** */ #include "fieldsplit.h" #include "../../buffer/buffer.h" #include "../../parser/matchers/blank.h" +#include "redirect_fieldsplit.h" #include static bool should_delimit(t_worddesc *original, size_t i) @@ -34,7 +35,7 @@ static void fieldsplit_delimit(t_buffer *word, t_buffer *marker, free(marker); } -static t_wordlist *minishell_fieldsplit(t_worddesc *original, +t_wordlist *minishell_fieldsplit(t_worddesc *original, t_wordlist **outlist) { size_t i; @@ -93,5 +94,7 @@ t_simple_cmd *simple_cmd_fieldsplit(t_simple_cmd *cmd) return (NULL); if (wordlist_fieldsplit(&cmd->words) == NULL) return (NULL); + if (redirect_fieldsplit(cmd) == NULL) + return (NULL); return (cmd); } diff --git a/src/postprocess/fieldsplit/fieldsplit.h b/src/postprocess/fieldsplit/fieldsplit.h index 18dee9d..8223ca8 100644 --- a/src/postprocess/fieldsplit/fieldsplit.h +++ b/src/postprocess/fieldsplit/fieldsplit.h @@ -6,15 +6,17 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/03 15:46:56 by khais #+# #+# */ -/* Updated: 2025/04/03 16:06:23 by khais ### ########.fr */ +/* Updated: 2025/04/21 11:57:40 by khais ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef FIELDSPLIT_H # define FIELDSPLIT_H -# include "../../parser/simple_cmd/simple_cmd.h" +# include "../../minishell.h" t_simple_cmd *simple_cmd_fieldsplit(t_simple_cmd *cmd); +t_wordlist *minishell_fieldsplit(t_worddesc *original, + t_wordlist **outlist); #endif // FIELDSPLIT_H diff --git a/src/postprocess/fieldsplit/redirect_fieldsplit.c b/src/postprocess/fieldsplit/redirect_fieldsplit.c new file mode 100644 index 0000000..9665a8e --- /dev/null +++ b/src/postprocess/fieldsplit/redirect_fieldsplit.c @@ -0,0 +1,71 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect_fieldsplit.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: khais +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/21 11:54:16 by khais #+# #+# */ +/* Updated: 2025/04/21 11:57:50 by khais ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "redirect_fieldsplit.h" +#include "fieldsplit.h" +#include "../../parser/redirect/redirect.h" +#include "../../parser/cmd/cmd_destroy.h" +#include + +static void redirect_fieldsplit_cleanup(t_redirect *in_list, + t_redirect *out_list, t_redirect *current, t_simple_cmd *cmd) +{ + redirect_destroy(in_list); + redirect_destroy(out_list); + redirect_destroy(current); + cmd->redirections = NULL; +} + +static t_simple_cmd *redirect_fieldsplit_single(t_redirect *in_list, + t_redirect *out_list, t_redirect *current, t_simple_cmd *cmd) +{ + t_wordlist *out; + + if (minishell_fieldsplit(current->redirectee.filename, &out) == NULL) + { + redirect_fieldsplit_cleanup(in_list, out_list, current, cmd); + return (wordlist_destroy(out), NULL); + } + worddesc_destroy(current->redirectee.filename); + current->redirectee.filename = wordlist_pop(&out); + if (out != NULL) + { + ft_dprintf(STDERR_FILENO, "minishell: %s: ambiguous redirect\n", + current->unexpanded_filename); + redirect_fieldsplit_cleanup(in_list, out_list, current, cmd); + return (wordlist_destroy(out), NULL); + } + return (cmd); +} + +t_simple_cmd *redirect_fieldsplit(t_simple_cmd *cmd) +{ + t_redirect *in_list; + t_redirect *out_list; + t_redirect *current; + + in_list = cmd->redirections; + out_list = NULL; + while (in_list != NULL) + { + current = redirect_pop(&in_list); + if (current->type != FT_HEREDOC) + { + if (redirect_fieldsplit_single(in_list, out_list, current, cmd) + == NULL) + return (NULL); + } + out_list = t_redirect_add_back(&out_list, current); + } + cmd->redirections = out_list; + return (cmd); +} diff --git a/src/postprocess/fieldsplit/redirect_fieldsplit.h b/src/postprocess/fieldsplit/redirect_fieldsplit.h new file mode 100644 index 0000000..b6c8cbc --- /dev/null +++ b/src/postprocess/fieldsplit/redirect_fieldsplit.h @@ -0,0 +1,20 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* redirect_fieldsplit.h :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: khais +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/04/21 11:53:54 by khais #+# #+# */ +/* Updated: 2025/04/21 11:54:42 by khais ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef REDIRECT_FIELDSPLIT_H +# define REDIRECT_FIELDSPLIT_H + +# include "../../minishell.h" + +t_simple_cmd *redirect_fieldsplit(t_simple_cmd *cmd); + +#endif // REDIRECT_FIELDSPLIT_H diff --git a/test.sh b/test.sh index cec004f..2c9d130 100755 --- a/test.sh +++ b/test.sh @@ -820,4 +820,25 @@ outfile hello there EOF +when_run <<"EOF" "ambiguous redirect" +export target="outfile1 outfile2" +echo hello > $target +echo $? +echo hi >> $target +echo $? +cat < $target +echo $? +ls +echo $? +EOF +expecting <<"EOF" +minishell: $target: ambiguous redirect +1 +minishell: $target: ambiguous redirect +1 +minishell: $target: ambiguous redirect +1 +0 +EOF + finalize