feat(here_doc): handle signals (^C, ^\) correctly

This is a bit of a big commit, because I had to move some stuff to other files,
sorry about that. I can split it up if it's too big to review.
This commit is contained in:
Khaïs COLIN 2025-04-17 09:44:04 +02:00
parent 5e6d7b3b4e
commit f1a0af09f8
15 changed files with 269 additions and 126 deletions

View file

@ -6,7 +6,7 @@
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/03/07 11:42:29 by khais #+# #+# */
/* Updated: 2025/03/28 19:07:45 by khais ### ########.fr */
/* Updated: 2025/04/17 11:51:27 by khais ### ########.fr */
/* */
/* ************************************************************************** */
@ -16,81 +16,12 @@
#include <unistd.h>
#include "libft.h"
#include "../../ft_errno.h"
#include "../../sig/sig.h"
#include "here_doc_utils.h"
char *expand_line(char *line, t_minishell *app);
void failed_to_open_tmp_file(void);
/*
** - check that arguments are not invalid
** - create a random filename
** - create the file
**
** do these operations, with error checking
*/
static int setup_here_doc(t_worddesc *marker, int infd, char **filename)
{
int outfd;
if (infd < 0 || marker == NULL || marker->word == NULL)
return (ft_errno(FT_EINVAL), -1);
*filename = here_doc_random_filename();
if (filename == NULL)
return (ft_errno(FT_EERRNO), -1);
outfd = open(*filename, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR);
if (outfd < 0)
return (ft_errno(FT_EERRNO), 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);
if (outfd < 0)
ft_errno(FT_EERRNO);
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)
{
ft_dprintf(STDERR_FILENO, "Allocation failure!\n");
free(line);
return (true);
}
res = ft_strcmp(marker->word, cleanline);
free(cleanline);
if (res == 0)
free(line);
return (res == 0);
}
/*
** Read from infd into some file until a line that is exactly equal to the
** marker is read.
@ -112,7 +43,8 @@ int here_doc(t_worddesc *marker, int infd, t_minishell *app)
outfd = setup_here_doc(marker, infd, &filename);
if (outfd < 0)
return (failed_to_open_tmp_file(), -1);
return (ft_errno(FT_EHEREDOC_FAILED), failed_to_open_tmp_file(), -1);
set_here_doc_mode_sig_handling();
line = get_next_line(infd);
while (line != NULL)
{
@ -122,6 +54,8 @@ int here_doc(t_worddesc *marker, int infd, t_minishell *app)
line = expand_line(line, app);
line = output_line_and_next(infd, outfd, line);
}
if (g_signum != 0)
return (ft_errno(FT_EHEREDOC_FAILED), interupted(outfd, filename));
ft_dprintf(STDERR_FILENO, "minishell: warning: here-document delimited by \
end-of-file (wanted `%s')\n", marker->word);
return (finalize(outfd, filename));

View file

@ -0,0 +1,100 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* here_doc_utils.c :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/17 11:50:08 by khais #+# #+# */
/* Updated: 2025/04/17 11:55:34 by khais ### ########.fr */
/* */
/* ************************************************************************** */
#include "here_doc_utils.h"
#include <stdlib.h>
#include "../../ft_errno.h"
#include "here_doc.h"
#include "../../sig/sig.h"
/*
** - check that arguments are not invalid
** - create a random filename
** - create the file
**
** do these operations, with error checking
*/
int setup_here_doc(t_worddesc *marker, int infd, char **filename)
{
int outfd;
if (infd < 0 || marker == NULL || marker->word == NULL)
return (ft_errno(FT_EINVAL), -1);
*filename = here_doc_random_filename();
if (filename == NULL)
return (ft_errno(FT_EERRNO), -1);
outfd = open(*filename, O_CREAT | O_WRONLY | O_EXCL, S_IRUSR | S_IWUSR);
if (outfd < 0)
return (ft_errno(FT_EERRNO), free(*filename), -1);
return (outfd);
}
/*
** output line to outfd, get the next line from infd, and return it
*/
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
*/
int finalize(int outfd, char *filename)
{
close(outfd);
outfd = open(filename, O_RDONLY, 0);
unlink(filename);
free(filename);
if (outfd < 0)
ft_errno(FT_EERRNO);
set_interactive_mode_sig_handling();
return (outfd);
}
int interupted(int outfd, char *filename)
{
ft_printf("\n");
close(outfd);
unlink(filename);
free(filename);
g_signum = 0;
set_interactive_mode_sig_handling();
return (-1);
}
/*
** check if line corresponds to marker
**
** if true is returned, line has been freed
*/
bool is_marker(char *line, t_worddesc *marker)
{
char *cleanline;
int res;
cleanline = strip_newline(line);
if (cleanline == NULL)
{
ft_dprintf(STDERR_FILENO, "Allocation failure!\n");
free(line);
return (true);
}
res = ft_strcmp(marker->word, cleanline);
free(cleanline);
if (res == 0)
free(line);
return (res == 0);
}

View file

@ -0,0 +1,24 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* here_doc_utils.h :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: khais <marvin@42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2025/04/17 11:49:52 by khais #+# #+# */
/* Updated: 2025/04/17 11:53:08 by khais ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef HERE_DOC_UTILS_H
# define HERE_DOC_UTILS_H
# include "../../parser/worddesc/worddesc.h"
int setup_here_doc(t_worddesc *marker, int infd, char **filename);
char *output_line_and_next(int infd, int outfd, char *line);
int finalize(int outfd, char *filename);
int interupted(int outfd, char *filename);
bool is_marker(char *line, t_worddesc *marker);
#endif // HERE_DOC_UTILS_H