Question

referring to the old homework question : /* implementing "/usr/bin/ps -ef | /usr/bin/more" */ using pipes.

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

int main()
{
  int fds[2];
  int child[2];
  char *argv[3];
  pipe(fds);
  if (fork()== 0) {
    close(fds[1]);
    close(STDIN_FILENO); dup(fds[0]); /* redirect standard input to fds[1] */
    argv[0] = "/bin/more";
    argv[1] = NULL;           /* check how the argv array is set */
    execv(argv[0], argv);// here how execv reads from stdin ??
    exit(0);


  }
  if (fork() == 0) {
    close(fds[0]);
    close(STDOUT_FILENO); dup(fds[1]);  /* redirect standard output to fds[0] */
    argv[0] = "/bin/ps";
    argv[1] = "-e"; argv[2] = NULL;
    execv(argv[0], argv);
    exit(0);

  }

  close(fds[1]);
  wait(&child[0]);
  wait(&child[0]);  
} 

After redirecting the fd to standard output, how does execv reads from it. Is it inbuilt in execv that it reads from standard input before executing the command? I am unable to get this concept.

Was it helpful?

Solution

Your question is based on a false premise -- execv doesn't read from anywhere, nor does it need to. It is more that reads from the stdin it inherits across the call to execv. The reason more reads from stdin is because it's a filter and, like most filters, it defaults to reading from stdin if another input source isn't specified on the command line. (Otherwise, /usr/bin/ps -ef | /usr/bin/more wouldn't work.)

OTHER TIPS

In your second fork call, I would change the code from this:

  if (fork() == 0) {
    close(fds[0]);

to this:

  close(fds[0]);
  if (fork() == 0) {

The argv[1] for the ps call should be -ef.

All programs will read from stdin to get terminal input and write to stdout to deliver data to the terminal, if they do not do anything to change the default settings for those streams. What the code is doing is modifying stdin for more and modifying stdout for ps. The stdout for more is the same as the current process (the parent). Thus, your program is redirecting ps terminal output data to be the terminal input for more.

The pipe call returns two file descriptors that are connected to each other unidirectionally. When ps writes to its stdout, it is going to the dupd fds[1]. When more reads from its stdin, it is the dupd fds[0]. So, more picks up the output of ps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top