From 7c6d061c6c8821a1cf346cb25087904c8cb72d59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kha=C3=AFs=20COLIN?= Date: Tue, 11 Mar 2025 13:30:40 +0100 Subject: [PATCH] here_doc: handle input with correct end marker --- Makefile | 2 + src/executing/here_doc/here_doc.c | 113 +++++++++++++++-------- src/executing/here_doc/here_doc.h | 3 +- src/executing/here_doc/random_filename.c | 56 +++++++++++ src/executing/here_doc/strip_newline.c | 32 +++++++ tests/here_doc_input_plus_eof.input | 2 + tests/test_here_doc.c | 21 ++++- tests/testutil.c | 6 +- 8 files changed, 191 insertions(+), 44 deletions(-) create mode 100644 src/executing/here_doc/random_filename.c create mode 100644 src/executing/here_doc/strip_newline.c create mode 100644 tests/here_doc_input_plus_eof.input diff --git a/Makefile b/Makefile index d410f9a..8178cc3 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,8 @@ srcs = \ src/env/env_manip.c \ src/env/envp.c \ src/executing/here_doc/here_doc.c \ + src/executing/here_doc/random_filename.c \ + src/executing/here_doc/strip_newline.c \ src/ft_errno.c \ src/get_command.c \ src/parser/command_list/command_list_builder.c \ diff --git a/src/executing/here_doc/here_doc.c b/src/executing/here_doc/here_doc.c index 3a64a13..36efaa7 100644 --- a/src/executing/here_doc/here_doc.c +++ b/src/executing/here_doc/here_doc.c @@ -6,7 +6,7 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/07 11:42:29 by khais #+# #+# */ -/* Updated: 2025/03/11 11:38:42 by khais ### ########.fr */ +/* Updated: 2025/03/11 13:31:15 by khais ### ########.fr */ /* */ /* ************************************************************************** */ @@ -14,46 +14,75 @@ #include #include #include -#include "../../ft_errno.h" -#include "../../buffer/buffer.h" -#include "libft/libft.h" +#include "libft.h" /* -** Genereate a random filename for use by here_doc +** - check that arguments are not invalid +** - create a random filename +** - create the file ** -** The filename will be of the form -** /tmp/minishell_here_doc_XXXXXXXXXXX -** where each X is a random alphanumerical char -** -** Random bytes are generated by reading from /dev/urandom -** -** Return NULL and sets ft_errno on error +** do these operations, with error checking */ -char *here_doc_random_filename(void) +static int setup_here_doc(t_worddesc *marker, int infd, char **filename) { - int randomfd; - char buf[1]; - t_buffer *filename; + int outfd; - randomfd = open("/dev/urandom", O_RDONLY); - if (randomfd < 0) - return (ft_errno(FT_EERRNO), NULL); - filename = ft_buffer_new(); + if (infd < 0 || marker == NULL || marker->word == NULL) + return (-1); + *filename = here_doc_random_filename(); if (filename == NULL) - return (close(randomfd), ft_errno(FT_EERRNO), NULL); - filename = ft_buffer_push_buf(filename, "/tmp/minishell_here_doc_", 24); - while (filename->length < 35) + return (-1); + outfd = open(*filename, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR); + if (outfd < 0) + return (free(*filename), -1); + return (outfd); +} + +/* +** output line to outfd, get the next line from infd, and return it +*/ +static char *output_line_and_next(int infd, int outfd, char *line) +{ + ft_dprintf(outfd, "%s", line); + free(line); + line = get_next_line(infd); + return (line); +} + +/* +** seek filename to start, unlink filename, and return new outfd +*/ +static int finalize(int outfd, char *filename) +{ + close(outfd); + outfd = open(filename, O_RDONLY, 0); + unlink(filename); + free(filename); + return (outfd); +} + +/* +** check if line corresponds to marker +** +** if true is returned, line has been freed +*/ +static bool is_marker(char *line, t_worddesc *marker) +{ + char *cleanline; + int res; + + cleanline = strip_newline(line); + if (cleanline == NULL) { - if (read(randomfd, buf, 1) != 1) - { - ft_buffer_free(filename); - return (close(randomfd), ft_errno(FT_EERRNO), NULL); - } - if (ft_isalnum(buf[0])) - filename = ft_buffer_pushchar(filename, buf[0]); + ft_dprintf(STDERR_FILENO, "Allocation failure!\n"); + free(line); + return (true); } - close(randomfd); - return (ft_buffer_to_charptr(filename)); + res = ft_strcmp(marker->word, cleanline); + free(cleanline); + if (res == 0) + free(line); + return (res == 0); } /* @@ -70,14 +99,18 @@ int here_doc(t_worddesc *marker, int infd) { int outfd; char *filename; + char *line; - if (infd < 0 || marker == NULL || marker->word == NULL) - return (-1); - filename = here_doc_random_filename(); - if (filename == NULL) - return (-1); - outfd = open(filename, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR); + outfd = setup_here_doc(marker, infd, &filename); if (outfd < 0) - return (free(filename), -1); - return (outfd); + return (-1); + line = get_next_line(infd); + while (line != NULL) + { + if (is_marker(line, marker)) + line = NULL; + else + line = output_line_and_next(infd, outfd, line); + } + return (finalize(outfd, filename)); } diff --git a/src/executing/here_doc/here_doc.h b/src/executing/here_doc/here_doc.h index 785c8c5..016d43a 100644 --- a/src/executing/here_doc/here_doc.h +++ b/src/executing/here_doc/here_doc.h @@ -6,7 +6,7 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/07 11:41:27 by khais #+# #+# */ -/* Updated: 2025/03/11 11:32:12 by khais ### ########.fr */ +/* Updated: 2025/03/11 13:31:52 by khais ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,5 +17,6 @@ int here_doc(t_worddesc *marker, int infd); char *here_doc_random_filename(void); +char *strip_newline(char *str); #endif // HERE_DOC_H diff --git a/src/executing/here_doc/random_filename.c b/src/executing/here_doc/random_filename.c new file mode 100644 index 0000000..80d1dd7 --- /dev/null +++ b/src/executing/here_doc/random_filename.c @@ -0,0 +1,56 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* random_filename.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: khais +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/03/11 13:29:32 by khais #+# #+# */ +/* Updated: 2025/03/11 13:30:33 by khais ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "here_doc.h" +#include "../../ft_errno.h" +#include "../../buffer/buffer.h" +#include +#include +#include "libft.h" + +/* +** Genereate a random filename for use by here_doc +** +** The filename will be of the form +** /tmp/minishell_here_doc_XXXXXXXXXXX +** where each X is a random alphanumerical char +** +** Random bytes are generated by reading from /dev/urandom +** +** Return NULL and sets ft_errno on error +*/ +char *here_doc_random_filename(void) +{ + int randomfd; + char buf[1]; + t_buffer *filename; + + randomfd = open("/dev/urandom", O_RDONLY); + if (randomfd < 0) + return (ft_errno(FT_EERRNO), NULL); + filename = ft_buffer_new(); + if (filename == NULL) + return (close(randomfd), ft_errno(FT_EERRNO), NULL); + filename = ft_buffer_push_buf(filename, "/tmp/minishell_here_doc_", 24); + while (filename->length < 35) + { + if (read(randomfd, buf, 1) != 1) + { + ft_buffer_free(filename); + return (close(randomfd), ft_errno(FT_EERRNO), NULL); + } + if (ft_isalnum(buf[0])) + filename = ft_buffer_pushchar(filename, buf[0]); + } + close(randomfd); + return (ft_buffer_to_charptr(filename)); +} diff --git a/src/executing/here_doc/strip_newline.c b/src/executing/here_doc/strip_newline.c new file mode 100644 index 0000000..7629be7 --- /dev/null +++ b/src/executing/here_doc/strip_newline.c @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* strip_newline.c :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: khais +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/03/11 13:31:22 by khais #+# #+# */ +/* Updated: 2025/03/11 13:31:31 by khais ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "libft.h" + +/* +** create a new string without the terminating newline of the given string. +** +** If the given string has no terminating newline, create a copy of the input +*/ +char *strip_newline(char *str) +{ + size_t last_char_idx; + char *outstr; + + if (str == NULL) + return (NULL); + last_char_idx = ft_strlen(str) - 1; + outstr = ft_strdup(str); + if (str[last_char_idx] == '\n') + outstr[last_char_idx] = '\0'; + return (outstr); +} diff --git a/tests/here_doc_input_plus_eof.input b/tests/here_doc_input_plus_eof.input new file mode 100644 index 0000000..0962cbf --- /dev/null +++ b/tests/here_doc_input_plus_eof.input @@ -0,0 +1,2 @@ +input +EOF diff --git a/tests/test_here_doc.c b/tests/test_here_doc.c index 7f644e4..dd291cf 100644 --- a/tests/test_here_doc.c +++ b/tests/test_here_doc.c @@ -6,7 +6,7 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/03/07 11:43:32 by khais #+# #+# */ -/* Updated: 2025/03/11 11:42:29 by khais ### ########.fr */ +/* Updated: 2025/03/11 11:44:34 by khais ### ########.fr */ /* */ /* ************************************************************************** */ @@ -68,9 +68,28 @@ static void test_here_doc_only_end_marker(void) do_leak_check(); } +static void test_here_doc_input_plus_end_marker(void) +{ + t_worddesc *marker; + int infile; + int result; + + ft_dprintf(STDERR_FILENO, "==> %s <==\n", __FUNCTION__); + marker = worddesc_create(ft_strdup("EOF"), 0, NULL); + infile = open("./here_doc_input_plus_eof.input", O_RDONLY); + result = here_doc(marker, infile); + close(infile); + worddesc_destroy(marker); + assert(result != -1); + assert_strequal("input\n", get_next_line(result)); + close(result); + do_leak_check(); +} + int main(void) { test_here_doc_filename_generation(); test_here_doc_invalid_args(); test_here_doc_only_end_marker(); + test_here_doc_input_plus_end_marker(); return (0); } diff --git a/tests/testutil.c b/tests/testutil.c index 5c4116e..e390926 100644 --- a/tests/testutil.c +++ b/tests/testutil.c @@ -6,7 +6,7 @@ /* By: khais +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/02/13 15:21:09 by khais #+# #+# */ -/* Updated: 2025/03/09 12:37:10 by khais ### ########.fr */ +/* Updated: 2025/03/11 11:46:04 by khais ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,9 +17,11 @@ void assert_strequal(char *str1, char *str2) { int ret; - ret = ft_strcmp(str1, str2); ft_dprintf(STDERR_FILENO, "Expected\t[%s]\n", str1); ft_dprintf(STDERR_FILENO, "to eq \t[%s]\n", str2); + if (str1 == str2) + return ; + ret = ft_strcmp(str1, str2); assert(ret == 0); }