Sending image through pipe to child process in C - c

What my program needs to do is create child process, then transform it into dipslay program and send a PNG image through a pipe to it. I think i'm close, but i don't know how to send an image through pipe.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
int main(void)
{
int fd[2];
pid_t childpid;
char string[] = "";
char readbuffer[10000];
char buf[10000];
FILE *fptr;
pipe(fd);
if((childpid = fork()) == -1)
{
perror("fork");
exit(1);
}
if(childpid == 0)
{
//Child
close(fd[1]);
dup(fd[0]);
execl("/usr/bin/display","display", (char *)0);
read(fd[0], readbuffer, sizeof(readbuffer));
exit(0);
}
else
{
//Parent
close(fd[0]);
dup2(fd[1],1);
printf("Type name of the file:\n");
scanf("%s",string);
fptr = fopen(string, "r");
while ( fgets(buf, sizeof(buf), fptr) != NULL) {
write(fd[1], buf, strlen(buf));
}
fclose(fptr);
}
return(0);

Firstly you need to close the file descriptor associated with standard input.
close(0);
then duplicate fd[0]. It should work. You don't need to duplicate fd[1] in parent process.
My program:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int pipe_fd[2];
int c;
FILE *file;
pipe(pipe_fd);
if(fork()==0)
{
//child
close(pipe_fd[1]);
close(0);
dup(pipe_fd[0]);
execl("/usr/bin/display","display", (char*)NULL);
read(pipe_fd[0], &c, 1);
exit(1);
}
// parent
close(pipe_fd[0]);
file=fopen("Lena2.pgm","r");
if(file==NULL)
printf("File error\n");
while(!feof(file))
{
c=getc(file);
write(pipe_fd[1], &c, 1);
}
}

Related

Restore stdin after a pipe

