Writing to a pipe in a child process called by execl - c

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?.

Related

How to fix data write or read using pipe in c program is giving wrong output?

I am trying to get an integer input in the child process and send it to the parent process using pipe()
but I receive garbage values every time in the parent process.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include<sys/wait.h>
int main(int argc, char *argv[])
{
pid_t pid;
int fd[2];
char *args[] = {"", NULL};
int cnum,pnum;
pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);
}
if(pipe(fd) == -1)//fd[0] for read fd[1] for write
{
perror("pipe");
exit(1);
}
if(pid == 0)
{
close(fd[0]);
printf("\n**In the child process**\n");
printf("Enter Number : ");
scanf("%d",&cnum);
write(fd[1],&cnum,sizeof(int));
close(fd[1]);
}
else
{
wait(NULL);
close(fd[1]);
printf("\n**In the parent precess**\n");
read(fd[0],&pnum,sizeof(int));
close(fd[0]);
printf("Number recieved = %d\n",pnum);
printf("PID = %d\n", getpid());
execv("./sayHello", args);
printf("Error");
}
}
Output of the above code
**In the child process**
Enter Number : 212
**In the parent precess**
Number recieved = 1036468968
PID = 22528
Hillo Amol
PID = 22528
I give input of 212 but in parent 1036468968 received.
You call fork before you create the pipe FDs. After you call fork, the parent and the child both create their own pair of pipe FDs, and there's no shared pipe between them.
Create the pipe before you fork and it could work.
As drorfromthenegev suggest problem is arising due to I am calling pipe() after fork().
So I call pipe() first and the i call fork() and it works..
Workable solution
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include<sys/wait.h>
int main(int argc, char *argv[])
{
pid_t pid;
int fd[2];
char *args[] = {"", NULL};
int cnum,pnum;
if(pipe(fd) == -1)//fd[0] for read fd[1] for write
{
perror("pipe");
exit(1);
}
pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);
}
if(pid == 0)
{
close(fd[0]);
printf("\n**In the child process**\n");
printf("Enter Number : ");
scanf("%d",&cnum);
write(fd[1],&cnum,sizeof(int));
close(fd[1]);
}
else
{
wait(NULL);
close(fd[1]);
printf("\n**In the parent precess**\n");
read(fd[0],&pnum,sizeof(int));
close(fd[0]);
printf("Number recieved = %d\n",pnum);
printf("PID = %d\n", getpid());
execv("./sayHello", args);
printf("Error");
}
}

Sending image through pipe to child process in 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);
}
}

two child process communicating through named pipe

