/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* executor_new.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: sede-san #include static void handle_execve_error(); static void handle_parent_process( int *prev_read_fd, t_list *current_command, int pipefd[2] ); static int handle_pipeline( t_list *current_command, int pipefd[2], int *exit_status ); static inline uint8_t execute_builtin( t_command *command, t_minishell *minishell ); static void execute_external_command( t_command *command, t_minishell *minishell ); static pid_t handle_fork( t_list *current_command, t_minishell *minishell ); static uint8_t execute_command( t_command *command, t_minishell *minishell ); static inline bool can_execute_command(t_command *command, t_minishell *minishell); static inline bool command_exists(t_command *command, t_minishell *minishell); static void cmdfree(t_command *command); static void cmdfree_argv(char **argv); # define WRITE_PIPE 1 # define READ_PIPE 0 # define CHILD_PID 0 u_int8_t execute( t_list *command_list, t_minishell *minishell ) { t_list *current_command; int prev_read_fd; int exit_status; int pipefd[2]; pid_t pid; prev_read_fd = -1; exit_status = EXIT_SUCCESS; current_command = command_list; while (current_command != NULL) { if (handle_pipeline(current_command, pipefd, &exit_status) == EXIT_FAILURE) break ; pid = handle_fork(current_command, minishell); if (pid == -1) { perror("fork"); exit_status = EXIT_FAILURE; break ; } if (pid == CHILD_PID) handle_child_process(prev_read_fd, current_command, pipefd, minishell); handle_parent_process(&prev_read_fd, current_command, pipefd); current_command = current_command->next; } ft_lstclear(&command_list, (void (*)(void *))cmdfree); while (wait(&exit_status) > 0) { if (WIFEXITED(exit_status)) exit_status = WEXITSTATUS(exit_status); } return (exit_status); } static int handle_pipeline( t_list *current_command, int pipefd[2], int *exit_status ) { if (current_command->next) // create pipe if needed { if (pipe(pipefd) == -1) { perror("pipe"); *exit_status = EXIT_FAILURE; return (EXIT_FAILURE); } } return (EXIT_SUCCESS); } static void handle_parent_process( int *prev_read_fd, t_list *current_command, int pipefd[2] ) { if (*prev_read_fd != -1) close(*prev_read_fd); if (current_command->next) { close(pipefd[WRITE_PIPE]); // parent does not write *prev_read_fd = pipefd[READ_PIPE]; // pass read end forward } else *prev_read_fd = -1; } static pid_t handle_fork( t_list *current_command, t_minishell *minishell ) { pid_t pid; const t_command *command = (t_command *)current_command->content; pid = 0; if (current_command->next != NULL || !is_builtin(command->path, minishell)) pid = fork(); return (pid); } void handle_child_process(int prev_read_fd, t_list *current_command, int pipefd[2], t_minishell *minishell) { redirect_pipes(prev_read_fd, current_command, pipefd); execute_command((t_command *)current_command->content, minishell); } void redirect_pipes(int prev_read_fd, t_list *current_command, int pipefd[2]) { redirect_input_pipe(prev_read_fd); redirect_output_pipe(current_command, pipefd); } void redirect_output_pipe(t_list * current_command, int pipefd[2]) { if (current_command->next) { dup2(pipefd[WRITE_PIPE], STDOUT_FILENO); close(pipefd[READ_PIPE]); close(pipefd[WRITE_PIPE]); } } void redirect_input_pipe(int prev_read_fd) { if (prev_read_fd != -1) { dup2(prev_read_fd, STDIN_FILENO); close(prev_read_fd); } } static inline bool can_execute_command( t_command *command, t_minishell *minishell ) { if (!is_builtin(command->path, minishell) && access(command->path, X_OK) != EXIT_SUCCESS) return (false); return (true); } static inline bool command_exists( t_command *command, t_minishell *minishell ) { if (!is_builtin(command->path, minishell) && access(command->path, F_OK) != EXIT_SUCCESS) return (false); return (true); } static uint8_t execute_command( t_command *command, t_minishell *minishell ) { if (is_builtin(command->path, minishell)) return (execute_builtin(command, minishell)); else { execute_external_command(command, minishell); return (EXIT_FAILURE); //! should never reach here } } static inline uint8_t execute_builtin( t_command *command, t_minishell *minishell ) { const t_builtin_func builtin = ft_hashmap_get(minishell->builtins, command->path); return (builtin(*command, minishell)); } static void execute_external_command( t_command *command, t_minishell *minishell ) { char **envp; envp = get_envp(minishell); if (envp == NULL) { perror("get_envp"); exit(EXIT_FAILURE); } execve(command->path, command->argv, envp); handle_execve_error(); } static void handle_execve_error() { perror("execve"); exit(EXIT_FAILURE); } // static inline bool is_piped( // t_command *command // ) { // return (command->piped_to != NULL || command->piped_from != NULL); // } // static u_int8_t handle_child_process( // t_command *command, // t_minishell *minishell // ) { // if (!redirect_pipes(command)) // exit(EXIT_FAILURE); // execute_command(command, minishell); // exit(EXIT_FAILURE); // } // static int redirect_pipe( // int from, // int to // ) { // if (dup2(from, to) == -1) // return (-1); // close(from); // return (0); // } // static int redirect_pipes( // t_command *command // ) { // if (command->piped_from && // redirect_pipe(command->piped_from->outfile, STDIN_FILENO) == -1) // { // perror("dup2"); // return (0); // } // if (command->piped_to && // redirect_pipe(command->outfile, STDOUT_FILENO) == -1) // { // perror("dup2"); // return (0); // } // return (1); // } // static void show_error( // t_command *command, // t_minishell *minishell // ) { // if (!command_exists(command, minishell)) // { // ft_eprintf("minishell: %s: command not found\n", command->argv[0]); // minishell->exit_status = 127; // } // else if (!can_execute_command(command, minishell)) // { // ft_eprintf("minishell: %s: %s\n", command->path, strerror(errno)); // minishell->exit_status = errno; // } // } static void cmdfree( t_command *command ) { if (command == NULL) return ; cmdfree_argv(command->argv); free(command->path); free(command); } static void cmdfree_argv( char **argv ) { size_t i; if (argv == NULL) return ; i = 0; while (argv[i] != NULL) { free(argv[i]); i++; } free(argv); } // static void debug_print_command_info( // t_command *command // ) { // size_t i; // if (command == NULL) // { // printf("Command is NULL\n"); // return ; // } // printf("Command info:\n"); // printf(" Path: %s\n", command->path); // printf(" Argc: %d\n", command->argc); // printf(" Argv:\n"); // for (i = 0; i < (size_t)command->argc; i++) // printf(" arg[%zu]: %s\n", i, command->argv[i]); // printf(" Infile FD: %d\n", command->infile); // printf(" Outfile FD: %d\n", command->outfile); // printf("--------------------------\n"); // }