I am writing a program that duplicates the command:

grep -cr Thread nachos/ | sort -t : +1.0 -2.0 --numeric --reverse | head --lines=5

My code:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>

#define R_FILE "/proc/meminfo"
#define GREP_EXEC "/bin/grep"
#define SORT_EXEC "/bin/sort"
#define HEAD_EXEC "/usr/bin/head"
#define BSIZE 256 


int main()
{
    int status;
    pid_t pid_1, pid_2, pid_3;
	
	int pipefd[4];
	//int pipefd[2];
	pipe(pipefd);
	pipe(pipefd + 2);

    pid_1 = fork();
    if (pid_1 == 0) { 
        /* grep process */
		dup2(pipefd[1], 1);
		
		close(pipefd[0]);
		close(pipefd[1]);
		close(pipefd[2]);
		close(pipefd[3]);
		execl("grep", "-cr", "Thread", "nachos/", (char *) 0);
				
	    return 0;
    } 

    pid_2 = fork();
    if (pid_2 == 0) {
        /* sort process */
		dup2(pipefd[0], 0);
		dup2(pipefd[3], 1);

		close(pipefd[0]);
		close(pipefd[1]);
		close(pipefd[2]);
		close(pipefd[3]);
		execl("sort", "-t", ":", "+1.0", "-2.0", "–-numeric", "-–reverse", (char *) 0);
        return 0;
    }

    pid_3 = fork();
    if (pid_3 == 0) {
        /* head process */
		dup2(pipefd[2], 0);
		//dup2(pipefd[0], 0);
		
		close(pipefd[0]);
		close(pipefd[1]);
		close(pipefd[2]);
		close(pipefd[3]);
		execl("head", "--lines=5", (char *) 0);
        return 0;
    } 

    close(STDIN_FILENO);
    close(STDOUT_FILENO);

    if ((waitpid(pid_1, &status, 0)) == -1) {
        fprintf(stderr, "Process 1 encountered an error. ERROR%d", errno);
        return EXIT_FAILURE;
    }        

    if ((waitpid(pid_2, &status, 0)) == -1) {
        fprintf(stderr, "Process 2 encountered an error. ERROR%d", errno);
        return EXIT_FAILURE;
    }

    if ((waitpid(pid_3, &status, 0)) == -1) {
        fprintf(stderr, "Process 3 encountered an error. ERROR%d", errno);
        return EXIT_FAILURE;
    }
    return 0;
}

I don't see what I am doing wrong. I am matching the write of the fd to stdout and likewise for read of the fd to stdin. My pipes seem to be matched up. Yet I get no output. Please any help would be appreciated.

#
close(pipefd[0]);
#
close(pipefd[1]);
#
close(pipefd[2]);
#
close(pipefd[3]);

you don't understand pipe...

please read the book about pipe...

show you simple example of pipe

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <wait.h>

int main()
{
    pid_t pid;
    int pipe_fd[2];
    if ( pipe(pipe_fd) == -1 )
    {
        perror("Pipe create error");
        exit(1);
    }

    if ( (pid = fork()) == -1 )
    {
        perror("Fork create error");
        exit(1);
    }

    if ( pid == 0 )
    {
        close(pipe_fd[0]);                   /* close open fd of pipe */
        
        /* write fd of pipe */
        if ( write(pipe_fd[1], "this is pipe", 128) == -1 )
        {
            perror("Write Error");
            exit(1);
        }
        exit(0);
    }

    if ( pipe > 0 )
    {
        waitpid(pid, NULL, 0);
        close(pipe_fd[1]);                   /* close write fd of pipe */      
        char buffer[14] = { 0 };
        
        /* read fd of pipe */
        if ( read(pipe_fd[0], buffer, 128) == -1 )
        {
            perror("Read error");
            exit(1);
        }
        printf("Read string is : %s", buffer);
        exit(0);
    }
}

I can help you a little bit. My changes are in red

show you simple example of pipe

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <wait.h>

int main()
{
    pid_t pid;
    int pipe_fd[2];
    if ( pipe(pipe_fd) == -1 )
    {
        perror("Pipe create error");
        exit(1);
    }

    if ( (pid = fork()) == -1 )
    {
        perror("Fork create error");
        exit(1);
    }

    if ( pid == 0 )
    {
        close(pipe_fd[0]);                   /* close open fd of pipe */
        
        /* write fd of pipe */
        /* Connect stdout to your pipe */
        /* Then execute the grep function */  
        if ( write(pipe_fd[1], "this is pipe", 128) == -1 )
        {
            perror("Write Error");
            exit(1);
        }
        exit(0);
    }

    if ( pid > 0 )
    {
        waitpid(pid, NULL, 0);
        close(pipe_fd[1]);                   /* close write fd of pipe */      
        char buffer[14] = { 0 };
        
        /* read fd of pipe */
        /* Now execute the sort command. But I dont know how will you tell the system that you want to sort the contents in buffer */

        if ( read(pipe_fd[0], buffer, 128) == -1 )
        {
            perror("Read error");
            exit(1);
        }
        printf("Read string is : %s", buffer);
        exit(0);
    }
}

Now I'm getting an error:

sort: invalid option -- ''

Let me explain my code a bit. It thought that with pipes and dup2 I can redirect stdin and stdout to fd[0] and fd[1]. Therefore you dont need to write to the buffer.

pipe(pipes); // sets up 1st pipe
pipe(pipes + 2); // sets up 2nd pipe

Which makes 4 fd's:

