[comp.unix.internals] struct msghdr, passing fds between processes

cjsv@sserve.cc.adfa.oz.au (Christopher JS Vance) (04/22/91)

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.

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.

I guess that the stream must probably be a UNIX domain socket or pipe.  Or am
I barking up the wrong tree?

What I'd like to do is start up a process which has access to my login terminal,
have it open a socket-based connection to a server process, and have it pass
access to my login terminal to the server process.

(Subsidiary question - if I can do this, and my server process had no
controlling terminal, does it suddenly inherit one?)

What colour dragons be here?  (i.e., what do I need to be wary of?)

A bit of working code would be a bonus.  If your reference is the BSD book by
Leffler et al., I can borrow a copy, but won't bother unless it helps.  I had
a copy of the Advanced IPC document, but I don't seem to remember seeing it
there, and the person who has my copy hasn't returned it.  I can get it back,
though, if it's worth it.

-- 
Christopher

jik@athena.mit.edu (Jonathan I. Kamens) (04/23/91)

  (Note Followup-To.  This isn't really related to the TCP/IP protocol.)

In article <1991Apr22.123248.8250@sserve.cc.adfa.oz.au>, cjsv@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@Athena.MIT.EDU				Allston, MA  02134
Office: 617-253-8085			      Home: 617-782-0710

cjsv@sserve.cc.adfa.oz.au (Christopher J S Vance) (04/26/91)

Thanks very much to Jonathan Kamens and Rich Salz who provided some sample code,
to Chip Rosenthal and Rich Stevens who recommended Rich Stevens' book,
and to Dan Bernstein who pointed me toward the source of his pty program.

-- Christopher