samad bond samad bond - 1 month ago 18
C Question

Running fifo pipe from single terminal

I was wondering if there is anyway to run two programs using named pipe i.e. fifo, by executing only one program. For example, solution mentioned here Sending strings between two pipes can it be ran using one terminal only? Is there anyway to call writer.c from reader.c and run the whole program just by running reader.c

Is execvp something I should be looking for?

EDIT: my reader.c looks like this

mkfifo("./q1", 0777);
pid_t pid = fork();
char *args[] = {"./writer.py", NULL};

if (pid < 0)
{
perror("unable to fork\n");
}
else if (fork() == 0) {
execv(args[0], args);
}
else if (fork() > 0) {
fp = fopen("./q2", "w");
for (i=0; i<10; i++)
fprintf(fp, "bb\n");
fclose(fp);
//remove("./q2");

pp = fopen("./q1", "r");
for (i=0; i<10; i++) {
fscanf(pp, "%s", str);
printf("read from the python program: %s\n", str);
}
fclose(pp);
}


My program now runs python and sends data successfully but it prints everything twice.

This is my python program

import os, sys

filename = "./q2"
pipe = open(filename, "r")
for i in range(10):
line = pipe.readline() [:-1]
print "read from the C program:", line
os.remove(filename)

filename = "./q1"
pipe = os.open(filename, os.O_WRONLY)
for i in range(10):
os.write(pipe, "aa\n")
os.close(pipe)


This is what my program prints when I run reader.c. Now it sometimes even print 'bb' 20 times instead of 10.

read from the C program: bb
read from the C program: bb
read from the C program: bb
read from the C program: bb
read from the C program: bb
read from the C program: bb
read from the C program: bb
read from the C program: bb
read from the C program: bb
read from the C program: bb
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
read from the python program: aa
Traceback (most recent call last):
File "./writer.py", line 6, in <module>
pipe = open(filename, "r")
IOError: [Errno 2] No such file or directory: './q2'

Answer

Use the popen() function to run writer.py from inside your reader program:

https://linux.die.net/man/3/popen

The popen function returns a FILE * which you can then use with any C buffered I/O function. Eg:

#include <stdio.h>
#include <errno.h>

int main(int argc, char **argv) {

    FILE *fp;
    if((fp = popen("/path/to/writer.py", "r")) == NULL) {
        // handle error in some way
        perror("popen");
        exit(1);
    }

    size_t numbytes;
    char buffer[255];

    // Here we read the output from the writer.py and rewrite it to 
    // stdout.  The result should look the same as if you ran writer.py
    // by itself.. not very useful.  But you would replace this with code
    // that does something useful with the data from writer.py

    while((numbytes = fread(buffer, 1, sizeof(buffer), fp)) > 0) {
        fwrite(buffer, 1, numbytes, stdout);
        // should check for error here
    }

    pclose(fp);
    exit(0);
}

PS: I did not compile or run this program, it is just an example to give you the idea... But it should work. Also.. I notice you say writer.c in one place and writer.py in another. It does not matter what language writer is written in. As long as the program pathname you pass to popen() results in output being written to stdout, it will work.

Comments