here_doc: handle input with correct end marker

This commit is contained in:
Khaïs COLIN 2025-03-11 13:30:40 +01:00
parent a6d1386574
commit 7c6d061c6c
Signed by: logistic-bot
SSH key fingerprint: SHA256:RlpiqKeXpcPFZZ4y9Ou4xi2M8OhRJovIwDlbCaMsuAo
8 changed files with 191 additions and 44 deletions

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#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));
}

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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

View file

@ -0,0 +1,56 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* random_filename.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <fcntl.h>
#include <unistd.h>
#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));
}

View file

@ -0,0 +1,32 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* strip_newline.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}