Search code examples
cpipeforkdup2execve

C : (standard input): Bad file descriptor


I try to recreate for a school project a program who emulate this type of command

< infile grep g | wc -c > outfile

Someone i have any idea why i'm getting

grep: (standard input): Bad file descriptor

when running the following code

void    first_cmd_exec(t_command *cmd, char **envp, int *pipe_fd)
    {
        if ((cmd->fd = open(cmd->file, O_WRONLY)) == -1)
            perror_exit("open");
        if (close(pipe_fd[0]) == -1)        
            perror_exit("close 1 1st cmd");
        if (dup2(cmd->fd, STDIN_FILENO) == -1)                   
            perror_exit("dup2 1st cmd");
        if (dup2(pipe_fd[1], STDOUT_FILENO) == -1)
            perror_exit("dup2 1st cmd");
        if (close(pipe_fd[1]) == -1)
            perror_exit("close 2 1st cmd");
        if (execve(cmd->path_exec, cmd->tab_cmd, envp) == -1)
            perror_exit("execve 1st cmd");
    }

void    last_cmd_exec(t_command *cmd, char **envp, int *pipe_fd)
    {
        cmd = cmd->next;
        if ((cmd->fd = open(cmd->file, O_WRONLY)) == -1)
            perror_exit("open 2nd cmd");
        if (close(pipe_fd[1]) == -1)                            
            perror_exit("close 1 2nd cmd");
        if (dup2(cmd->fd, STDOUT_FILENO) == -1)                 
            perror_exit("dup2 2nd cmd");
        if (dup2(pipe_fd[0], STDIN_FILENO) == -1)               
            perror_exit("dup2 2nd cmd");
        if (close(pipe_fd[0]) == -1)
            perror_exit("close 2 2nd cmd");
        if (execve(cmd->path_exec, cmd->tab_cmd, envp) == -1)
            perror_exit("execve 2nd cmd");
        exit(EXIT_SUCCESS);
    }

void fork_it(t_list *list, char **envp)
    {
        pid_t       pid;
        pid_t       pid_2;
        t_command   *cmd;
        int         status;
        int         pipe_fd[2];
    
        cmd = list->first;
        if (pipe(pipe_fd) == -1)
            perror_exit("pipe");
        pid = fork();
        if (pid < 0)
            perror_exit("fork");
        else if (pid == 0)
            first_cmd_exec(cmd, envp, pipe_fd); 
        pid_2 = fork();
        if (pid_2 < 0)
            perror_exit("fork");
        else if (pid_2 == 0)
            last_cmd_exec(cmd, envp, pipe_fd);  
        else
        {
            close(pipe_fd[0]);
            close(pipe_fd[1]);
            waitpid(pid, &status, 0);
            waitpid(pid_2, &status, 0);
        }
    
    }

If I understand correctly I have to use dup2 to replace the standard input with my fd (my infile), so that my execve command can use it, and the same for my second command after the pipe so that it can write to my output file, but I must be missing something in my understanding or my code.

Thanks in advance


Solution

  • https://man7.org/linux/man-pages/man2/read.2.html

    EBADF fd is not a valid file descriptor or is not open for reading.

    is grep's stdin open for reading?

    void    first_cmd_exec(t_command *cmd, char **envp, int *pipe_fd)
        {
            if ((cmd->fd = open(cmd->file, **O_WRONLY**)) == -1)
    

    no, you seem to be opening it write-only for some reason.