struct msghdr, passing fds between processes
Jonathan I. Kamens
jik at athena.mit.edu
Tue Apr 23 09:43:12 AEST 1991
(Note Followup-To. This isn't really related to the TCP/IP protocol.)
In article <1991Apr22.123248.8250 at sserve.cc.adfa.oz.au>, cjsv at sserve.cc.adfa.oz.au (Christopher JS Vance) writes:
|> I note that a BSD struct msghdr (used with sendmsg and recvmsg) allows the
|> passing of `access rights'. I seem to remember someone indicating that this
|> meant open file descriptors, sort of like a call on dup, except to a different
|> process.
Yes.
|> Could someone who knows please point me to some documentation of this feature,
|> or at least let me know what kinds of stream these can be passed over. I assume
|> that the numbers change on the wire and come out as open fds at the other end.
The only documentation about it that I know of is the recvmsg(2) man page
(or, at least, that's the only place I've seen it mentioned; it may be
mentioned in other man pages as well). According to that man page, fd's can
only be passed over sockets (although I suspect that it'll work with pipes
too, since pipes are implemented on top of sockets). The way you pass a
descriptor is by assigning the address of an int containing the descriptor
number to the msg_accrights member of the msghdr structure and sizeof(int) to
the msg_accrightslen member of the structure, and then sending a message over
a socket to another process using sendmsg(). The other process receives the
mssage using recvmsg(), and the integer found in the msg_accrights member will
be the number of the open file descriptor that was passed (as you point out,
it may be a different number than what it was at the originating end).
I'm not sure what happens if you send a descriptor from a process to itself;
I suspect it's just like a dup().
Here's a really simple program, with absolutely no error checking, that
demonstrates how this works. It works for me, but I make no guarantees :-).
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <stdio.h>
main()
{
int pair[2];
struct msghdr msg;
int fd;
char buf[BUFSIZ];
int c;
socketpair(AF_UNIX, SOCK_STREAM, 0, pair);
msg.msg_name = 0;
msg.msg_namelen = 0;
msg.msg_iov = 0;
msg.msg_iovlen = 0;
msg.msg_accrights = (char *) &fd;
msg.msg_accrightslen = sizeof(fd);
if (fork()) {
/* Parent */
close(pair[1]);
fd = open("/etc/passwd", O_RDONLY, 0);
sendmsg(pair[0], &msg, 0);
}
else {
/* Child */
close(pair[0]);
recvmsg(pair[1], &msg, 0);
while ((c = read(fd, buf, sizeof(buf))) > 0)
write(1, buf, c);
}
}
--
Jonathan Kamens USnail:
MIT Project Athena 11 Ashford Terrace
jik at Athena.MIT.EDU Allston, MA 02134
Office: 617-253-8085 Home: 617-782-0710
More information about the Comp.unix.internals
mailing list