Transfer int using pipe between N number of process - c

I want to transfer data between multiple child process using pipe() like that :
And that need to work for any number of child process. I want to see child process print the read pipe value and increment this value by one and transfers this values to the next process.
But for now, I have 3 problems :
My child function was call multiple time with the same parameter
Because of that, the file descriptor change and I don't want that.
Every process except the first one get Bad file descriptor with errno
Everything seams to work for the first one because it receives the value from father and have no error when write to the writePipe.
When I run my program, this is my console output
id:0 pipeRead:5 PipeWrite:8
id:0 res:4 value:500
id:1 pipeRead:9 PipeWrite:12
id:2 pipeRead:13 PipeWrite:16
id:1 pipeRead:3 PipeWrite:6
id:2 pipeRead:7 PipeWrite:10
id:1 res:-1 value:0
id:2 pipeRead:3 PipeWrite:6
id:2 res:-1 value:0
Read Error: Bad file descriptor
Read Error: Bad file descriptor
So, here my code attempt
int execChild(int appID, int pipeRead[2], int pipeWrite[2]){
//Before start process, I close read/write that not used here
//Close write of read pipe
close(pipeRead[1]);
//Close read of write pipe
close(pipeWrite[0]);
printf("id:%d pipeRead:%d PipeWrite:%d\n",appID,pipeRead[0],pipeWrite[1]);
int buff=0;
long int res;
res = read(pipeRead[0],&buff,sizeof(int));
if (res==-1) perror("Read Error");
//Close read pipe after used
close(pipeRead[0]);
printf("id:%d res:%ld value:%d\n",appID,res,buff);
//Increment value
buff += 1;
res = write(pipeWrite[1],&buff,sizeof(int));
if(res==-1)perror("Write Error");
//Close write pipe after used
close(pipeWrite[1]);
return 0;
}
int main(int argc, char *argv[]) {
int nbFis = 3;
//Init array of pipeArray with malloc
int* pipeArr[nbFis];
for (int i = 0; i < nbFis; i++)
pipeArr[i] = (int*)malloc(2 * sizeof(int));
for (int i = 0; i < nbFis; i++) // Generate n child
{
//Here we open every inter child pipe
//If the process is 0 we need to open the last pipe of the array
//Else we open the last pipe
if(i==0){
pipe(pipeArr[nbFis-1]);//Open Read Pipe
//To test I inject an int value here to child 0
int value = 500;
write(pipeArr[nbFis-1][1],&value,sizeof(int));//Write value in the pipe
}else{
pipe(pipeArr[i-1]);//Open Read Pipe
}
pipe(pipeArr[i]);//Open Write Pipe
if (fork() == 0) {
//If it's the first child we send the last pipe in the array as read pipe and current pipe as write pipe
//Else we send the previous pipe in the list as read pipe and current pipe as write pipe
if(i==0){
execChild(i,pipeArr[nbFis-1],pipeArr[i]);
}else{
execChild(i,pipeArr[i-1],pipeArr[i]);
}
}
}
//Wait for the end of process and free memory
for (int i = 0; i < nbFis; i++) {
free(pipeArr[i]);
wait(NULL);
}
return 0;
}

Related

Piping between several processes in C

