19 Commits 0bae743536 ... 832ed83d38

Author SHA1 Message Date
  Moul 832ed83d38 [norm] reduce variable name lenght. 2 years ago
  Moul b47bd878ca [enh] right_redirections: close fd and restore stdout. 2 years ago
  Moul 0325e6e6b2 [mod] use 'STDIN' and 'STDOUT' defines. 2 years ago
  Moul 2bfa8d8026 [norm] heredoc: split on two functions. Update comments. 2 years ago
  Moul c1da64f57e [enh] handle double redirections with heredoc. 2 years ago
  Moul 19fcebb780 [enh] heredoc: directly call execution to avoid passing on many code. 2 years ago
  Moul 715df09b95 [enh] handle double redirections on a specialized f(). 2 years ago
  Moul cbc4b23842 [enh] double redirections: enhance unit tests. 2 years ago
  Moul 3af6144027 [norm] pipe: modifications which do not modify behavior. 2 years ago
  Moul d862bfe035 [mod] simplify debug printing f(). 2 years ago
  Moul e568218aaa [mod] move 'open_left_redirections()' inside multipiping. 2 years ago
  Moul e65c4bfe4f [mod] modify print debug f(). 2 years ago
  Moul 2c95435b65 [mod] redirection: organize f() and clarify they names. 2 years ago
  Moul 355c203b92 [mod] add 'e' struct on right_redirection function 2 years ago
  Moul ce4523d242 [enh] double redirection: do not go on certain part for last redirection. 2 years ago
  Moul 73cb28bd84 [enh] new function to fill pipe data struct. 2 years ago
  Moul 460e21af59 [fix] double redirection: forget to precise output fd. 2 years ago
  Moul feac05beb6 [enh] add unit tests for double redirections. 2 years ago
  Moul 2bd87080f5 [enh] add double redirection parsing. 2 years ago
9 changed files with 210 additions and 88 deletions
  1. 41 15
      src/heredoc.c
  2. 1 1
      src/parse_redirections.c
  3. 42 12
      src/pipe_exec.c
  4. 10 10
      src/pipe_parsing.c
  5. 59 12
      src/pipe_redir_parsing.c
  6. 28 25
      src/redirect.c
  7. 15 11
      src/sh.h
  8. 7 2
      src/struct.h
  9. 7 0
      tests.sh

+ 41 - 15
src/heredoc.c

@@ -5,36 +5,62 @@
 ** Unset term caps modes
 ** retrieve text through a prompt
 ** Set term caps modes
-** backup STDIN, pipe the text in STDIN
-** wait the fork, launch the cmd with the upper text
-** restore STDIN
+** pipe the text in STDIN
+** wait the fork
 */
 
-void	prompt_redirection(t_e *e, t_pipe *p, t_pipe_redir *t)
+void	prompt_redirection_init(t_e *e, t_pipe *p, t_pr *t, t_pr *t2)
 {
 	char	*txt;
-	int		pipefd[2];
-	int		stdfd;
 	int		i;
 
 	set_term_modes(0);
 	txt = prompt_heredoc(e, txt, t->otxt, i);
 	set_term_modes(1);
-	pipe(pipefd);
+	pipe(e->pipefd);
 	if (fork() == 0)
 	{
-		close(pipefd[0]);
-		ft_putstr_fd(txt, pipefd[1]);
+		close(e->pipefd[STDIN]);
+		ft_putstr_fd(txt, e->pipefd[STDOUT]);
 		ft_strdel(&txt);
 		exit(0);
 	}
-	close(pipefd[1]);
-	stdfd = dup(0);
-	dup2(pipefd[0], 0);
 	wait(NULL);
-	pipe_init(e, t->itxt);
-	close(pipefd[0]);
-	close(0);
+	close(e->pipefd[STDOUT]);
+	prompt_redirection_exec(e, p, t, t2);
+}
+
+/*
+** backup STDIN, dup pipe on STDIN
+** if double redirections: open_right_redirections
+** exec the cmd which read on pipe
+** wait fork
+** if double redirections: close file fd, restore STDOUT
+** restore STDIN
+*/
+
+void	prompt_redirection_exec(t_e *e, t_pipe *p, t_pr *t, t_pr *t2)
+{
+	int		stdfd;
+
+	stdfd = dup(STDIN);
+	dup2(e->pipefd[STDIN], STDIN);
+	if (t2 != NULL)
+		open_right_redirections(e, p, t2);
+	if (fork() == 0)
+	{
+		manage_cmd_2(e, cmd_splitting(e, t->itxt, ' '));
+		exit(0);
+	}
+	wait(NULL);
+	if (t2 != NULL)
+	{
+		close(e->fd_file);
+		close(STDOUT);
+		dup(e->fdout);
+	}
+	close(e->pipefd[STDIN]);
+	close(STDIN);
 	dup(stdfd);
 }
 