I made a pipe using stdin and stdout to communicate but I can't figure out how to restore stdin after closing it in my father process.
Here is an example :
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
void readPBM(char *output)
{
char tmp[1024];
int fd[2] = {0,0};
int pid;
//Open the pipe for inter-process communication
pipe(&fd[0]);
//Fork and test if we are child or parent process
pid = fork();
if(pid) //Parent process
{
wait(NULL); //Wait for child's end
close(fd[1]);//Close pipe's write stream
close(0);//Close stdin
dup(fd[0]);
close(fd[0]);
strcpy(output, "");// Init output at 0
while(fgets(tmp, 1024, stdin) != NULL) //Put remainings entry in output
{
strcat(output, tmp);
}
strcat(output, "It works\n");
}
else if(pid == 0) //Child process
{
close(fd[0]);//Close pipe's read stream
close(1);//Close stdout
dup(fd[1]);//Duplicate stdin
close(fd[1]);
printf("A random string ...\n");
exit(0);
}
else //Print error if fork failed
{
printf("Error creating a new process");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
int i, j;
char *str = NULL;
char c;
str = malloc(512 * sizeof(char*));
readPBM(str);
printf("%s", str);
c = getchar();
}
I tried to save stdin using : int stdin_copy = dup(0) then restoring it but my getchar is not working.
I also tried to use freopen("/dev/stdin", "a", stdin) but it still doesn't wait for an input
Using fdopen seems to work well so here is the fixed code :
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
void readPBM(char *output)
{
FILE* fp;
char tmp[1024];
int fd[2] = {0,0};
int pid;
//Open the pipe for inter-process communication
pipe(&fd[0]);
//Fork and test if we are child or parent process
pid = fork();
if(pid) //Parent process
{
wait(NULL); //Wait for child's end
close(fd[1]);//Close pipe's write stream
fp = fdopen(fd[0], "r");
strcpy(output, "");// Init output at 0
while(fgets(tmp, 1024, fp) != NULL) //Put remainings entry in output
{
strcat(output, tmp);
}
strcat(output, "It works\n");
fclose(fp);
}
else if(pid == 0) //Child process
{
close(fd[0]);//Close pipe's read stream
close(1);//Close stdout
dup(fd[1]);//Duplicate stdin
close(fd[1]);
printf("A random string ...\n");
exit(0);
}
else //Print error if fork failed
{
printf("Error creating a new process");
exit(EXIT_FAILURE);
}
}
int main(int argc, char *argv[])
{
int i, j;
char *str = NULL;
char c;
str = malloc(512 * sizeof(char*));
readPBM(str);
printf("%s", str);
c = getchar();
}

Linux: Using pipe to send the information in between the processes

The pipe is created with fd[] and fd1[]. I am writing with the pipes. Taking two pipes gave me error as i was referencing to STDIN_FILENO, so i deleted it. I just used the pipe to read and write. Now it is still not reading from the pipe. Pipe with file descriptor fd[] works. but the fd1[] does not.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv)
{
int fd[2];
pid_t childpid;
pipe(fd);
int fd2[2];
pipe(fd2);
int array[5] = {1,2,3,4,5};
int array2[5] = {11,12,13,14,15};
//fprintf(stderr,"size%ld",sizeof(int));
//char buffer[111];
int *subarr1;
int buffer_num;
int status;
if ((childpid = fork()) == 0) {
fprintf(stderr,"\nProcess:%d Parent:%d",getpid(),getppid());
//dup2(fd[1], STDOUT_FILENO);
close(fd[0]); //read end
write(fd[1],array,100);
close(fd[1]);
//execl("/bin/ls", "ls", "-l", NULL);
perror("The exec of ls failed\n");
if ((childpid = fork()) == 0)
{
fprintf(stderr,"\nProcess:%d Parent:%d",getpid(),getppid());
//dup2(fd2[1], STDOUT_FILENO);
close(fd2[0]); //read end
write(fd2[1],array2,sizeof(array2));
close(fd2[1]);
//execl("/bin/ls", "ls", "-l", NULL);
perror("The exec of ls failed\n");
}
else
{// parent
wait(NULL);
}
}
else {
wait(&status);
fprintf(stderr,"\nTHis is parent");
subarr1 = (int*)malloc(sizeof(int)*(5));
fprintf(stderr,"\nProcess:%d Parent:%d",getpid(),getppid());
//dup2(fd[0], STDIN_FILENO);
close(fd[1]);
int j;
for(j=0;j<5;j++)
{
read(fd[0],&buffer_num,sizeof(int));
subarr1[j] = buffer_num;
//printf("%s",buffer);
}
for(j=0;j<5;j++)
{
fprintf(stderr,"\n%d\n",subarr1[j]);
}
close(fd[0]);//read end
//dup2(fd2[0], STDIN_FILENO);
buffer_num = 0;
close(fd2[1]);
//read(fd2[0],&buffer_num,100);
for(j=0;j<5;j++)
{
read(fd2[0],&buffer_num,sizeof(int));
subarr1[j] = buffer_num;
//printf("%s",buffer);
}
for(j=0;j<5;j++)
{
fprintf(stderr,"\n%d\n",subarr1[j]);
}
//fprintf(stderr, "\nThis is second pipe%s", buffer);
close(fd2[0]);
/*//printf("\nAAAAAAAA%s\n",buffer);
dup2(fd2[0], STDIN_FILENO);
close(fd2[1]);
printf("\nAAAAAAAA%s\n",buffer);
read(fd2[0],buffer,100);
printf("%s",buffer);
close(fd2[0]);//read end
printf("\nAAAAAAAA%s\n",buffer);
*/
//execl("/usr/bin/sort", "sort", "-n", NULL);
perror("The exec of sort failed\n");
}
return 0;
}
This call:
read(fd2[0],&buffer_num,100);
tries to read 100 bytes into memory starting at the local (int) variable buffer, so overwrites whatever else is on the stack after it, smashing the stack and causing undefined behavior (probably crashing at some point).
You have similar problems with your write calls, writing 100 bytes from objects that are much smaller, but those likely only write garbage you then ignore, rather than causing a crash (though that is likewise undefined behavior).

Using pipe between diffrent programs how ?