I'm writing a shell in C and am trying to implement multiple pipes. I've done this by creating a two dimensional array with pipes and using a separate pipe everytime. All commands in between pipes are separated by a parsing function and put into a struct. Every command line in-between pipes gets it's own process. And for all commands in the middle I'm trying to read from the previous process and write to the next one. Somewhere here the problem starts. It works fine for one pipe, however when I trying more than one pipe I don't get any output and the program gets stuck. In GDB I get a failed message from the execvp after forking the second process. What can this be due to?
int create_pipe(int* fd)
{
int pipe_id = pipe(fd);
if (pipe_id == -1)
{
return -1;
}
return 0;
}
void write_pipe(int* fd)
{
close(fd[READ]);
if ((dup2(fd[WRITE], STDOUT_FILENO)) < -1)
{
fork_error();
}
close(fd[WRITE]);
}
void read_pipe(int *fd)
{
close(fd[WRITE]);
if (dup2(fd[READ], STDIN_FILENO) < 0)
{
fork_error();
}
close(fd[READ]);
}
void need_to_pipe (int i, int (*fd)[2])
{
if (commands[i].pos == first)
{
write_pipe(fd[i * 2]);
}
else if (commands[i].pos == last)
{
read_pipe(fd[(i-1) *2]);
}
else //if (commands[i].pos == middle)
{
dup2(fd[(i-1)*2][READ], STDIN_FILENO);
close(fd[(i-1)*2][READ]);
close(fd[(i-1)*2][WRITE]);
//close(fd[(i)*2][READ]);
//close(fd[(i)*2][WRITE]);
close(fd[(i)*2][READ]);
dup2(fd[i*2][WRITE], STDOUT_FILENO);
close(fd[(i)*2][WRITE]);
}
}
/**
* Fork a proccess for command with index i in the command pipeline. If needed,
* create a new pipe and update the in and out members for the command..
*/
void fork_cmd(int i, int (*fd)[2]) {
pid_t pid;
switch (pid = fork()) {
case -1:
fork_error();
case 0:
// Child process after a successful fork().
if (!(commands[i].pos == single))
{
need_to_pipe(i, fd);
}
// Execute the command in the contex of the child process.
if (execvp(commands[i].argv[0], commands[i].argv)<0)
{
fprintf(stderr, "command not found: %s\n",
commands[i].argv[0]);
exit(EXIT_FAILURE);
}
default:
// Parent process after a successful fork().
break;
}
}
/**
* Fork one child process for each command in the command pipeline.
*/
void fork_cmds(int n, int (*fd)[2])
{
for (int i = 0; i < n; i++)
{
fork_cmd(i, fd);
}
}
void wait_once ()
{
wait(NULL);
}
/**
* Make the parents wait for all the child processes.
*/
void wait_for_all_cmds(int n)
{
for (int i = 0; i < n; i++)
{
wait_once();
//wait for number of child processes.
}
}
int main() {
int n; // Number of commands in a command pipeline.
size_t size = 128; // Max size of a command line string.
char line[size];
while(true) {
// Buffer for a command line string.
printf(" >>> ");
get_line(line, size);
n = parse_cmds(line, commands);
int fd[(n-1)][2];
for(int i =0;i<n-1;i++)
{
int pipe_id = pipe(fd[i*2]);
if (pipe_id == -1)
{
return -1;
}
}
fork_cmds(n, fd);
for(int i =0;i<n-1;i++)
{
int *fdclose= fd[i*2];
close (fdclose[READ]);
close (fdclose[WRITE]);
}
wait_for_all_cmds(n);
}
exit(EXIT_SUCCESS);
}
You [probably] have too many processes keeping pipe ends open (that do not belong to the given child) because your loop opens all pipes before any forking.
This places an undue burden on each child because it has to close many pipe ends to prevent it from holding open a pipe end, preventing other children from seeing an EOF on their input pipes.
To see this, for debug purposes in your present code, the child could do (just before the exec* call) (e.g.):
fprintf(stderr,"child: %d\n",getpid());
fflush(stderr);
system("ls -l /proc/self/fd 1>&2");
Each child should only have three open streams on stdin, stdout, and stderr (e.g. 0, 1, 2).
I think you'd find that there are many extraneous/detrimental streams open on the various children.
You only need two pipe arrays (e.g.): int pipeinp[2]; int pipeout[2]; Initially, pipeinp is all -1.
Roughly ...
Parent should do a single pipe call at the top of fork_cmd [before the fork] to pipeout.
The child dups (and closes) the read end of pipeinp [if not -1] to stdin.
Child dups/closes the write end of pipeout to stdout.
It closes the read end of pipeout.
After that, the parent should copy pipeout to pipeinp and close the write end of pipeinp
This should be repeated for all pipe stages.
No pipe to pipeout should be done for the last command. And, the [last] child should not change stdout.
For a working example, see my answer: fd leak, custom Shell

Own shell -> Hang on after using pipe & dup2 on child [duplicate]

