C Pipe to STDIN of Another Program

2019-02-15 12:36发布

问题:

I can barely understand the man page for pipe, so I kinda need help understanding how to take a piped input in an external executable.

I have 2 programs: main.o & log.o

I written main.o to fork. Here is what it is doing:

  • Parent fork will pipe data to the child
  • Child fork will exec log.o

I need the child fork for main to pipe to STDIN of log.o

log.o simply takes STDIN & logs with time stamp to a file.

My code is composed of some code from various StackOverflow pages I dont remember & the man page for pipe:

printf("\n> ");
while(fgets(input, MAXINPUTLINE, stdin)){
   char buf;
   int fd[2], num, status;
   if(pipe(fd)){
      perror("Pipe broke, dood");
      return 111;
   }
   switch(fork()){
   case -1:
      perror("Fork is sad fais");
      return 111;

   case 0: // Child
      close(fd[1]); // Close unused write end
      while (read(fd[0], &buf, 1) > 0) write(STDOUT_FILENO, &buf, 1);

      write(STDOUT_FILENO, "\n", 1);
      close(fd[0]);
      execlp("./log", "log", "log.txt", 0); // This is where I am confused
      _exit(EXIT_FAILURE);

   default: // Parent
      data=stuff_happens_here();
      close(fd[0]); // Close unused read end
      write(fd[1], data, strlen(data));
      close(fd[1]); // Reader will see EOF
      wait(NULL); // Wait for child
   }
   printf("\n> ");
}

回答1:

I suppose this is what you're going to do:
1. main fork, parent pass message to child via pipe.
2. child receive message from pipe, redirect message to STDIN, execute log.
3. log receive message from STDIN, do something.

the key to do this is dup2 to redirect file descriptor, from pipe to STDIN.

This is the modified simple version:

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

int main(int argc, char *argv[]) {
    int fd[2];
    char buf[] = "HELLO WORLD!";
    if(pipe(fd)){
      perror("pipe");
      return -1;
    }
    switch(fork()){
        case -1:
            perror("fork");
            return -1;
        case 0:
            // child
            close(fd[1]);
            dup2(fd[0], STDIN_FILENO);
            close(fd[0]);
            execl("./log", NULL);
        default:
            // parent
            close(fd[0]);
            write(fd[1], buf, sizeof(buf));
            close(fd[1]);
            wait(NULL);
    }
    printf("END~\n");
    return 0;
}  


回答2:

I can suggest a simpler approach. There's a function called popen(). It works very similar to the system() function except you can read or write to/from the child stdin/stdout.

Example:

int main(int argc, char* argv[])
{
    FILE* fChild = popen("logApp.exe", "wb"); // the logger app is another application
    if (NULL == fChild) return -1;

    fprintf(fChild, "Hello world!\n");

    pclose(fChild);
}

Write "man popen" in your console for a full description.



回答3:

You could use dup2

See Mapping UNIX pipe descriptors to stdin and stdout in C



标签: c pipe