/ pipex / pipex / mandatory / pipex.c
pipex.c
  1  /* ************************************************************************** */
  2  /*                                                                            */
  3  /*                                                        :::      ::::::::   */
  4  /*   pipex.c                                            :+:      :+:    :+:   */
  5  /*                                                    +:+ +:+         +:+     */
  6  /*   By: gychoi <gychoi@student.42seoul.kr>         +#+  +:+       +#+        */
  7  /*                                                +#+#+#+#+#+   +#+           */
  8  /*   Created: 2023/01/15 22:13:08 by gychoi            #+#    #+#             */
  9  /*   Updated: 2023/02/07 18:24:25 by gychoi           ###   ########.fr       */
 10  /*                                                                            */
 11  /* ************************************************************************** */
 12  
 13  #include "pipex.h"
 14  
 15  char	*find_path(char *command, char **envp)
 16  {
 17  	int		i;
 18  	char	*path;
 19  	char	*find;
 20  	char	**paths;
 21  
 22  	if (access(command, F_OK | X_OK) == 0)
 23  		return (command);
 24  	i = 0;
 25  	while (ft_strncmp(envp[i], "PATH", 4))
 26  		i++;
 27  	if (envp[i] == NULL)
 28  		return (NULL);
 29  	paths = ft_split(envp[i] + 5, ':');
 30  	i = 0;
 31  	find = NULL;
 32  	while (paths[i])
 33  	{
 34  		path = ft_strjoin(paths[i], command);
 35  		if (access(path, F_OK | X_OK) == 0)
 36  			find = ft_strdup(path);
 37  		free(paths[i++]);
 38  		free(path);
 39  	}
 40  	free(paths);
 41  	return (find);
 42  }
 43  
 44  int	execute_command(char *argv, char **envp)
 45  {
 46  	char	*command;
 47  	char	*path;
 48  	char	**tokens;
 49  	int		i;
 50  
 51  	tokens = ft_split(argv, ' ');
 52  	command = ft_strjoin("/", tokens[0]);
 53  	path = find_path(command, envp);
 54  	if (tokens == NULL || command == NULL || path == NULL)
 55  		return (-1);
 56  	if (execve(path, tokens, envp) == -1)
 57  	{
 58  		i = 0;
 59  		while (tokens[i])
 60  			free(tokens[i++]);
 61  		free(tokens);
 62  		free(command);
 63  		free(path);
 64  	}
 65  	return (-1);
 66  }
 67  
 68  void	child_write(char **argv, char **envp, int *pfd)
 69  {
 70  	int	infile;
 71  
 72  	if (access(argv[1], F_OK) == -1)
 73  		px_error("No such file or directory\n", argv[1], 0);
 74  	infile = px_open(argv[1], O_RDONLY);
 75  	px_close(pfd[READ_END]);
 76  	if (pfd[WRITE_END] != STDOUT_FILENO)
 77  	{
 78  		px_dup2(pfd[WRITE_END], STDOUT_FILENO);
 79  		px_close(pfd[WRITE_END]);
 80  		px_dup2(infile, STDIN_FILENO);
 81  		px_close(infile);
 82  	}
 83  	if (execute_command(argv[2], envp) == -1)
 84  		px_error("command not found\n", argv[2], 0);
 85  }
 86  
 87  void	child_read(char **argv, char **envp, int *pfd)
 88  {
 89  	int	outfile;
 90  
 91  	outfile = px_open(argv[4], O_WRONLY | O_CREAT | O_TRUNC);
 92  	px_close(pfd[WRITE_END]);
 93  	if (pfd[READ_END] != STDIN_FILENO)
 94  	{
 95  		px_dup2(pfd[READ_END], STDIN_FILENO);
 96  		px_close(pfd[READ_END]);
 97  		px_dup2(outfile, STDOUT_FILENO);
 98  		px_close(outfile);
 99  	}
100  	if (execute_command(argv[3], envp) == -1)
101  		px_error("command not found\n", argv[3], 127);
102  }
103  
104  int	main(int argc, char **argv, char **envp)
105  {
106  	int		pfd[2];
107  	int		status;
108  	pid_t	pid[2];
109  
110  	if (argc != 5)
111  		px_error("Usage: ./pipex infile \"command1\" \"command2\" " \
112  				"outfile\n", NULL, 1);
113  	px_pipe(pfd);
114  	pid[0] = fork();
115  	if (pid[0] == -1)
116  		px_error("Error: fork\n", NULL, 1);
117  	else if (pid[0] == 0)
118  		child_write(argv, envp, pfd);
119  	pid[1] = fork();
120  	if (pid[1] == -1)
121  		px_error("Error: fork\n", NULL, 1);
122  	else if (pid[1] == 0)
123  		child_read(argv, envp, pfd);
124  	px_close(pfd[0]);
125  	px_close(pfd[1]);
126  	if (waitpid(pid[0], NULL, WNOHANG) == -1)
127  		px_error("Error: child write\n", NULL, 1);
128  	if (waitpid(pid[1], &status, 0) == -1)
129  		px_error("Error: child read\n", NULL, 1);
130  	return (WEXITSTATUS(status));
131  }