0

I'm writing a program that executes the word count command on the child process. The father process should send a sequence of lines entered by the user trough a pipeline to the child process. I tried to do this but I ended up with an error. This is my code:

int main ()
{
    int fd[2];
    char buff;
    int pid;
    int pip;
    pid = fork();
    pip = pipe(fd);

    if (pid != 0)
    {
        pip = pipe(fd);
        if (pipe == 0)
        {
            while (read(fd[0], &buff,1) > 0 )
            {
                write (fd[1],&buff,1);      
            }
            close(fd[0]);
            _exit(0);
        }
    }
    else
    {
        dup2(fd[1],1);
        close(fd[1]);
        execlp ("wc","wc",NULL);
        _exit(-1);
    }
    return 0;
}

I've also tried to use dup2 to associate the standard input from the child to the read descriptor of the pipe created by the father process. But I get this error : wc: standard input: Input/output error. How can I solve this?

UPDATED (the error is solved but I get an infinite loop)

int main ()
{
    int fd[2];
    char buff;
    int pid;
    int pip;

    pip = pipe(fd);

    if (pip == 0)
    {
             pid = fork();
         if (pid != 0)
          {     

            while (read(fd[0], &buff,1) > 0 )
            {
                write (fd[1],&buff,1);      
            }
            close(fd[0]);

          }
          else {

        dup2(fd[1],1);
        close(fd[1]);
        execlp ("wc","wc",NULL);
        _exit(-1);
          }
    }
    return 0;
}
José Cunha
  • 107
  • 1
  • 9
  • 2
    Why are you calling pipe() twice on the same fd array? Why are you first forking and then creating the pipe? Creating the pipe in one thread and using it in the other thread is open to race conditions. – Werner Henze Apr 13 '16 at 16:11
  • @WernerHenze You're right , the pipe was meant to be created by the father process . My mistake. – José Cunha Apr 13 '16 at 16:15
  • 1
    @WernerHenze, it is worse than you say, because there are no threads here, and therefore no shared data. The child process will *never* see the effect of the second `pipe()` call in its copy of the array, and by making that call, the parent loses the FDs of the pipe to the child. – John Bollinger Apr 13 '16 at 16:16
  • Do you want wc's output to just show up on the screen, or are you hoping to read it in the parent program? If so, you may need a second pipe (and the logic gets even tricker). – Steve Summit Apr 13 '16 at 16:19
  • @JohnBollinger I already fixed the issue with the pipe and I made only the parent making the pipe. However the wc command only gives me 0. – José Cunha Apr 13 '16 at 16:20
  • Why do you call `_exit()` instead of `exit()`? Or indeed, instead of just letting the program reach the end of `main()`? Nothing useful is gained by using `_exit()` in this case, and although it is specified by POSIX, it is not part of standard C (which has `_Exit()` instead). – John Bollinger Apr 13 '16 at 16:21
  • @SteveSummit I want wc's output to just show up on the screen. – José Cunha Apr 13 '16 at 16:21
  • 1
    @JoséCunha If you changed the code, then please update your question. – Werner Henze Apr 13 '16 at 16:21
  • @JoséCunha, your corrected code is still wrong. The pipe needs to be created *before* the fork if both parent and child are to see the same contents. C.f. my previous comments about *no shared data*. – John Bollinger Apr 13 '16 at 16:24
  • @WernerHenze You're right is now updated. @JohnBollinger Yes you're right , I should let the program reach the main , but I still did the `_exit(-1)` after the `execlp` to check for errors – José Cunha Apr 13 '16 at 16:26
  • @JohnBollinger I updated and followed your suggestion but now I get nothing in the output – José Cunha Apr 13 '16 at 16:34
  • @JoséCunha, in the latest version of your code, you *still* create the pipe after forking. Now parent and child each do it. – John Bollinger Apr 13 '16 at 16:36
  • @JohnBollinger I've now updated and I get an infinite loop (thank you for the patience) – José Cunha Apr 13 '16 at 16:38
  • 1
    Your file descriptor handling is broken. Please think about which process shall read from where (console, pipe) and write to where (console, pipe). Drawing a diagram might help. Then try to match that with your code and think about where to read/write from/to files 0, 1, fd[0] and fd[1]. – Werner Henze Apr 13 '16 at 16:59
  • @WernerHenze Ok , so the parent process must read from the console so must change `read(f[0]..)` to `read(0..)` and write on the `fd[1]` , and the child process must read from `fd[1]` and write on the console right ? – José Cunha Apr 13 '16 at 17:13

1 Answers1

0
#include <unistd.h>

int main ()
{
    int fd[2];
    char buff;
    int pid;
    int pip;
    int status;

    pip = pipe(fd);

    if (pip == 0)
    {
        pid = fork();
        if (pid != 0)
        {
            close(fd[0]);
            while (read(0, &buff,1) > 0 )
            {
                write (fd[1],&buff,1); /* your old loop forwarded internally in the pipe only*/
            }
            close(fd[1]);
         } else {
             dup2(fd[0],0);  /* you had dup2(fd[1], 1), replacing stdout of wc with the write end from wc */
             close(fd[0]);
             close(fd[1]);
             execlp ("wc","wc",NULL);
             _exit(-1);
          }
    }
    wait(&status); /* reap the child process */
    return 0;
}
Stian Skjelstad
  • 2,277
  • 1
  • 9
  • 19