I have main program which creates two children and one named pipe(FIFO). Each children executes a program called “sendSignal" via execv(). One of the argument of the “sendSignal” is the FIFO in the main program.
The children are going to send signal to each other. It decided with an argument in the main (in variable firstShooter)program which signal shoot first.
I want to know how these two children can send each other their pid through this named pipe.
Following is the main program:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
/* this program should be provided with 2 arguments */
int main(int argc, char **argv)
{
char str1[15];
char str2[15];
char fileDescriptor[15];
char *my_args[4];
char *myfifo = "myfifo";
int fd, pipeCheck;
pid_t pid1, pid2, wid;
/* If the user does not provide the argument to determin which child is firing first */
if(argc != 2)
{
fprintf(stderr,"%s: 2 arguments needed, got %d\n",argv[0],argc-1);
exit(1);
}
/* create the FIFO (named pipe) */
pipeCheck = mkfifo(myfifo, 0666);
/* check if the named pipe was created properly if not output an error */
if(pipeCheck == -1)
{
fprintf(stderr, "%s: Error creating named pipe: %s\n",argv[0], strerror(errno));
exit(1);
}
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)
{
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // the named pipe as arguemnt
my_args[3] = NULL;
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by first child...");
exit(-1);
}
pid2 = fork();
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // named pipe as arguemnt
my_args[3] = NULL;
// printf("this is converted = %s\n",my_args[1]);
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by second child...");
exit(-1);
}
close(fd);
unlink(myfifo);
wid = wait(NULL);
return 0;
}
here is the sendSignal:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
void sig_handler(int signo)
{
if(signo == SIGUSR1)
printf("signal received\n");
}
int main(int argc, char **argv)
{
char abspath[256] = "";
getcwd(abspath, 256);
strrchr(abspath, '/');
if(signal(SIGUSR1,sig_handler) == SIG_ERR)
printf("\n Cannot catch the signal\n");
char *myfifo = "myfifo";
int firstShooter = atoi(argv[1]); //define the first process to send the signal
int fd;
char str1[15];
char str2[15];
char pid1[15];
char pid2[15];
fd = open(argv[2],O_RDWR);
if(firstShooter == 1)
{
sprintf(pid1,"%d",getpid());
write(fd,pid1,sizeof(pid1));
}
if(firstShooter == 2)
{
sprintf(pid2,"%d",getpid());
write(fd,pid2,sizeof(pid2));
}
read(fd,str1,sizeof(str2));
read(fd,str2,sizeof(str2));
close(fd);
printf("str1 = %s\n",str1);
printf("str2 = %s\n",str2);
return 0;
}
Both of your children processes got the same arguments:
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // the named pipe as argument
my_args[3] = NULL;
firstShooter parameter doesn't make sense as process cannot identify itself as first or second.
I suggest to add one more parameter - process index. sendSignal function logic can be modified this way:
char pid1[15];
char pid2[15];
int processIndex = atoi(argv[3]);
fd = open(argv[2],O_RDWR);
if (processIndex == firstShooter)
{
// Send firstShooter PID
sprintf(pid1,"%d",getpid());
write(fd,pid1,sizeof(pid1));
// Got the other PID
read(fd,pid2,sizeof(pid2));
}
else
{
// Got the firstShooter PID
read(fd,pid1,sizeof(pid1));
// Send the other PID
sprintf(pid2,"%d",getpid());
write(fd, pid2, sizeof(pid2));
}
close(fd);
printf("pid1 = %s\n",pid1);
printf("pid2 = %s\n",pid2);
There are some issues in the way you have implemented.
1.Calling two fork() in the main program will be creating more than two child processes.(3 child processes). So give a condition to check that you are calling the next fork in the context of the parent itself.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
/* this program should be provided with 2 arguments */
int main(int argc, char **argv)
{
int * status;
char str1[15];
char str2[15];
char fileDescriptor[15];
char *my_args[4];
char *myfifo = "myfifo";
int fd, pipeCheck;
pid_t pid1, pid2, wid;
/* If the user does not provide the argument to determin which child is firing first */
if(argc != 2)
{
fprintf(stderr,"%s: 2 arguments needed, got %d\n",argv[0],argc-1);
exit(1);
}
/* create the FIFO (named pipe) */
pipeCheck = mkfifo(myfifo, 0666);
/* check if the named pipe was created properly if not output an error */
if(pipeCheck == -1)
{
fprintf(stderr, "%s: Error creating named pipe: %s\n",argv[0], strerror(errno));
exit(1);
}
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)//child
{
// printf("pid1=0\n");
printf("i am child 1 %d\n",getpid());
my_args[0] = "sendSignal";
my_args[1]=malloc(6);
sprintf(my_args[1] , "%d", getpid());
//my_args[1]="1";
printf("p%s\n",my_args[1]);
my_args[2] = myfifo; // the named pipe as arguemnt
my_args[3] ="1";
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by first child...");
exit(-1);
}
else if(pid1>0)// parent
{
// printf("pid1 %d",pid1);
waitpid(pid1,&status,WIFEXITED(status));
pid2 = fork();
// printf("p:%d",pid2);
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
printf("i am child 2 %d\n",getpid());
my_args[0] = "sendSignal";
my_args[1]=malloc(6);
sprintf(my_args[1] , "%d", getpid());
my_args[2] = myfifo; // named pipe as arguemnt
my_args[3] = "2";
// printf("this is converted = %s\n",my_args[1]);
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by second child...");
exit(-1);
}
printf("done\n");
}
close(fd);
wait(NULL);
fd=open("fifo1", O_RDONLY);
char * space=(char *)malloc(6);
read(fd,space,6);
printf("from fifo1 %s",space);
fd=open("fifo2", O_RDONLY);
//char * space=(char *)malloc(6);
read(fd,space,6);
printf("from fifo2 %s",space);
//unlink(myfifo);
wid = wait(NULL);
unlink(myfifo);
return 0;
}
2. The two child process are accessing the same pipe. Pipe is for one way communication with an end for reading and another for writing. So create two pipes each for a process. I would suggest better not to go for pipes.

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).

Resources