I'm trying to simulate bash pipe like ls | grep ma | wc but for some reason it seems like my third child process that executes wc just hangs. I can't find the culprit, please help.
Here's my code:
#include <stddef.h> 
#include <stdio.h>  
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define CMD_NUM 3
int main(void)
{
    pid_t pids[CMD_NUM]; 
    int *pipeFd;
    int pipeFds[CMD_NUM - 1][2]; 
    for (int i = 0; i < CMD_NUM - 1; i++)
        if (pipe(pipeFds[i]) == -1)
            perror("Error creating pipes");
    pids[0] = fork();
    if (pids[0] == 0)
    {
        printf("I'm in 1r if\n");
        pipeFd = pipeFds[0];
        close(pipeFd[0]);
        close(1);
        dup2(pipeFd[1], 1);
        char* argv[] = {"ls", "-l", NULL};
        execvp("ls", argv);
        perror("Error ls execvp");
        exit(1);
    }
    
    for (int i = 1; i < CMD_NUM - 1; i++)
        {
            printf("I'm in for\n");
            pids[i] = fork();
            if (pids[i] == 0)
            {
                close(0);
                close(1);
                pipeFd = pipeFds[i - 1]; 
                close(pipeFd[1]);
                dup2(pipeFd[0], 0);
                pipeFd = pipeFds[i]; 
                close(pipeFd[0]);
                dup2(pipeFd[1], 1);
                char* argv[] = {"grep", "ma", NULL};
                execvp("grep", argv);
                perror("Error in execvp");
                exit(1);
            }
        }
        pids[CMD_NUM - 1] = fork();
        if (pids[CMD_NUM - 1] == 0)
        {
            printf("I'm in 2n if\n");
            pipeFd = pipeFds[CMD_NUM - 2];
            close(pipeFd[1]);
            close(0);
            dup2(pipeFd[0], 0);
            char* argv[] = {"wc", NULL};
            perror("hello");
            execvp(argv[0], argv);
            perror("Error en execvp");
            exit(1);
        }
        for (int i = 0; i < CMD_NUM - 1; i++)
        {
            printf("I'm closing pipes\n");
            pipeFd = pipeFds[i];
            close(pipeFd[0]);
            close(pipeFd[1]);
        }
        printf("I'm waiting for my last child\n");
        waitpid(pids[CMD_NUM - 1], NULL, 0);
}
I'm only waiting for the last child because it's a requirement.