在 c 中实现 Bash 管道和重定向

问题描述 投票:0回答:1

interesting screen lldb

我在实现管道和输出重定向时遇到问题。 单独使用效果很好,但是当我尝试时

'ls | wc > a',
它的功能与真正的 Bash 不同。它创建文件“a”,但它不会将
'ls | wc'
的输出重定向到该文件并创建无限循环它等待 pid,但我有循环等待最后的所有函数,我做了一个错误,但我不知道哪里?

我有一个用于创建管道及其执行的函数,以及用于重定向的函数,我找不到我的问题的解决方案 为什么我的| wc > file' 未从我的文件重定向

管道.c

void create_pipe(int pipe_fd[2], int i, int last) 
{
    if (i < (last - 1))
    {
        if (pipe(pipe_fd) == -1) 
        {
            perror("pipe");
            exit(EXIT_FAILURE);
        }
    }
}

void close_pipes_in_parent(int i, t_data *data, int *input_fd) 
{
    if (i != data->first)
        close(*input_fd);
    if (i < data->last) 
    {
        close(data->pipe_fd[1]);
        *input_fd = data->pipe_fd[0];
    }

}


pid_t fork_process_pipe(int i, int input_fd, t_data *data, t_Token *curr, char **envp, t_Token *lst_tok) 
{
    pid_t pid = fork(); 

    if (pid == 0)
    { 
        printf("111111111111111111");
        if (i != data->first) 
        {
                dup2(input_fd, STDIN_FILENO);
                close(input_fd);
        }
        if (i < data->last) 
        {
                dup2(data->pipe_fd[1], STDOUT_FILENO);
                close(data->pipe_fd[0]);
                close(data->pipe_fd[1]);
        }
        data->path_exe = ft_get_reading(data, curr, envp);
        if(!data->path_exe)
        {
            printf("Bash : command not found : %s\n", data->cmd[0]);
            ft_free_tabtab(data->cmd);
            free_token(lst_tok);
            exit(EXIT_FAILURE);
        }
        if (execve(data->path_exe, data->cmd, envp) == -1) 
        {
            ft_free_tabtab(data->cmd);
            free(data->path_exe);
            exit(EXIT_FAILURE);
        }
        free(curr->Token_str);
        free(curr);
    }
    return (pid);
}


redir.c

int *creat_fd_out(t_data *data, t_Token *curr, int *output_fd)
{
    int i;

    i = 0;
    while(i < data->nb_file)
    {
        output_fd[i] =  open(curr->next->next->Token_str, O_CREAT | O_WRONLY | O_TRUNC, 0644);
        if (output_fd[i] == -1) 
            exit(EXIT_FAILURE);
        i++;
        curr = curr->next->next ;
    }
    return(output_fd);
}

void close_fd_in(t_data *data, int *output_fd)
{
    int i;

    i = 0;
    while(i < data->nb_file)
    {    
        close(output_fd[i]);
        i++;
    }
}

pid_t fork_process_redi(t_data *data, t_Token *curr, char **envp, t_Token *lst_tok) 
{
    pid_t pid = fork(); 
    int *output_fd = malloc(data->nb_file * sizeof(int)); 
    
    if (pid == 0)
    { 
        if ((curr->type == E_WORD && curr->next != NULL) && (curr->next->Token_str[0] == '>'))
        {  
            data->path_exe = ft_get_reading(data, curr, envp);
            if(!data->path_exe)
            {
                printf("Bash : command not found : %s\n", data->cmd[0]);
                ft_free_tabtab(data->cmd);
                free_token(lst_tok);
            }
            output_fd = creat_fd_out(data, curr, output_fd);
            dup2(output_fd[data->nb_file -1], STDOUT_FILENO);
            close_fd_in(data, output_fd);

        }
        if (execve(data->path_exe, data->cmd, envp) == -1) 
        {
            ft_free_tabtab(data->cmd);
            free(data->path_exe);
            exit(EXIT_FAILURE);
        }
        free(curr->Token_str);
        free(curr);
    }
    return (pid);
}

lanch_exe.c 

void execute_pipeline_redirection(t_data *data, t_Token *list_token, char **envp) 
{
    int index_fork;
    int input_fd;
    t_Token *curr;

    data->last = data->nb_cmd;
    curr = list_token;
    input_fd = STDIN_FILENO;
    data->first = 0;
    index_fork = 0;
    pid_t pid[data->last];
    

    while (curr != NULL) 
    {   
        if ((curr->type == E_WORD && curr->next != NULL) && (curr->next->Token_str[0] == '>') && (curr->next->next->type == E_FILE))   
        {
            pid[index_fork] = -1;        
            pid[index_fork] = fork_process_redi(data, curr, envp, list_token);
            index_fork++;
        }
        if (((curr->type == E_WORD || curr->next->type ==  E_FILE ) && curr->next != NULL && curr->next->Token_str[0] == '|') && (curr->type == E_WORD && curr->next == NULL))
        {        
            pid[index_fork] = -1;        
            create_pipe(data->pipe_fd, index_fork, data->last);
            pid[index_fork] = fork_process_pipe(index_fork, input_fd, data, curr, envp, list_token);
            close_pipes_in_parent(index_fork, data, &input_fd);
            index_fork++;

        }
        curr = curr->next;
    }
    wait_for_children(data->last, pid);
}

当我像

ls | wc > a
那样进行crestin测试时,我的PID似乎无限期地保持等待状态,而当我执行 母鸡
ls | cat fichier.txt > a
,它工作正常

-> image test0 <-

-> image test1 <-

-> lldb witch will test test.txt""><-

c bash fork wait waitpid
1个回答
0
投票

在 fork_process_redi 中,您正在设置输出文件描述符,而不是输入,就像您在 fork_process_pipe 中所做的那样。带有重定向的管道中的最后一个命令将从 STDIN 读取,直到 EoF 读取,而不是从最后一个命令的管道读取。 “cat file”不会从标准输入读取,并且运行正常。

不相关,但是execve之后的空闲语句永远不会被执行。当分叉进程退出时,内存会被释放,所以这不是问题。

© www.soinside.com 2019 - 2024. All rights reserved.