Szymon
Szymon

Reputation: 88

Fork exec and pipe with bash script

I would like to put the output from a bash script (sc.sh), which is in the same directory as this program and which contains line below, to the input of a C program (cprog); executing cprog works but I do not know why the bash script is not starting:

timeout 5 cat /dev/urandom

and this is the main program:

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

int main(int argc, char* argv[])
{
    int fd[2];
    pid_t pid1, pid2;
    char * input[] = {"/bin/bash", "sc.sh", argv[1], NULL}; 
    char * output[] = {"./cprog", argv[1], NULL};

    pipe(fd);

    pid1 = fork();
    if (pid1 == 0) {
        dup2(fd[1], STDOUT_FILENO);
        close(fd[0]);
        execv(input[0], input);   
        return 1;
    }

    pid2 = fork();
    if (pid2 == 0) {
        dup2(fd[0], STDIN_FILENO);
        close(fd[1]);
        execv(output[0], output);
        return 1;
    }

    close(fd[0]);
    close(fd[1]);
    waitpid(pid1, NULL, WNOHANG);
    waitpid(pid2, NULL, WNOHANG);
    return 0;
}

Upvotes: 0

Views: 929

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 753890

I modified your program to report errors and actually wait for the children to die, like so:

#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

int main(int argc, char* argv[])
{
    if (argc > 2)
        fprintf(stderr, "Excess arguments ignored\n");
    int fd[2];
    pid_t pid1, pid2;
    char * input[] = {"/bin/bash", "sc.sh", argv[1], NULL}; 
    char * output[] = {"./cprog", argv[1], NULL};

    pipe(fd);

    pid1 = fork();
    if (pid1 == 0) {
        dup2(fd[1], STDOUT_FILENO);
        close(fd[0]);
        close(fd[1]);
        execv(input[0], input);   
        perror(input[0]);
        return 1;
    }

    pid2 = fork();
    if (pid2 == 0) {
        dup2(fd[0], STDIN_FILENO);
        close(fd[0]);
        close(fd[1]);
        execv(output[0], output);
        perror(output[0]);
        return 1;
    }

    close(fd[0]);
    close(fd[1]);
    int status1;
    int corpse1 = waitpid(pid1, &status1, 0);
    printf("PID %d: %d (0x%.4X)\n", pid1, corpse1, status1);
    int status2;
    int corpse2 = waitpid(pid2, &status2, 0);
    printf("PID %d: %d (0x%.4X)\n", pid2, corpse2, status2);
    return 0;
}

I used a simple C program as cprog:

#include <stdio.h>

int main(void)
{
    int c;
    unsigned sum = 0;
    unsigned cnt = 0;
    while ((c = getchar()) != EOF)
        sum += c, cnt++;
    printf("sum of bytes: %u\n", sum);
    printf("num of bytes: %u\n", cnt);
    return 0;
}

Testing on the command line yielded:

$ bash sc.sh | cprog
sum of bytes: 325895667
num of bytes: 69926912
$

Running the main program (it was p19 created from p19.c) yielded:

$ ./p19
sum of bytes: 372818733
num of bytes: 70303744
PID 28575: 28575 (0x7C00)
PID 28576: 28576 (0x0000)
$

The exit status shows that the timeout exited with status 124, which is what GNU documents as the exit status when the command times out.

So, in my reproduction of your environment, the code you provided works OK. That suggests that your environment is not set up as you think. Maybe the sc.sh script isn't there.

Upvotes: 1

Related Questions