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