Question asked again and code modified...
I need to create three programs named as program0 program1 and program2 in linux.
Program0:Creates a parent with two child processes and executes program 1 and program 2 with its childs waits them to finish and close.
Program1:Takes a file name from the user and writes text to the file.It finishes writing when CTNL+D pressed and creates a pipe.After that by using cat command it writes file to stdout and uses dup() to create pipe which has file in it.
Program2:It reads filename from the pipe with the help of dup() and then executes wc command.
So far I managed to create all programs and I have no compling errors.Program 0 executes both programs.Program1 is also working and sends file to the pipe but program2 cannot read it from the pipe is prints weird symbols..
When I try to read from the pipe within the program1 it works(see the deactivated code in program1) but same code is not working if I put it inside program2.
So what how can I make program2 to read from the pipe after that I will try to execute wc command in program2 but first I should be able to see that its taking file input from the stdout so how?
I know its kinda long but please help me guys...
Program 0
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#define MAX 999
int main()
{
pid_t pid1, pid2;
pid1 = fork();
if(pid1<0)
{
fprintf(stderr,"Fork basarisiz");
exit(-1);
}
else if (pid1 ==0)/*child prosesleri*/
{
printf("program1\n");
execlp("./program1","program1",NULL);
execlp("./program2","program2",NULL);
}
else /*parent procsesleri */
{
wait(NULL);
pid2 = fork();
if(pid2<0)
{
fprintf(stderr,"Fork basarisiz");
exit(-1);
}
else if (pid2 ==0)/*child prosesleri*/
{
printf("\n");
printf("Program 2\n");
printf("\n");
execlp("./program2","program2",NULL);
//printf("\n");
}
else
{
}
/////////////////////////////////////////////////////////////////////////
wait(NULL);
printf("\n");
printf("Parent:Two child processes have successfully been created\n");
printf("Parent:Two child processes have successfully been terminated\n");
printf("Parent:This process will now terminate\n");
printf("\n");
exit(0);
}
}
Program 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX 999
int main()
{
char c[10000];
char file[10000];
int words;
printf("Child1:A text file will be created\n");
printf("Child1:Enter the name of the file\n");
scanf("%123s",file);
strcat(file,".txt");
FILE * pf;
pf = fopen(file, "w" );
if (!pf)
fprintf( stderr, "I couldn't open the file.\n" );
else
{
printf("Child1: Input a number of text lines ended, each ended by a CR (carriage return).\n");
/////////////////////////////
do
{
if (NULL != fgets(c, sizeof(c), stdin))
{
if (0 == strcmp(c, ".\n"))
{
break;
}
fprintf(pf, "%s", c);
}
else
{
if (0 != ferror(stdin))
{
fprintf(stderr, "An error occured while reading from stdin\n");
}
else
{
printf("Child1: Finish the input by CNTL^D\n");
}
break;
}
} while (1);
/////////////////////////////
}
printf("\nChild1:The file %s is succesfully created and saved in the current dictionary\n",file);
//////////////////////////////////////////////
/////////////////////////pipe///////////////
fclose(pf); // close file
char ch;
int outcount = 0;
int fd[2], nbytes;
pid_t childpid;
int i;
char f2[2];
char readbuffer[80];
pipe(fd);
if((childpid = fork()) == -1)
{
perror("fork");
exit(1);
}
if(childpid == 0)
{ printf("\nChild1:The file written to pipe with cat\n");
close(1) ;
dup(fd[1]);
close(fd[0]);
execlp("/bin/cat", "cat", file,NULL);
}
else
{
wait(NULL);
//close(0) ;
//dup(fd[0]) ;
//close(fd[1]);
//nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
//printf("%s\n",readbuffer);
}
return(0);
}
Program 2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int fd[2],nbytes;
pid_t childpid;
char readbuffer[80];
pipe(fd);
if((childpid = fork()) == -1)
{
perror("fork");
exit(1);
}
if(childpid == 0)
{
}
else
{
close(0) ;
dup(fd[0]) ;
close(fd[1]);
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("%s\n",readbuffer);
}
return(0);
}
You may want to check the man pages for execve(2) (for starting cat) and dup2(2) (for overriding stdin and stdout as needed) for this one. execve will overwrite the currently executing program by a different one (same PID, same file descriptors), while dup2 will allow you re-define any of the standard file descriptors to point into any file descriptor you provide to it (such as any of the ends of your pipe).

