1

I am trying to execute an external program (echo is just for testing, but should work nevertheless). The program takes the first argument and submits it to the second, that requires them over STDIN.

The redirection to the pipe and therefore to STDIN is working perfectly, if you print out the pipe content instead of using exec.

But the program (echo) is not returning anything, the behaviour stays the same. Therefore the STDIN is not redirected, but I don't understand why. Is there a missing parameter in the exec-family I am missing or something?

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

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        printf("parameters do not match");
        exit(1);
    }

    // create two pipes
    int downstream[2];
    int upstream[2];
    pipe(downstream);
    pipe(upstream);

    // create child
    if (fork() == 0)
    {
        // close not required descriptors
        close(upstream[0]);
        close(downstream[1]);

        // close and duplicate stdin/stdout from pipe 
        dup2(downstream[0], STDIN_FILENO);
        dup2(upstream[1], STDOUT_FILENO);

        // exec
        // What to do here?
        char *args[] = {"echo", NULL};

        execvp(args[0], args);
        exit(0);
    }

    // close not required
    close(upstream[1]);
    close(downstream[0]);

    // send second argument to pipe
    write(downstream[1], argv[1], strlen(argv[1]));

    // read result from pipe
    char buffer[100];
    read(upstream[0], buffer, 100);
    printf("OUTPUT: %s", buffer);
    exit(0);
}
4
  • 1
    echo does not read from stdin. Commented Dec 16, 2019 at 23:38
  • 2
    use cat instead. Commented Dec 16, 2019 at 23:47
  • 1
    You do not need to add terminating NUL to argv[1]. It's already NUL terminated. consider removing argv[1][strlen(argv[1])] = '\0'; Commented Dec 17, 2019 at 6:16
  • Thanks @dash-o, removed it from the question. Commented Dec 17, 2019 at 9:56

1 Answer 1

1

You might want to modify the way you deliver the data, so that it will work for programs that are working in blocks, and expect EOF indicator.

The main should close the downstream, once it deliver the data. This will allow many programs that work in buffered mode to process the input, even when it's not completed lines. Also should checks for error/EOF on data coming from the child, and handle the output of large blocks.

Proposed main

    ...
    close(upstream[1]);
    close(downstream[0]);

    // send second argument to pipe
    write(downstream[1], argv[1], strlen(argv[1]));
    close(downstream[1]) ;

    // read result from pipe
    char buffer[100];
    int nread ;
    // Lop until EOF or error.
    while ( (nread=read(upstream[0], buffer, sizeof(buffer)-1) > 0 ) {
        buffer[nread] = 0 ;       // NUL terminator.
        printf("OUTPUT: %s", buffer);
    } ;
    exit(0);

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.