I was reading this example from Stevens book about using socketpair to send
the fd of a file opened by a child back to its parent.
This program called openfile is execed by the function myopen and is passed
a socket fd (opened using socketpair) which openfile then uses to send the
fd to the parent process. My question is - are stream pipes assigned
global numbers valid across all processes? Otherwise how is a
process (instance of openfile) able to use a socket fd opened by another?
I'd be grateful if someone could clarify this.
Arvind
-------------------
/*
* Open a file, returning a file descriptor.
*
* This function is similar to the UNIX open() system call,
* however here we invoke another program to do the actual
* open(), to illustrate the passing of open files
* between processes.
*/
int
my_open(filename, mode)
char *filename;
int mode;
{
int fd, childpid, sfd[2], status;
char argsfd[10], argmode[10];
extern int errno;
if (s_pipe(sfd) < 0) /* create an unnamed stream pipe */
return(-1); /* errno will be set */
if ( (childpid = fork()) < 0)
err_sys("can't fork");
else if (childpid == 0) { /* child process */
close(sfd[0]); /* close the end we don't use */
sprintf(argsfd, "%d", sfd[1]);
sprintf(argmode, "%d", mode);
if (execl("./openfile", "openfile", argsfd, filename,
argmode, (char *) 0) < 0)
err_sys("can't execl");
}
/* parent process - wait for the child's execl() to complete */
close(sfd[1]); /* close the end we don't use */
if (wait(&status) != childpid)
err_dump("wait error");
if ((status & 255) != 0)
err_dump("child did not exit");
status = (status >> 8) & 255; /* child's exit() argument */
if (status == 0) {
fd = recvfile(sfd[0]); /* all OK, receive fd */
} else {
errno = status; /* error, set errno value from child's errno */
fd = -1;
}
close(sfd[0]); /* close the stream pipe */
return(fd);
/*Quote:}
* openfile <socket-descriptor-number> <filename> <mode>
*
* Open the specified file using the specified mode.
* Return the open file descriptor on the specified socket descriptor
* (which the invoker has to set up before exec'ing us).
* We exit() with a value of 0 if all is OK, otherwise we pass back the
* errno value as our exit status.
*/
main(argc, argv)
int argc;
char *argv[];
{
int fd;
extern int errno;
extern char *pname;
pname = argv[0];
if (argc != 4)
err_quit("openfile <sockfd#> <filename> <mode>");
/*
* Open the file.
*/
if ( (fd = open(argv[2], atoi(argv[3]))) < 0)
exit( (errno > 0) ? errno : 255 );
/*
* And pass the descriptor back to caller.
*/
exit( sendfile(atoi(argv[1]), fd) );
Quote:}