Hey,
Im a complete noob in UNIX and this problem is killing me.
Im trying to write the stdin (which i receive from a pipe) to a file, but as always C crashes without no explanation. Here is what i have so far:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void) {
pid_t childpid;
int fd[2];
int file;
mode_t fd_mode=S_IRWXU;
if ((pipe(fd) == -1) || ((childpid = fork()) == -1)) {
perror("Failed to setup pipeline");
return 1;
}
if(childpid>0) {
// send output to the pipe
printf("I am parent\n");
if (dup2(fd[1], STDOUT_FILENO) == -1)
perror("Failed to redirect stdout of ls");
else if ((close(fd[0]) == -1) || (close(fd[1]) == -1))
perror("Failed to close extra pipe descriptors on ls");
else {
execl("input",NULL); // input is an executable which produces
// 2 lines of text
perror("Failed to exec output file");
}
return 1;
}
// receive input from the pipe
printf("I am child\n");
if (dup2(fd[0], STDIN_FILENO) == -1)
perror("Failed to redirect stdin of writing to file");
else if ((close(fd[0]) == -1) || (close(fd[1]) == -1))
perror("Failed to close extra pipe file descriptors");
else {
if((file=open("file1.txt",O_WRONLY | O_CREAT,fd_mode))==-1)
perror("Error opening the file");
char *buffer=(char *)malloc(200);
fgets(buffer,100,STDIN_FILENO); // this should in theory write 100
// characters to the buffer from stdin, but it kills the program
write(file,buffer,100);
perror("Failed to write to the pipe");
}
return 1;
}
What exactly are you trying to do? Looks like you want to use pipes to communicate between the parent and child process. Standard output (stdout) of the parent process (ls) goes to the pipe which becomes the standard input (stdin) of the child process (sort). stdout of the child process...sort in this case...goes to a file.
ls | sort > file.out
Or are you sending the stdout of the parent process to a file which then becomes the stdin of the child process. Or if it's neither of the above. Be specific as to the one that best fits your needs.
Changes to the original source code are highlighted in red.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void) {
pid_t childpid;
int fd[2];
int file;
mode_t fd_mode=S_IRWXU;
if ((pipe(fd) == -1) || ((childpid = fork()) == -1)) {
perror("Failed to setup pipeline");
return 1;
}
if(childpid>0) {
/* send output to the pipe */
printf("I am parent\n");
if (dup2(fd[1], STDOUT_FILENO) == -1) {
perror("Failed to redirect stdout of ls");
return 1;
}
else if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) {
perror("Failed to close extra pipe descriptors on ls");
return 1;
} else
if (execl("/bin/ls", "ls", "-lrt", (char *) 0) < 0) {
perror("Failed to exec output file");
return 1;
}
}
/* receive input from the pipe */
printf("I am child\n");
if (dup2(fd[0], STDIN_FILENO) == -1) {
perror("Failed to redirect stdin of writing to file");
return 1;
}
else if ((close(fd[0]) == -1) || (close(fd[1]) == -1)) {
perror("Failed to close extra pipe file descriptors");
return 1;
} else {
if ((file=open("file1.txt",O_WRONLY | O_CREAT,fd_mode))==-1) {
perror("Error opening the file");
return 1;
}
char *buffer=(char *)malloc(200);
/*
* use read() instead of fgets() as read() takes an int for the file
* descriptor while fgets() takes a pointer to a stream of type FILE.
* Replacing fgets() with read() doesn't crash the program anymore.
*/
read(STDIN_FILENO, buffer, 100);
if (write(file, buffer, 100) < 0) {
perror("Failed to write to the pipe");
return 1;
}
}
return 0;
}