I'm working on a C shell and am having trouble with getting an arbitrary amount of pipes to work. When I run the shell, it hangs on any piping. For some reason, when I do ls -la | sort, it hangs on the sort until I enter stuff and hit Ctrl+D. I know it has something to do with a pipe not closing, but the print statements show that pipes 3,4,5 all get closed in both the parent and child. I've been at this for a few hours and don't know why this doesn't work. Any help would be much appreciated.
Original Code:
char *current_command;
current_command = strtok_r(cmdline_copy, "|", &cmdline_copy);
char *commands[100][MAX_ARGS]; //Max 100 piped commands with each having MAX_ARGS arguments
int i = 0;
while (current_command != NULL) { //Go through each command and add it to the array
char *copy = malloc(strlen(current_command)*sizeof(char)); //Copy of curretn command
strcpy(copy, current_command);
char *args_t[MAX_ARGS];
int nargs_t = get_args(copy, args_t);
memcpy(commands[i], args_t, sizeof(args_t)*nargs_t); //Copy the command and it's arguments to the 2d array
i++;
current_command = strtok_r(NULL, "|\n", &cmdline_copy); //Use reentrant version of strtok to prevent fighting with get_args function
}
int fd[2*(i-1)]; //Set up the pipes i.e fd[0,1] is first pipe, fd[1,2] second pipe, etc.
for (int j = 0; j < i*2; j+=2) {
pipe(fd+j);
}
//Here is where we do the commands
for (int j = 0; j < i; j++) {
pid = fork(); //Fork
if (pid == 0) { //Child process
if (j == 0) { //First process
printf("Child Closed %d\n", fd[0]);
close(fd[0]);
dup2(fd[1], fileno(stdout));
}
else if (j == i -1) { //Last process
dup2(fd[j], fileno(stdin));
printf("Child closed %d\n", fd[j]);
printf("Child closed %d\n", fd[j+1]);
close(fd[j+1]);
close(fd[j]);
}
else { //Middle processes
dup2(fd[j], fileno(stdin));
dup2(fd[j+1], fileno(stdout));
printf("Child closed %d\n", fd[j]);
close(fd[j]);
}
execvp(commands[j][0], commands[j]);
}
else if (pid > 0) { //Parent
printf("Parent closed %d\n", fd[j]);
close(fd[j]);
printf("Parent closed %d\n", fd[j+1]);
close(fd[j+1]);
waitpid(pid, NULL, 0); //Wait for the process
}
else {
perror("Error with fork");
exit(1);
}
}
Final Code:
char *current_command;
current_command = strtok_r(cmdline_copy, "|", &cmdline_copy);
char *commands[100][MAX_ARGS]; //Max 100 piped commands with each having MAX_ARGS arguments
int command_count = 0;
while (current_command != NULL) { //Go through each command and add it to the array
char *copy = malloc(strlen(current_command)*sizeof(char)); //Copy of curretn command because get_args uses strtok
strcpy(copy, current_command);
char *args_t[MAX_ARGS];
int nargs_t = get_args(copy, args_t);
memcpy(commands[command_count], args_t, sizeof(args_t)*nargs_t); //Copy the command and it's arguments to the 2d array
command_count++;
current_command = strtok_r(NULL, "|\n", &cmdline_copy); //Use reentrant version of strtok to prevent fighting with get_args function
}
int fd[command_count*2-1];
pid_t pids[command_count];
for (int j = 0; j < command_count*2; j+=2) { //Open up a pair of pipes for every command
pipe(fd+j);
}
for (int j = 0; j < command_count; j++) {
pids[j] = fork();
if (pids[j] == 0) { //Child process
if (j == 0) { //Duplicate only stdout pipe for first pipe
dup2(fd[1], fileno(stdout));
}
else if (j == (command_count-1)) { //Duplicate only stdin for last pipe
up2(fd[2*(command_count-1)-2], fileno(stdin));
}
else { //Duplicate both stdin and stdout
dup2(fd[2*(j-1)], fileno(stdin));
dup2(fd[2*j+1], fileno(stdout));
}
for (int k = 0; k < j*2; k++) { //Close all fds
close(fd[k]);
}
execvp(commands[j][0], commands[j]); //Exec the command
}
else if (pids[j] < 0) {
perror("Error forking");
}
}
for (int k = 0; k < command_count*2; k++) { //Parent closes all fds
close(fd[k]);
}
waitpid(pids[command_count-1], NULL, 0); //Wait for only the last process;
You aren't closing enough file descriptors in the children (or, in this case, in the parent).
Rule of thumb: If you
dup2()
one end of a pipe to standard input or standard output, close both of the
original file descriptors returned by
pipe()
as soon as possible.
In particular, you should close them before using any of the
exec*()
family of functions.
The rule also applies if you duplicate the descriptors with either
dup()
or
fcntl()
with F_DUPFD
In your code, you create all the pipes before you fork any children; therefore, each child needs to close all the pipe file descriptors after duplicating the one or two that it is going to use for input or output.
The parent process must also close all the pipe descriptors.
Also, the parent should not wait for children to complete until after launching all the children. In general, children will block with full pipe buffers if you make them run sequentially. You also defeat the benefits of parallelism. Note, however, that the parent must keep the pipes open until it has launched all the children — it must not close them after it launches each child.
For your code, the outline operation should be:
Create N pipes
For each of N (or N+1) children:
Fork.
Child duplicates standard input and output pipes
Child closes all of the pipe file descriptors
Child executes process (and reports error and exits if it fails)
Parent records child PID.
Parent goes on to next iteration; no waiting, no closing.
Parent now closes N pipes.
Parent now waits for the appropriate children to die.
There are other ways of organizing this, of greater or lesser complexity. The alternatives typically avoid opening all the pipes up front, which reduces the number of pipes to be closed.
'Appropriate children' means there are various ways of deciding when a pipeline (sequence of commands connected by pipes) is 'done'.
One option is to wait for the last command in the sequence to exit. This has advantages — and is the traditional way to do it. Another advantage is that the parent process can launch the last child; the child can launch its predecessor in the pipeline, back to the first process in the pipeline. In this scenario, the parent never creates a pipe, so it doesn't have to close any pipes. It also only has one child to wait for; the other processes in the pipeline are descendents of the one child.
Another option is to wait for all the processes to die(1). This is more or less what Bash does. This allows Bash to know the exit status of each element of the pipeline; the alternative does not permit that — which is relevant to set -o pipefail and the PIPEFAIL array.
Can you help me understand why the dup2 statement for the middle pipes is dup2(fd[(2*j)+1], fileno(stdout)) and dup2(fd[2*(j-1)], fileno(stdin))? I got it off Google and it works, but I'm unsure why.
fileno(stdout) is 1.
fileno(stdin) is 0.
The read end of a pipe is file descriptor 0 (analogous to standard input).
The write end of a pipe is file descriptor 1 (analogous to standard output).
You have an array int fd[2*N]; for some value of N > 1, and you get a pair of file descriptors for each pipe.
For an integer k, fd[k*2+0] is the read descriptor of a pipe, and fd[k*2+1] is the read descriptor.
When j is neither 0 nor (N-1), you want it to read from the previous pipe and to write to its pipe:
fd[(2*j)+1] is the write descriptor of pipe j — which gets connected to stdout.
fd[2*(j-1)] is the read descriptor of pipe j-1 — which gets connected to stdin.
So, the two dup2() calls connect the the correct pipe file descriptors to standard input and standard output of process j in the pipeline.
(1)
There can be obscure scenarios where this leaves the parent hung indefinitely. I emphasize obscure; it requires something like a process that hangs around as a daemon without forking.

