0

I'm trying to execute the Linux command "ls -l | tail -n 2" with a simple pipe in a c code.

I added your tips and now this works but the output isn't exactly as it should be. It prints the output in a single line instead of two and waits for a user input to close. here is the new code:

#include "stdio.h"
#include "unistd.h"
#include "stdlib.h"
#include "sys/wait.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

void main()
{
    char line[100];
    pid_t pid;
    int fd[2];
    int status;
    char* ls_arguments[] = {"ls", "-l", NULL};
    char* tail_arguments[] = {"tail", "-n", "2", NULL};
    pipe(fd);
    pid = fork();
    if(pid == 0)//ls client
    {
        close(1);
        dup(fd[1]);
        close(fd[0]);
        execvp("ls", ls_arguments);
    }
    pid = fork();
    if(pid == 0)//tail client
    {
        close(0);
    close(fd[1]);
        dup(fd[0]);
        execvp("tail", tail_arguments);
    }
    wait(pid, 0, WNOHANG);
    close(fd[0]);
    close(fd[1]);
}

this should run the "ls -l" command and output to the pipe and the next "tail" client would get it as input and run the "tail -n 2" command and print out the final output but the terminal prints nothing. Any help?

12
  • There's no point in putting code after execvp(), since it never returns unless it gets an error. Commented Jan 31, 2017 at 21:37
  • You need to close(fd[0]) in the ls client and close(fd[1]) in the tail client before they each call exec. Commented Jan 31, 2017 at 21:38
  • And the parent process needs to close both of them. Commented Jan 31, 2017 at 21:39
  • but if i close the pipe in the ls client it will be closed in the tail client right? Commented Jan 31, 2017 at 21:42
  • No. Closing an fd in one process has no effect on other processes. The pipe doesn't go away until all processes close it. Commented Jan 31, 2017 at 21:44

1 Answer 1

1

First of all, there is not such wait function, here is what the man says:

#include <sys/types.h>
#include <sys/wait.h>

pid_t wait(int *status);

pid_t waitpid(pid_t pid, int *status, int options);

I think you meant to use waitpid.

Then, you child process doesn't finish because the pipe is still opened somewhere: in the parent. Indeed you should first close the descriptors and then wait for your childs process. I would write:

  close(fd[0]);
  close(fd[1]);
  wait(NULL); // Wait for the first child to finish
  wait(NULL); // Wait fot the second one
  return 0;
}

Instead of:

  wait(pid, 0, WNOHANG);
  close(fd[0]);
  close(fd[1]);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.