I need to write a program that create pipe send filename from command line to child process. In child read that file and send it back using pipe. Parent process should print the file. if error occur in child process error must be send to parent process.
here is my code, it print some junk along file file (and also it disable scrolling in terminal emulator when I run it).
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void main(int argc, char *argv[]) {
int pipefd[2];
char buff[100];
int childpid;
int size;
FILE *file;
if (argc != 2) {
printf("usage:\n%s <filename>\n", argv[0]);
exit(1);
}
if (pipe(pipefd) < 0) {
perror("can't open pipe\n");
}
if ((childpid = fork()) == 0) {
sleep(1);
size = read(pipefd[0], buff, sizeof(buff));
file = fopen(buff, "r");
if (file == NULL) {
write(pipefd[1], "Can't open file", 15);
exit(1);
}
while (!feof(file)) {
if (fgets(buff, sizeof(buff), file) == NULL) {
write(pipefd[1], "Error reading file", 18);
} else {
write(pipefd[1], buff, sizeof(buff));
}
}
} else if (childpid > 0) {
size = strlen(argv[1]);
if (write(pipefd[1], argv[1], size) != size) {
perror("Error writing to pipe\n");
}
wait(NULL);
while ((size = read(pipefd[0], buff, sizeof(buff))) > 0) {
write(1, buff, size);
}
}
exit(0);
}
Your program works as intended after quite a few changes. Lets list out what all changes are required and why-
I) Both in the child and parent, close the respective pipes as soon as you are done with them. From man page of
read(3)
,So do something like this in your code everywhere where the job pipes is over,
You hadn't closed the write end of of the pipe in the child and your parent was blocking in the
read
II) You are using something like
while(fgets(...))
in a loop to read data from file. This will bomb when there are newlines in the file andfgets
returns multiple times, overwriting thebuffer
everytime during the processI always use simple
fgetc
andfeof
combination to read from file. So, change your file reading mechanism to something likeIII) While writing the file data from the child, you should use
strlen
(as we have already made sure buffer is null terminated, see above ) and notsizeof
as the buffer may not be full at all and you will end up writing junk. So, changeto
IV) Follow a safe
exit
from the child and parent after their job is done. Something likeand
PS: I've changed the file reading logic, so your compiler error is gone now and do follow the advice given by n.m.
This code does not compile:
You can't have an
else
clause there.You cannot write
sizeof(buf)
meaningful bytes iffgets
returned less than that. The rest will be filled with junk.Moreover, mixing string-oriented
fgets
with binaryread/write
is a bad style. Useread
orfread
to read the file. They return number of bytes read, use this number as an argument towrite
.