+ 1 - 1
src/parse_redirections.c

@@ -53,7 +53,7 @@ int		check_before_after_chevron(char *str, int chev)
 ** If '&' presence: parse one way, else: parse other way
 */
 
-void	parse_and(char *str, t_pipe_redir *t, int file_pos)
+void	parse_and(char *str, t_pr *t, int file_pos)
 {
 	char	*and;
 	int		andp;

+ 42 - 12
src/pipe_exec.c

@@ -6,19 +6,18 @@
 ** Wait for infinite fork to display again promt
 */
 
-void	launch_pipes(t_e *e, t_pipe *p, t_pipe_redir **t)
+void	launch_pipes(t_e *e, t_pipe *p, t_pr **t)
 {
 	p->i = -1;
 	p->cmd_opt = (char***)malloc(sizeof(char**) * (p->nbr + 1));
 	while (++p->i <= p->pnbr)
 	{
-		p->cmd_opt[p->i] = cmd_splitting(e, t[p->i]->itxt, ' ');
-		remove_cotes(p->cmd_opt[p->i]);
-		open_redirections(e, p, t[p->i]);
-		if (ft_strcmp(t[p->i]->operator, "<<") != 0)
-			handle_multi_piping(e, p, t[p->i]);
-		if (ft_strstr(t[p->i]->operator, ">") == NULL)
-			close_redirections(e, p, t[p->i]);
+		if (t[p->i]->itxt != NULL)
+		{
+			p->cmd_opt[p->i] = cmd_splitting(e, t[p->i]->itxt, ' ');
+			remove_cotes(p->cmd_opt[p->i]);
+		}
+		handle_multi_piping(e, p, t[p->i]);
 		free(p->cmd_opt[p->i]);
 		if (p->i != 0)
 			free(p->fd[p->i - 1]);
@@ -44,13 +43,14 @@ void	launch_pipes(t_e *e, t_pipe *p, t_pipe_redir **t)
 ** Close previous pipe file descriptors except for first cmd to free fd
 */
 
-void	handle_multi_piping(t_e *e, t_pipe *p, t_pipe_redir *t)
+void	handle_multi_piping(t_e *e, t_pipe *p, t_pr *t)
 {
 	int		ok;
 
 	ok = manage_cmd_1(e, p->cmd_opt[p->i]);
 	if (fork() == 0)
 	{
+		open_left_redirections(e, p, t);
 		if (p->i < p->nbr)
 		{
 			close(p->fd[p->i][0]);
@@ -72,16 +72,46 @@ void	handle_multi_piping(t_e *e, t_pipe *p, t_pipe_redir *t)
 	}
 }
 
-void	inside_pipe(t_e *e, t_pipe *p, t_pipe_redir *t)
+void	inside_pipe(t_e *e, t_pipe *p, t_pr *t)
 {
 	if (ft_strstr(t->operator, ">") != NULL)
-		right_redirections(p, t);
-	manage_cmd_2(e, p->cmd_opt[p->i]);
+		open_right_redirections(e, p, t);
+	if (t->itxt != NULL && ft_strcmp(t->operator, "<<") != 0)
+		manage_cmd_2(e, p->cmd_opt[p->i]);
 	if (ft_strstr(t->operator, ">") != NULL)
 		close_redirections(e, p, t);
 }
 
 /*
+** Special function to handle double redirections of fd and execution fork
+** fork, open left and right redirections
+** execute cmd, close fd, father wait for end of son fork
+*/
+
+void	launch_double_redirections(t_e *e, t_pipe *p, t_pr **t)
+{
+	int		fd;
+
+	if (ft_strcmp(t[0]->operator, "<<") == 0)
+	{
+		prompt_redirection_init(e, p, t[0], t[1]);
+		return ;
+	}
+	else if (fork() == 0)
+	{
+		fd = open(t[0]->otxt, O_RDONLY);
+		close(0);
+		dup(fd);
+		open_right_redirections(e, p, t[1]);
+		manage_cmd_2(e, cmd_splitting(e, t[0]->itxt, ' '));
+		close(STDOUT);
+		close(fd);
+		exit(0);
+	}
+	wait(NULL);
+}
+
+/*
 ** check every cmd, every cote type
 ** if block starts and ends with same cote:
 ** cut first and last char

+ 10 - 10
src/pipe_parsing.c

@@ -36,13 +36,17 @@ void	pipe_init(t_e *e, char *all_cmd)
 
 void	pipe_init_2(t_e *e, t_pipe *p, char *all_cmd)
 {
-	t_pipe_redir	**t;
+	t_pr	**t;
 
 	p->cmd_pipe = cmd_splitting(e, all_cmd, '|');
 	pipe_parsing(p, e);
-	t = (t_pipe_redir**)malloc(sizeof(t_pipe_redir*) * (p->nbr + 2));
+	t = (t_pr**)malloc(sizeof(t_pr*) * (p->nbr + 2));
 	fill_pipe_redir_data(e, p, t);
-	launch_pipes(e, p, t);
+	if (ft_strchr(t[0]->operator, '<') != NULL && t[1] != NULL && \
+			ft_strchr(t[1]->operator, '>') != NULL)
+		launch_double_redirections(e, p, t);
+	else
+		launch_pipes(e, p, t);
 }
 
 /*
@@ -51,14 +55,10 @@ void	pipe_init_2(t_e *e, t_pipe *p, char *all_cmd)
 ** display content on structure
 */
 
-void	display_data(t_pipe_redir **t)
+void	display_data(t_pr *t)
 {
-	int		i;
-
-	i = -1;
-	while (t[++i] != NULL)
-		ft_printf("itxt: '%s'\nifd: %d\noperator: '%s'\nofd: %d\notxt: '%s'\n",
-			t[i]->itxt, t[i]->ifd, t[i]->operator, t[i]->ofd, t[i]->otxt);
+	ft_printf("itxt: '%s', ifd: %d, operator: '%s', ofd: %d, otxt: '%s'\n",
+		t->itxt, t->ifd, t->operator, t->ofd, t->otxt);
 }
 
 /*

+ 59 - 12
src/pipe_redir_parsing.c

@@ -5,7 +5,7 @@
 ** Else: fill pipe
 */
 
-void	fill_pipe_redir_data(t_e *e, t_pipe *p, t_pipe_redir **t)
+void	fill_pipe_redir_data(t_e *e, t_pipe *p, t_pr **t)
 {
 	int		j;
 
@@ -13,19 +13,66 @@ void	fill_pipe_redir_data(t_e *e, t_pipe *p, t_pipe_redir **t)
 	p->i = 0;
 	while (p->cmd_pipe[++j] != NULL)
 	{
-		if (parse_redirection(e, p, p->cmd_pipe[j], t) == 0)
-		{
-			t[p->i] = (t_pipe_redir*)malloc(sizeof(t_pipe_redir));
-			t[p->i]->itxt = p->cmd_pipe[j];
-			t[p->i]->ifd = 1;
-			t[p->i]->operator = "|";
-			t[p->i]->ofd = 0;
-			t[p->i++]->otxt = NULL;
-		}
+		if (parse_double_redir(e, p->cmd_pipe[j], p, t) == 0)
+			pipe_creation(t, p, p->cmd_pipe[j]);
 	}
 	t[p->i] = NULL;
 }
 
+void	pipe_creation(t_pr **t, t_pipe *p, char *cmd)
+{
+	t[p->i] = (t_pr*)malloc(sizeof(t_pr));
+	t[p->i]->itxt = cmd;
+	t[p->i]->ifd = 1;
+	t[p->i]->operator = "|";
+	t[p->i]->ofd = 0;
+	t[p->i++]->otxt = NULL;
+}
+
+/*
+** cat << end >> toto
+** cat << end > toto
+** cat < tests.sh > toto
+** cat < tests.sh >> toto
+**
+** Detect if there is two redirections:
+** - first one < or << and snd one: > or >>
+** If so, handle one redirection to the other:
+** - split in two parts:
+** - first part for classic redirection
+** - second part for snd redirection
+** Else, mono-redirection
+*/
+
+int		parse_double_redir(t_e *e, char *str, t_pipe *p, t_pr **t)
+{
+	int		first_chev;
+	int		snd_chev;
+	char	*cmd;
+	int		nchev;
+	int		ret;
+
+	first_chev = check_chev_is_on_non_coted_block(e, str, '<');
+	snd_chev = first_chev + 1 + \
+	check_chev_is_on_non_coted_block(e, &str[first_chev + 1], '>');
+	if (first_chev != -1 && snd_chev != -1 && snd_chev - first_chev > 0)
+	{
+		cmd = ft_strsub(str, 0, snd_chev);
+		ret = parse_redirection(e, p, cmd, t);
+		ft_strdel(&cmd);
+		nchev = str[snd_chev] == str[snd_chev + 1] ? 2 : 1;
+		t[p->i] = (t_pr*)malloc(sizeof(t_pr));
+		t[p->i]->itxt = NULL;
+		t[p->i]->operator = ft_strsub(&str[snd_chev], 0, nchev);
+		t[p->i]->otxt = ft_strtrim(&str[snd_chev + nchev]);
+		t[p->i++]->ofd = -100;
+		p->pnbr++;
+	}
+	else
+		ret = parse_redirection(e, p, str, t);
+	return (ret);
+}
+
 /*
 ** Get chevrons positions
 ** Take closer chevron
@@ -38,7 +85,7 @@ void	fill_pipe_redir_data(t_e *e, t_pipe *p, t_pipe_redir **t)
 ** Split with strsub
 */
 
-int		parse_redirection(t_e *e, t_pipe *p, char *str, t_pipe_redir **t)
+int		parse_redirection(t_e *e, t_pipe *p, char *str, t_pr **t)
 {
 	int		chev;
 	int		chev2;
@@ -54,7 +101,7 @@ int		parse_redirection(t_e *e, t_pipe *p, char *str, t_pipe_redir **t)
 		return (0);
 	fd = str[chev - 1] == '1' || str[chev - 1] == '2' ? 1 : 0;
 	nchev = str[chev] == str[chev + 1] ? 2 : 1;
-	t[p->i] = (t_pipe_redir*)malloc(sizeof(t_pipe_redir));
+	t[p->i] = (t_pr*)malloc(sizeof(t_pr));
 	t[p->i]->itxt = ft_strtrim(ft_strsub(str, 0, chev - fd));
 	t[p->i]->operator = ft_strsub(str, chev - fd, nchev + fd);
 	t[p->i]->ifd = ft_isdigit(t[p->i]->operator[0]) ? \

+ 28 - 25
src/redirect.c

@@ -7,7 +7,7 @@
 ** if > or >>: dup STDERR or STDOUT in to STDIN
 */
 
-void	open_redirections(t_e *e, t_pipe *p, t_pipe_redir *t)
+void	open_left_redirections(t_e *e, t_pipe *p, t_pr *t)
 {
 	if (t->operator[0] == '|')
 		return ;
@@ -19,24 +19,7 @@ void	open_redirections(t_e *e, t_pipe *p, t_pipe_redir *t)
 		dup(p->fd[p->i][0]);
 	}
 	else if (ft_strcmp(t->operator, "<<") == 0)
-		prompt_redirection(e, p, t);
-}
-
-/*
-** if != <<: close fd, restore stdfd
-*/
-
-void	close_redirections(t_e *e, t_pipe *p, t_pipe_redir *t)
-{
-	if (ft_strcmp(t->operator, "<<") != 0 && t->operator[0] != '|')
-	{
-		close(p->fd[p->i][0]);
-		if (ft_strcmp(t->operator, "<") != 0)
-			t->ifd == '2' ? close(STDERR) : close(STDOUT);
-		else
-			close(0);
-		dup(p->fd[p->i][1]);
-	}
+		prompt_redirection_init(e, p, t, NULL);
 }
 
 /*
@@ -46,17 +29,16 @@ void	close_redirections(t_e *e, t_pipe *p, t_pipe_redir *t)
 ** save stdfd, dup new fd in STDIN
 */
 
-void	right_redirections(t_pipe *p, t_pipe_redir *t)
+void	open_right_redirections(t_e *e, t_pipe *p, t_pr *t)
 {
-	int		fd_file;
-
 	if (t->ofd == -100)
 	{
 		if (ft_strstr(t->operator, ">>") != NULL)
-			fd_file = open(t->otxt, O_APPEND | O_WRONLY | O_CREAT, 0644);
+			e->fd_file = open(t->otxt, O_APPEND | O_WRONLY | O_CREAT, 0644);
 		else
-			fd_file = open(t->otxt, O_TRUNC | O_WRONLY | O_CREAT, 0644);
-		t->ifd == 2 ? dup2(fd_file, STDERR) : dup2(fd_file, STDOUT);
+			e->fd_file = open(t->otxt, O_TRUNC | O_WRONLY | O_CREAT, 0644);
+		e->fdout = t->ifd == 2 ? dup(STDERR) : dup(STDOUT);
+		t->ifd == 2 ? dup2(e->fd_file, STDERR) : dup2(e->fd_file, STDOUT);
 	}
 	else
 	{
@@ -66,3 +48,24 @@ void	right_redirections(t_pipe *p, t_pipe_redir *t)
 			dup2(t->ifd, t->ofd);
 	}
 }
+
+/*
+** if != <<: close fd, restore stdfd
+** right_redirections: close fd_file, restore stdout
+*/
+
+void	close_redirections(t_e *e, t_pipe *p, t_pr *t)
+{
+	if (ft_strcmp(t->operator, "<<") != 0 && t->operator[0] != '|')
+	{
+		close(p->fd[p->i][0]);
+		if (ft_strcmp(t->operator, "<") != 0)
+			t->ifd == '2' ? close(STDERR) : close(STDOUT);
+		else
+			close(0);
+		dup(p->fd[p->i][1]);
+		close(e->fd_file);
+		close(STDOUT);
+		dup(e->fdout);
+	}
+}

+ 15 - 11
src/sh.h

@@ -37,32 +37,36 @@ void	count_pipe_nbr(t_e *e, t_pipe *p, char *str);
 /*
 ** pipe_redir_parsing.c
 */
-void	fill_pipe_redir_data(t_e *e, t_pipe *p, t_pipe_redir **t);
-void	display_data(t_pipe_redir **t);
-int		parse_redirection(t_e *e, t_pipe *p, char *str, t_pipe_redir **t);
+void	fill_pipe_redir_data(t_e *e, t_pipe *p, t_pr **t);
+void	pipe_creation(t_pr **t, t_pipe *p, char *cmd);
+void	display_data(t_pr *t);
+int		parse_double_redir(t_e *e, char *str, t_pipe *p, t_pr **t);
+int		parse_redirection(t_e *e, t_pipe *p, char *str, t_pr **t);
 /*
 ** parse_redirections.c
 */
 int		check_chev_is_on_non_coted_block(t_e *e, char *str, char c);
 int		check_before_after_chevron(char *str, int chev);
-void	parse_and(char *str, t_pipe_redir *t, int file_pos);
+void	parse_and(char *str, t_pr *t, int file_pos);
 /*
 ** pipe_exec.c
 */
-void	launch_pipes(t_e *e, t_pipe *p, t_pipe_redir **t);
-void	handle_multi_piping(t_e *e, t_pipe *p, t_pipe_redir *t);
-void	inside_pipe(t_e *e, t_pipe *p, t_pipe_redir *t);
+void	launch_pipes(t_e *e, t_pipe *p, t_pr **t);
+void	handle_multi_piping(t_e *e, t_pipe *p, t_pr *t);
+void	inside_pipe(t_e *e, t_pipe *p, t_pr *t);
+void	launch_double_redirections(t_e *e, t_pipe *p, t_pr **t);
 void	remove_cotes(char **cmd);
 /*
 ** redirect.c
 */
-void	open_redirections(t_e *e, t_pipe *p, t_pipe_redir *t);
-void	close_redirections(t_e *e, t_pipe *p, t_pipe_redir *t);
-void	right_redirections(t_pipe *p, t_pipe_redir *t);
+void	open_left_redirections(t_e *e, t_pipe *p, t_pr *t);
+void	open_right_redirections(t_e *e, t_pipe *p, t_pr *t);
+void	close_redirections(t_e *e, t_pipe *p, t_pr *t);
 /*
 ** heredoc.c
 */
-void	prompt_redirection(t_e *e, t_pipe *p, t_pipe_redir *t);
+void	prompt_redirection_init(t_e *e, t_pipe *p, t_pr *t, t_pr *t2);
+void	prompt_redirection_exec(t_e *e, t_pipe *p, t_pr *t, t_pr *t2);
 char	*prompt_heredoc(t_e *e, char *txt, char *eof, int i);
 int		here_edition(t_e *h, int heredoc);
 /*

+ 7 - 2
src/struct.h

@@ -41,6 +41,8 @@ typedef struct			s_block
 ** number columns in current window
 ** boolean value for ctrl + d in prompt
 ** slen: len from semicolon split: used for non-splitting inside coted blocks
+** fd_file: file descriptor of file for redirection on the right
+** fdout: fd backup of stdout so restore it later
 */
 
 typedef struct			s_e {
@@ -62,6 +64,9 @@ typedef struct			s_e {
 	int					d;
 	int					slen;
 	t_block				**b;
+	int					fd_file;
+	int					fdout;
+	int					pipefd[2];
 }						t_e;
 
 /*
@@ -92,13 +97,13 @@ typedef struct			s_pipe
 ** otxt: could be cmd or nothing (NULL)
 */
 
-typedef struct			s_pipe_redir
+typedef struct			s_pr
 {
 	char				*itxt;
 	int					ifd;
 	char				*operator;
 	int					ofd;
 	char				*otxt;
-}						t_pipe_redir;
+}						t_pr;
 
 #endif

+ 7 - 0
tests.sh

@@ -81,6 +81,13 @@ tests=(
 #"cat << fin\nnrstai\nfin\n" # double gauche
 #"cat << toto\nnrstai\nrsnati\nairnst\ntoto" # double gauche avec autre string de fin
 
+## Double redirection
+"cat < $tmpf > /tmp/txt; cat /tmp/txt; rm /tmp/txt"
+"cat < $tmpf >> /tmp/txt; cat /tmp/txt; rm /tmp/txt"
+### Same file name
+"cat < $tmpf > $tmpf"
+#"cat < $tmpf >> $tmpf" # This one is non stop adding many time which stopped the script
+
 ## Redirections avec fd de sortie spécifié
 ### Redirection closed
 "ls 1>&-"