Yes that is true that file descriptors remain open even after fork or exec or fork and exec.You only need to know the value of fd in the new process image that was replaced using exec else put that fd on the one which is already known to that process(ex:0,1,2). So you can do this in two ways:
Placing the fd on either one of standard file descriptors using dup2(note:as far as i know you will be unable to reset that standard file descriptor for which it was actually known for)
Passing the fd as string argument for one of 6 exec functions does the job
Therefore I suggest you to use second method in case if you want standard fds remain
These are the two methods of implementation:
P1.c(using argument passing)
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
void main()
{
printf("Hello this is process 1\n");
int fd=open("./foo",O_RDONLY);
char buf[255];
//int n=read(fd,buf,255);
int h=fork();
if(h==0)
{
char *fname="./p2";
char *arg[3];
char targ[10];
sprintf(targ,"%d",fd);
arg[0]=fname;
arg[1]=targ;
arg[2]=NULL;
execvp(fname,arg);
}
else
{
printf("This is from p1 process\n");
//write(1,buf,strlen(buf));
//do some process with p1
printf("This is end of p1 process\n");
}
}
P1.c(using dup2 with 0)
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
void main()
{
printf("Hello this is process 1\n");
int fd=open("./foo",O_RDONLY);
int h=fork();
if(h==0)
{
dup2(fd,0);//note we will be loosing standard input in p2
execvp(fname,NULL);
}
else
{
printf("This is from p1 process\n");
//write(1,buf,strlen(buf));
//do some process with p1
printf("This is end of p1 process\n");
}
}
P2.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
int main(int argc,char *argv[])
{
int fd=atoi(argv[1]); //here fd=0 in case dup2 in process ps1.c
char buf[1024];
int n=read(fd,buf,1024);
buf[n]='\0';
printf("This is from p2\n");
write(1,buf,strlen(buf));
}