// pipes[0] = read end of grep->sort pipe (read by sort)
// pipes[1] = write end of grep->sort pipe (written by grep)
// pipes[2] = read end of sort->head pipe (read by head)
// pipes[3] = write end of sort->head pipe (written by grep)

My updated code:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>

#define R_FILE "/proc/meminfo"
#define GREP_EXEC "/bin/grep"
#define SORT_EXEC "/bin/sort"
#define HEAD_EXEC "/usr/bin/head"
#define BSIZE 256 


int main()
{
    int status;
    pid_t pid_1, pid_2, pid_3;
	
	int pipefd[4];
	pipe(pipefd);
	pipe(pipefd + 2);

    pid_1 = fork();
    if (pid_1 == 0) { 
        /* grep process */
		close(pipefd[0]);
		close(pipefd[2]);
		close(pipefd[3]);
		
		dup2(pipefd[1], 1);
		
		close(pipefd[1]);
		execl(GREP_EXEC, "grep", "-cr", "Thread", "nachos/", (char *) 0);
	    return 0;
    } 

    pid_2 = fork();
    if (pid_2 == 0) {
        /* sort process */
		close(pipefd[1]);
		close(pipefd[2]);
		
		dup2(pipefd[0], 0);
		dup2(pipefd[3], 1);
		
		close(pipefd[0]);
		close(pipefd[3]);
		
		execl(SORT_EXEC, "sort", "-t", ":", "+1.0", "-2.0", "–-numeric", "-–reverse", (char *) 0);
        return 0;
    }

    pid_3 = fork();
    if (pid_3 == 0) {
        /* head process */
		close(pipefd[0]);
		close(pipefd[1]);
		close(pipefd[3]);
		
		dup2(pipefd[2], 0);
		
		close(pipefd[2]);
		
		execl(HEAD_EXEC, "head", "--lines=5", (char *) 0);
        return 0;
    } 

    /* shell process */
	
	
	
	
    /* Remember to close unused pipes! */
        close(pipefd[0]);
	close(pipefd[1]);
	close(pipefd[2]);
	close(pipefd[3]);
    close(STDIN_FILENO);
    close(STDOUT_FILENO);

    if ((waitpid(pid_1, &status, 0)) == -1) {
        fprintf(stderr, "Process 1 encountered an error. ERROR%d", errno);
        return EXIT_FAILURE;
    }        

    if ((waitpid(pid_2, &status, 0)) == -1) {
        fprintf(stderr, "Process 2 encountered an error. ERROR%d", errno);
        return EXIT_FAILURE;
    }

    if ((waitpid(pid_3, &status, 0)) == -1) {
        fprintf(stderr, "Process 3 encountered an error. ERROR%d", errno);
        return EXIT_FAILURE;
    }
    return 0;
}

you can read 《advanced programming unix environment》or 《unix network programming》volume 2 can help you know what is pipe and IPC

I am going to post my working code. I could not find an exact example of this on the intrawebs.

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>

#define R_FILE "/proc/meminfo"
#define GREP_EXEC "/bin/grep"
#define SORT_EXEC "/bin/sort"
#define HEAD_EXEC "/usr/bin/head"
#define BSIZE 256 


int main(int argc, char *argv[])
{
    int status;
    pid_t pid_1, pid_2, pid_3;
	
	int pipefd[2];
	int pipefd2[2];
	pipe(pipefd);
	pipe(pipefd2);

    pid_1 = fork();
    if (pid_1 == 0) { 
        /* grep process */
		close(pipefd[0]);
		close(pipefd2[0]);
		close(pipefd2[1]);
		close(STDIN_FILENO);
		close(STDIN_FILENO);
		dup2(pipefd[1], 1);
		close(pipefd[1]);
		execl(GREP_EXEC, "grep", "-cr", "Thread", "nachos/", (char *) 0);
	    return 0;
    } 

    pid_2 = fork();
    if (pid_2 == 0) {
        /* sort process */
		close(pipefd[1]);
		close(pipefd2[0]);
		close(STDIN_FILENO);
		close(STDIN_FILENO);
		
		//dup2(pipefd[0], 0);
		//dup2(pipefd2[1], 1);
		
		dup2(pipefd[0], 0);
		dup2(pipefd2[1], 1);
		
		close(pipefd[0]);
		close(pipefd2[1]);
		execl(SORT_EXEC, "sort", "-t", ":", "+1.0", "-2.0", "--numeric", "--reverse", (char *) 0);
        return 0;
    }

    pid_3 = fork();
    if (pid_3 == 0) {
        /* head process */
		close(pipefd[0]);
		close(pipefd[1]);
		close(pipefd2[1]);
		dup2(pipefd2[0], 0);
		close(pipefd2[0]);
		execl(HEAD_EXEC, "head", "--lines=5", (char *) 0);
        return 0;
    }

    /* shell process */
    /* Remember to close unused pipes! */
	close(pipefd[0]);
	close(pipefd[1]);
	close(pipefd2[0]);
	close(pipefd2[1]);
    close(STDIN_FILENO);
    close(STDOUT_FILENO);

    if ((waitpid(pid_1, &status, 0)) == -1) {
        fprintf(stderr, "Process 1 encountered an error. ERROR%d", errno);
        return EXIT_FAILURE;
    }        

    if ((waitpid(pid_2, &status, 0)) == -1) {
        fprintf(stderr, "Process 2 encountered an error. ERROR%d", errno);
        return EXIT_FAILURE;
    }

    if ((waitpid(pid_3, &status, 0)) == -1) {
        fprintf(stderr, "Process 3 encountered an error. ERROR%d", errno);
        return EXIT_FAILURE;
    }
    return 0;
}
This question has already been answered. Start a new discussion instead.