Writing to a pipe in a child process called by execl

I don't understand how to use the created pipe from mp.c in the child process sp.c. I (think I) can't seem to access proper file descriptor when using execl for outside process.
/***************mp.c*****************/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[]) {
char *procpath = "/mypath/sp";
char *procname = "sp";
pid_t pid;
int fd[2];
int ret;
char buf[20];
memset(&buf[0], 0, sizeof(buf));
ret = pipe(fd);
if(ret == -1){
perror("pipe");
exit(1);
}
pid = fork();
printf("%d\n",pid);
if (pid == 0){
//dup2(mypipefd[1],STDOUT_FILENO);
ret = execl(procpath, procpath, "1","2",NULL);
perror("execl failed to run slave program");
exit(1);
}
else if (pid > 0){
/* Parent process*/
printf("execl ret val = %d",ret);
printf("Parent process \n");
close(fd[1]);
read(fd[0],buf,15);
// close(fd[1]);
close(fd[0]);
printf("buf: %s TEST\n", buf);
printf("buf: %s TEST\n", buf);
}
else{
printf("call to fork failed, no child\n");
exit(-1);
}
exit(0);
}
and the created process...
/***************sp.c*****************/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
int main(int argc, char *argv[]){
int ret;
//printf("Child process \n");
int fd[2];
pipe(fd);
//dup2(fd[1],1);
//int out;
/*ret = dup2(fd[1],1);
if (ret = -1){
printf("%s\n", strerror(errno));
};*/
//sprintf()
//printf("%d\n", ret);
//mypipefd = argv[1];
printf("Child process \n");
//close(fd[0]);
write(fd[1], "Hello there!",12);
close(fd[1]);
exit(0);
}
The problem is that you are creating a different pipe in each application. In order to correctly communicate over a pipe, two program should share the same pipe ( one of the file descriptor create by the pipe function).
Basically to solve this problem, you must create the pipe in one application and send the file descriptor to the other program without calling again the system call pipe. A file descriptor can be sent to another process by using a socket unix domain. Look a this post Can I share a file descriptor to another process on linux or are they local to the process?.

Thread feeding other MultiThreading

I see it's easy to open pipe between two process using fork, but how we can passing open pipe to threads.
Assume we need to pass out of PROGRAM A to PROGRAM B "may by more than one thread",
PROGRAM B send his output to PROGRAM C
EDIT:
I come again after modifying the code to become more easy for reading.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <fcntl.h>
void *thread1(void *arg) {
int status, fd[2];
pid_t pid;
pipe(fd);
pid = fork();
if (pid == 0) {
int fd2 = *((int *) (arg));
dup2(STDIN_FILENO, fd2);
close(fd[0]);
dup2(fd[1], STDOUT_FILENO);
close(fd[1]);
execvp("PROGRAM B", NULL);
exit(1);
} else {
close(fd[1]);
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
execl("PROGRAM C", NULL);
wait(&status);
return NULL;
}
}
int main(void) {
FILE *fpipe;
char *command = "PROGRAM A";
char buffer[1024];
if (!(fpipe = (FILE*) popen(command, "r"))) {
perror("Problems with pipe");
exit(1);
}
char* outfile = "out.dat";
//FILE* f = fopen (outfile, "wb");
//int fd = fileno( f );
int fd[2];
fd[0] = open(outfile, O_WRONLY);
pthread_t thid;
if (pthread_create(&thid, NULL, thread1, fd) != 0) {
perror("pthread_create() error");
exit(1);
}
int len;
while (read(fpipe, buffer, sizeof (buffer)) != 0) {
len = strlen(buffer);
write(fd[0], buffer, len);
}
pclose(fpipe);
return (0);
}
For intra-process messaging, POSIX queues will probably suit your needs better than pipes. Check out man mq_overview (or online).

Resources