FRI-OS
example/posix/pipes-interprocess.c

Shows interprocess communication through an anonymous pipe

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
// the function executed in the parent process
int parent(int input, int output)
{
char buffer[1024];
int result;
// read from standard input into a buffer
while((result = read(0, buffer, 1024)) > 0)
{
// send the buffer through the pipe to the child
if(write(output, buffer, result) != result)
{
perror("Error writing to pipe");
return 5;
}
// read the transformed input from the child into buffer
if(read(input, buffer, result) != result)
{
perror("Error reading from pipe");
return 4;
}
// write the buffer to standard output
if(write(1, buffer, result) != result)
{
perror("Error writing to standard output");
return 7;
}
}
// if the loop above did not end with EOF
if(result != 0)
{
perror("Error reading from standard input");
return 6;
}
return 0;
}
// the function executed in the child process
int child(int input, int output)
{
char buffer[1024];
int result;
// read input sent from the parent throught the pipe
while((result = read(input, buffer, 1024)) > 0)
{
// convert all read characters to uppercase
for(int i=0; i!=result; ++i)
buffer[i] = toupper(buffer[i]);
// send the updated buffer back to the parent
if(write(output, buffer, result) != result)
{
perror("Error writing to pipe");
return 5;
}
}
// if the loop above did not end with EOF
if(result != 0)
{
perror("Error reading from pipe");
return 4;
}
return 0;
}
// closes the unused ends of the pipes and calls the parents function
int call_parent(int parent_to_child[2], int child_to_parent[2])
{
close(child_to_parent[1]);
close(parent_to_child[0]);
return parent(child_to_parent[0], parent_to_child[1]);
}
// closes the unused ends of the pipes and calls the childs function
int call_child(int parent_to_child[2], int child_to_parent[2])
{
close(parent_to_child[1]);
close(child_to_parent[0]);
return child(parent_to_child[0], child_to_parent[1]);
}
int main(void)
{
puts("Write some ASCII text");
// create pipe from the parent process to the child process
int parent_to_child[2];
if(pipe(parent_to_child) == -1)
{
perror("Error creating pipe from parent to child");
return 1;
}
// create pipe from the child process to the parent process
int child_to_parent[2];
if(pipe(child_to_parent) == -1)
{
perror("Error creating pipe from child to parent");
return 2;
}
// try to fork
switch(fork())
{
// handle errors and quit
case -1: perror("Fork failed"); return 3;
// we are in the child process
case 0: return call_child(parent_to_child, child_to_parent);
// we are in the parent process
default: return call_parent(parent_to_child, child_to_parent);
}
return 0;
}