Someone can help me with my code in c?

Iam trying to create a code with 1 parent and 2 childrens. The method recive 3 parameters:
original_file word1 word2
The parent read a file line by line:
If the line is pair, send the line to method proccess_pair and the word1.
If the line contains the word1, save the lines in the file_1.txt
If the line is odd, send the line to method proccess_odd and the word2.
If the line contains the word1, save the lines in the file_2.txt
Im beginner in c, and i trying with this:
int p_h1[2] // pipe from parent to child1
int p_h2[2];// pipe from parent to child2
int main(int argc, char **argv){
pid_t pdi1, pdi2;
FILE *fd; // for original file
FILE *p_h1f, *p_h2f; //file create for child1 and child2 respectively
char buffer[1024];//buffer
if (pid1<0){
fprintf(stderr,"Error fork \n %s \n",strerror(errno));
exit(EXIT_FAILURE);
}
else if (pid1==0){//Im the child1
//proccess for child 1
proccess_pair(arg[2]);
exit(EXIT_SUCCESS);
}
pid2 = fork();
if (pid2<0){
fprintf(stderr,"Error fork \n %s \n",strerror(errno));
exit(EXIT_FAILURE);
}
else if (pid2==0){//Im the child2
//proccess for child 2
proccess_odd(arg[2]);
exit(EXIT_SUCCESS);
}
//Parent dont read from pipe
close(p_h1[0]);
close(p_h2[0]);
fd = fopen(argv[1],"r"); //I openthe file for read it;
p_h1f = fdopen(p_h1[1],"w")
p_h2f = fdopen(p_h2[1],"w")
int i = 1;
while(fgets(buffer,1024,fd) != NULL){
if (i % 2 ==0){ //check if the lines is pairs
fputs(buffer,p_h1f);
fflush(p_h1f);
}else{
fputs(buffer,p_h2f);
fflush(p_h2f);
}
i++;
}
close(p_h1[1]);
close(p_h2[1]);
fclose(fd);
wait(NULL);
wait(NULL);
}
Both methods(for chil1 and chil2) will be the same(but closing the correct sides of pipes), for this reason i only implement one of them:
void proccess_pair(char *word1){
FILE *fd;
fd = fopen("file_1.txt","w");
//closing the not used
close(p_h1[1]);
close(p_h2[1]);
close(p_h2[0]);
int nsto = dup(1)//duplicate the stdout
dup2(fd,1);//changing stdout->file_1.txt
execlp("grep","grep",word1,NULL);//execution of grep
exit(EXIT_SUCCESS);
}
Im learning and i know that i have many many error, for this reason i need help.
Regards
How i can create many pipes in an array in c?
On a POSIX-conformant system, you can do that by calling pipe() many times on elements of a 2D array of int, as you presented.
¿I can use two different pipes(parent-child1,parent-child2)? I can use an array of pipes?
A pipe itself lives only in the kernel. There is no userspace data
structure representing a pipe, so you cannot have an array of pipes.
The file descriptors for the pipe ends, however, are just ints. The pipe() function takes as its argument a pointer to the first element of an array of at least two int, and (on success) it writes the appropriate file descriptors into the array.
From a C perspective, there is nothing special about the array in which the pipe ends are to be returned. In particular, it can be an element of a multi-dimensional array if you so desire. Or it can be a local variable. Or it can be a member of a struct or a union. Or it can be a large enough block of dynamically-allocated space. It's not special.
Something like this should work:
int new_process(char *word){ // return the writing part of a pipe to a newly created child
int p[2];
pipe( p ); // get a new pipe
if (fork()==0) { // create a new child
dup2(p[0],0); // child's in is pipe's entry
close(p[1]); // close writing part
execlp("grep","grep",word,NULL); // exec
}
close(p[0]); // parent don't need the reading part
return p[1]; // send back the writing part to caller
}
int main(int argc, char **argv) {
int f1 = new_process(argv[1]); // get the pipe to first child
int f2 = new_process(argv[1]); // ...second...
char buffer[1024];//buffer
FILE *fd = fopen(argv[1],"r"); // open the file for reading;
while(fgets(buffer,1024,fd) != NULL) { // read aline
if (i % 2 ==0) { //check if the line no is pair
fputs(buffer,f1); // send it to first child
fflush(f1);
} else{
fputs(buffer,f2); // send it to second child
fflush(f2);
}
i++;
}
close(f1);
close(f2);
fclose(fd);
wait(NULL);
wait(NULL);
}
Don't forget to add necessary controls on failures.

