redirections WIP
This commit is contained in:
@@ -6,7 +6,7 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/13 04:35:06 by lperrey #+# #+# */
|
||||
/* Updated: 2021/11/13 10:18:51 by lperrey ### ########.fr */
|
||||
/* Updated: 2021/11/14 06:01:45 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@@ -20,6 +20,7 @@ enum e_in_quote_state
|
||||
};
|
||||
static int quote_state_change(int *quote_state, const char *s);
|
||||
|
||||
/* Duplicate a string minus the quoting characters ['] and ["]*/
|
||||
char *ft_strdup_quotes(const char *s)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/07 02:01:33 by lperrey #+# #+# */
|
||||
/* Updated: 2021/11/13 21:27:20 by lperrey ### ########.fr */
|
||||
/* Updated: 2021/11/14 10:13:38 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@@ -22,8 +22,6 @@ enum e_in_quote_state
|
||||
t_list *ft_lstnew_generic(size_t lst_sizse, size_t content_size);
|
||||
t_list *expand_token(char *content);
|
||||
char *rejoin_after_expand(t_list *expand_lst);
|
||||
char **ft_split_quotes(char const *s, char c); // Generic
|
||||
char *ft_strdup_quotes(const char *s); // Generic
|
||||
int new_token_for_each_field(char **fields, t_token **t);
|
||||
|
||||
// 1 - chaque bout dans un element d'une t_list
|
||||
@@ -35,39 +33,43 @@ int new_token_for_each_field(char **fields, t_token **t);
|
||||
// (ft_lstadd_front() sur le token original, puis set le token orignal à :
|
||||
// t->id = 0 ; free(t->content) ; t->content = NULL ; pour qu'il soit ignoré sur la suite du parsing)
|
||||
|
||||
int words_expansions(t_token *t)
|
||||
int words_expansions(t_token *token_list)
|
||||
{
|
||||
void *tmp_expand;
|
||||
char **tmp_split;
|
||||
|
||||
while (t)
|
||||
while (token_list)
|
||||
{
|
||||
if (t->id == T_WORD)
|
||||
{
|
||||
// 1
|
||||
tmp_expand = expand_token(t->content);
|
||||
if (!tmp_expand)
|
||||
return (0);
|
||||
// 2
|
||||
tmp_expand = rejoin_after_expand(tmp_expand);
|
||||
if (!tmp_expand)
|
||||
return (0);
|
||||
// 3
|
||||
tmp_split = ft_split_quotes(tmp_expand, ' ');
|
||||
free(tmp_expand);
|
||||
if (!tmp_split)
|
||||
return (0);
|
||||
// 4
|
||||
tmp_expand = ft_dup_2d_arr(tmp_split, (t_dup_func)ft_strdup_quotes);
|
||||
ft_free_2d_arr(tmp_split);
|
||||
tmp_split = tmp_expand;
|
||||
if (!tmp_split)
|
||||
return (0);
|
||||
// 5
|
||||
if (!new_token_for_each_field(tmp_split, &t))
|
||||
return (0);
|
||||
}
|
||||
t = t->next;
|
||||
if (token_list->id == T_WORD)
|
||||
token_expansions(&token_list);
|
||||
token_list = token_list->next;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
int token_expansions(t_token **t)
|
||||
{
|
||||
void *tmp;
|
||||
char **tmp_split;
|
||||
|
||||
// 1
|
||||
tmp = expand_token((*t)->content);
|
||||
if (!tmp)
|
||||
return (0);
|
||||
// 2
|
||||
tmp = rejoin_after_expand(tmp);
|
||||
if (!tmp)
|
||||
return (0);
|
||||
// 3
|
||||
tmp_split = ft_split_quotes(tmp, ' ');
|
||||
free(tmp);
|
||||
if (!tmp_split)
|
||||
return (0);
|
||||
// 4
|
||||
tmp = ft_dup_2d_arr(tmp_split, (t_dup_func)ft_strdup_quotes);
|
||||
ft_free_2d_arr(tmp_split);
|
||||
tmp_split = tmp;
|
||||
if (!tmp_split)
|
||||
return (0);
|
||||
// 5
|
||||
if (!new_token_for_each_field(tmp_split, t))
|
||||
return (0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/10/24 10:52:40 by lperrey #+# #+# */
|
||||
/* Updated: 2021/11/14 00:35:42 by lperrey ### ########.fr */
|
||||
/* Updated: 2021/11/14 11:00:39 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@@ -69,8 +69,8 @@ t_cmd **parsing(t_token *token_list)
|
||||
return (NULL);
|
||||
|
||||
// 2.9.1 - 3) Redirection
|
||||
/* if (!redirections(token_list, cmd_arr))
|
||||
return (ft_retp_free(NULL, cmd_arr, ft_free_cmd_arr)); */
|
||||
if (!redirections(token_list, cmd_arr))
|
||||
return (ft_retp_free(NULL, cmd_arr, (void(*)(void *))ft_free_cmd_arr));
|
||||
|
||||
// Struct CMD fill
|
||||
|
||||
|
||||
102
srcs/parsing/redirections/here_doc.c
Normal file
102
srcs/parsing/redirections/here_doc.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* here_doc.c :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
|
||||
/* Updated: 2021/11/14 10:58:37 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
#define TMP_HERE_DOC "/tmp/minishell_here_doc"
|
||||
|
||||
static int here_doc_write(char *delimiter, int doc_fd);
|
||||
|
||||
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.
|
||||
// implementer une gestion des signaux pour here_doc (actuellement ça leaks).
|
||||
// Peut-être remplacer gnl() par readline() pour avoir une gestion correct
|
||||
// du terminal (actuellement l'affichage lors du changement de ligne est foireux).
|
||||
int here_doc;
|
||||
|
||||
delimiter = ft_strdup_quotes(delimiter);
|
||||
if (!delimiter)
|
||||
return (ft_reti_perror(-1, "ft_strdup_quotes()"));
|
||||
here_doc = open(TMP_HERE_DOC, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
|
||||
if (here_doc == -1)
|
||||
return (ft_reti_perror_io(-1, "open() ", TMP_HERE_DOC));
|
||||
if (!here_doc_write(delimiter, here_doc))
|
||||
{
|
||||
gnl(STDIN_FILENO, NULL, 1);
|
||||
return (0);
|
||||
}
|
||||
if (close(here_doc) == -1)
|
||||
ft_perror_io("close() ", TMP_HERE_DOC);
|
||||
here_doc = open(TMP_HERE_DOC, O_RDONLY);
|
||||
if (here_doc == -1)
|
||||
ft_perror_io("open() ", TMP_HERE_DOC);
|
||||
if (unlink(TMP_HERE_DOC) == -1)
|
||||
return (ft_reti_perror_io(-1, "unlink() ", TMP_HERE_DOC));
|
||||
return (here_doc);
|
||||
}
|
||||
|
||||
static int here_doc_write(char *delimiter, int doc_fd)
|
||||
{
|
||||
char *line;
|
||||
|
||||
while (1)
|
||||
{
|
||||
line = NULL;
|
||||
if (gnl(STDIN_FILENO, &line, 0) == -1)
|
||||
return (ft_reti_perror_free(0, 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(0, line, free, "write() "TMP_HERE_DOC));
|
||||
if (write(doc_fd, "\n", 1) == -1)
|
||||
return (ft_reti_perror_free(0, line, free, "write() "TMP_HERE_DOC));
|
||||
free(line);
|
||||
}
|
||||
free(line);
|
||||
gnl(STDIN_FILENO, NULL, 1);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
static int here_doc_write(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(0, 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(0, line, free, "write() "TMP_HERE_DOC));
|
||||
if (write(doc_fd, "\n", 1) == -1)
|
||||
return (ft_reti_perror_free(0, line, free, "write() "TMP_HERE_DOC));
|
||||
free(line);
|
||||
line = NULL;
|
||||
}
|
||||
free(line);
|
||||
gnl(STDIN_FILENO, NULL, 1);
|
||||
return (1);
|
||||
}
|
||||
*/
|
||||
@@ -6,74 +6,16 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2021/11/11 18:46:43 by lperrey #+# #+# */
|
||||
/* Updated: 2021/11/12 20:17:09 by lperrey ### ########.fr */
|
||||
/* Updated: 2021/11/14 10:04:21 by lperrey ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "minishell.h"
|
||||
|
||||
int ft_reti_perror_io(int ret, char *err_str, char *io_file) // generic
|
||||
{
|
||||
ft_putstr_fd(err_str, 2);
|
||||
perror(io_file);
|
||||
return (ret);
|
||||
}
|
||||
int here_doc(char *delimiter);
|
||||
|
||||
int here_doc_handle_PLACEHOLDER(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. */
|
||||
// Pas d'expansion sur le delimiter, mais quote removal tout de même.
|
||||
// TODO : quote removal sur le delimiter.
|
||||
QUOTE_REMOVAL_PLACEHOLDER();
|
||||
}
|
||||
|
||||
int redirect_cmd_input(t_token *t, t_cmd *cmd)
|
||||
{
|
||||
if (cmd->fd_in != STDIN_FILENO && cmd->fd_in > 0)
|
||||
if (close(cmd->fd_in) == -1)
|
||||
perror("close()");
|
||||
if (t->id == '<')
|
||||
{
|
||||
// TODO : Expansion + quote removal sur le word t->next->content.
|
||||
// si plus d'un champ ou aucun champ aprés expansion,
|
||||
// message d'erreur comme bash "bash: $VAR: ambiguous redirect"
|
||||
// OU prise en compte seulement du premier champ.
|
||||
EXPAND_AND_QUOTE_REMOVAL_PLACEHOLDER();
|
||||
cmd->fd_in = open(t->next->content, O_RDONLY);
|
||||
if (cmd->fd_in == -1)
|
||||
ft_reti_perror_io(0, "open() ", t->next->content);
|
||||
}
|
||||
else if (t->id == T_DLESS)
|
||||
cmd->fd_in = here_doc_handle_PLACEHOLDER(t->next->content); // TODO
|
||||
return (1);
|
||||
}
|
||||
|
||||
int redirect_cmd_output(t_token *t, t_cmd *cmd)
|
||||
{
|
||||
int flags;
|
||||
|
||||
if (cmd->fd_out != STDOUT_FILENO && cmd->fd_out > 0)
|
||||
if (close(cmd->fd_out) == -1)
|
||||
perror("close()");
|
||||
// TODO : Expansion + quote removal sur le word t->next->content.
|
||||
// si plus d'un champ ou aucun champ aprés expansion,
|
||||
// message d'erreur comme bash "bash: $VAR: ambiguous redirect"
|
||||
// OU prise en compte seulement du premier champ.
|
||||
EXPAND_AND_QUOTE_REMOVAL_PLACEHOLDER();
|
||||
if (t->id == '>')
|
||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||
else if (t->id == T_DGREAT)
|
||||
flags = O_WRONLY | O_CREAT | O_APPEND;
|
||||
cmd->fd_out = open(t->next->content, flags, S_IRWXU);
|
||||
if (cmd->fd_out == -1)
|
||||
return (ft_reti_perror_io(0, "open() ", t->next->content));
|
||||
return (1);
|
||||
}
|
||||
static int redirect_cmd_input(t_token *t, t_cmd *cmd);
|
||||
static int redirect_cmd_output(t_token *t, t_cmd *cmd);
|
||||
|
||||
int redirections(t_token *t, t_cmd **cmd_arr)
|
||||
{
|
||||
@@ -98,3 +40,51 @@ int redirections(t_token *t, t_cmd **cmd_arr)
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int redirect_cmd_input(t_token *t, t_cmd *cmd)
|
||||
{
|
||||
if (cmd->fd_in != STDIN_FILENO && cmd->fd_in > 0)
|
||||
if (close(cmd->fd_in) == -1)
|
||||
perror("close()");
|
||||
if (t->id == '<')
|
||||
{
|
||||
// TODO : Expansion + quote removal sur le word t->next->content.
|
||||
// si plus d'un champ ou aucun champ aprés expansion,
|
||||
// message d'erreur comme bash "bash: $VAR: ambiguous redirect"
|
||||
// OU prise en compte seulement du premier champ.
|
||||
//EXPAND_AND_QUOTE_REMOVAL_PLACEHOLDER();
|
||||
cmd->fd_in = open(t->next->content, O_RDONLY);
|
||||
if (cmd->fd_in == -1)
|
||||
ft_perror_io("open() ", t->next->content);
|
||||
}
|
||||
else if (t->id == T_DLESS)
|
||||
{
|
||||
cmd->fd_in = here_doc(t->next->content);
|
||||
if (cmd->fd_in == -1)
|
||||
return (ft_reti_print(0, "minishell: heredoc error\n", 2));
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int redirect_cmd_output(t_token *t, t_cmd *cmd)
|
||||
{
|
||||
int flags;
|
||||
|
||||
if (cmd->fd_out != STDOUT_FILENO && cmd->fd_out > 0)
|
||||
if (close(cmd->fd_out) == -1)
|
||||
perror("close()");
|
||||
// TODO : Expansion + quote removal sur le word t->next->content.
|
||||
// si plus d'un champ ou aucun champ aprés expansion,
|
||||
// message d'erreur comme bash "bash: $VAR: ambiguous redirect"
|
||||
// OU prise en compte seulement du premier champ.
|
||||
//EXPAND_AND_QUOTE_REMOVAL_PLACEHOLDER();
|
||||
flags = O_WRONLY | O_CREAT;
|
||||
if (t->id == '>')
|
||||
flags = flags | O_TRUNC;
|
||||
else if (t->id == T_DGREAT)
|
||||
flags = flags | O_APPEND;
|
||||
cmd->fd_out = open(t->next->content, flags, S_IRWXU);
|
||||
if (cmd->fd_out == -1)
|
||||
return (ft_reti_perror_io(0, "open() ", t->next->content));
|
||||
return (1);
|
||||
}
|
||||
Reference in New Issue
Block a user