How to tell which pipe was written to first

So I have some code that I am working on where I'm going to fork N children to do something with N different files and gather some info. The parent is only reading, and the children are only writing. If one child finishes before the other, I'd like to start processing that data in the parent, while the others still run.
Here I am making N pipes
int pipefds[nFiles*2];
int k;
for(k = 0; k < nFiles; k++)
{
if(pipe(pipefds[k*2]))
{
/* pipe failed */
}
}
I then fork N processes, and want them to do something with the file and send it to the parent
int i;
for(i = 0; i < nFiles; i++)
{
pid = fork();
if(pid < 0)
{
/* error */
}
else if(pid == 0)
{
/*child */
close(pipefds[i*2]); //I think I want to close the Read End of each child's pipe
getData(file[i]); // do something with the file this process is handling
write(fd[i*2 +1], someData, sizeof(someData); // write something to the write end of the child's pipe
exit(0);
}
else
{
/*parent*/
if(i = nFiles -1) //do I have to make this condition so that I start once all processes have been started??
{
int j;
for(j = 0; j < nFiles; j++)
{
close(pipefds[j*2+1]); //close all the parents write ends
}
/*Here I want to pick the pipe that finished writing first and do something with it */
}
}
Do I have to wait for the last iteration of the for loop to start doing parent stuff (cause I want all the processes to start before I do anything)? Also How to I find the pipe in pipefds which is has finished writing so I can start handling it while the others run? Thanks!
Probably the simplest solution is to create all the children first. Then run a separate loop around poll or select. When you get a read hit on one of the pipe ends, read the data into a buffer. If that read gets an indication that the other end of the pipe has closed, you can begin processing the data from that child. (Don't forget to remove that pipe from the set you are polling or selecting on.) When all children's pipes are closed, you're done.

Interprocess Communication in C, one character at a time

First off, this IS homework, I am not asking for an answer, however I am confused about something.
I have a homework assignment for a programming class, and I am a little confused about how to write the code the specific way that the instructor is asking.
The program first creates a child process, and then proceeds to send command line arguments from the parent process, through a pipe, ONE CHARACTER at a time to the child process, and then read them into the child process ONE CHARACTER at a time, incrementing the character count in the child process each time a character is read in.
I think I accomplished sending the data through the pipe one character at a time, but I have no idea how to "go" to the child process every time a character is sent, read it, increment the number of characters, and then go back to the parent process and repeat.
Here is my code, It works and gives accurate answers, but any tips on how to accomplish what my instructor is asking would be appreciated, thank you!!
// Characters from command line arguments are sent to child process
// from parent process one at a time through pipe.
//
// Child process counts number of characters sent through pipe.
//
// Child process returns number of characters counted to parent process.
//
// Parent process prints number of characters counted by child process.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char **argv)
{
// set up pipe
int pA[2];
char buff[50];
pipe(pA);
// call fork()
pid_t childId = fork();
if (childId == 0) {
// -- running in child process --
int nChars = 0;
// close the output side of pipe
close(pA[1]);
// Receive characters from parent process via pipe
// one at a time, and count them.
nChars = read(pA[0], buff, sizeof(buff)); //this line of code is what i need to change to be reading characters in one at a time
// Return number of characters counted to parent process.
return nChars;
}
else {
// -- running in parent process --
int nChars = 0;
int size = 0;
printf("CS201 - Assignment 3 - Timothy Jensen\n");
// close the input side of the pipe
close(pA[0]);
// Send characters from command line arguments starting with
// argv[1] one at a time through pipe to child process.
for (int i = 1; i < argc; i++)
{
size = strlen(argv[i]);
for (int z = 0; z < size; z++)
{
write(pA[1], &argv[i][z], 1);
}
}
// Wait for child process to return. Reap child process.
// Receive number of characters counted via the value
// returned when the child process is reaped.
wait(&nChars);
printf("child counted %d chars\n", nChars/256);
return 0;
}
}
You need to make the following changes:
Make the last argument 1 in the call to read.
read(pA[0], buff, 1);
Put the above call in a while loop and increment nChar for every successful attempt at read.
while ( read(pA[0], buff, 1) == 1 )
{
++nChars;
}
Close the file descriptor from the parent process once you are done writing to it.
Here's a working version of main.
int main(int argc, char **argv)
{
// set up pipe
int pA[2];
char buff[50];
pipe(pA);
// call fork()
pid_t childId = fork();
if (childId == 0) {
// -- running in child process --
int nChars = 0;
// close the output side of pipe
close(pA[1]);
// Receive characters from parent process via pipe
// one at a time, and count them.
while ( read(pA[0], buff, 1) == 1 )
{
++nChars;
}
return nChars;
}
else {
// -- running in parent process --
int nChars = 0;
int size = 0;
printf("CS201 - Assignment 3 - Timothy Jensen\n");
// close the input side of the pipe
close(pA[0]);
// Send characters from command line arguments starting with
// argv[1] one at a time through pipe to child process.
for (int i = 1; i < argc; i++)
{
size = strlen(argv[i]);
for (int z = 0; z < size; z++)
{
write(pA[1], &argv[i][z], 1);
}
}
close(pA[1]);
// Wait for child process to return. Reap child process.
// Receive number of characters counted via the value
// returned when the child process is reaped.
wait(&nChars);
printf("child counted %d chars\n", nChars/256);
return 0;
}
}
It seems a little silly, but you could change:
nChars = read(pA[0], buff, sizeof(buff));
to:
char ch;
nChars = read(pA[0], &ch, 1);
Of course, you would put the above into a loop to assemble a string 'one character at a time' back into buff.

Resources