How to transfer file descriptors with UNIX domain sockets?

Oliver Laumann net at tub.UUCP
Sat Jun 30 00:21:30 AEST 1990


In article <37317 at ucbvax.BERKELEY.EDU> rgm at OCF.Berkeley.EDU (Rob Menke) writes:
> 
> I have seen references in various IPC tutorials and manuals that it is
> possible to transfer file descriptors between processes via UNIX domain
> sockets using sendmsg(2) and recvmsg(2).
> 
> I'm hoping that someone out there might be able to provide a detailed
> description of how this is done, or better yet, some clear code that could be
> used as an example.

The following two trivial programs demonstrate this functionality.

The first of them accepts a connection on a UNIX domain socket, opens
/etc/passwd, sends the file descriptor to the peer process, and then exits.

The other program establishes a connection, receives the file descriptor,
reads a buffer full of data from it, and writes it to standard output.

Yes, I know, the programs are written in a sloppy style (no exit codes,
arguments not properly casted, no man-page and "imake" file :-)

Regards,
--
Oliver Laumann     net at TUB.BITNET     net at tub.cs.tu-berlin.de     net at tub.UUCP


--------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>

main () {
    int s, fd;
    struct sockaddr_un a;
    static struct msghdr msg;
    static struct iovec iov;
    char *name = "foo";

    unlink (name);
    if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) {
	perror ("socket"); return;
    }
    a.sun_family = AF_UNIX;
    strcpy (a.sun_path, name);
    if (bind (s, (struct sockaddr *)&a, strlen (name)+2) == -1) {
	perror ("bind"); return;
    }
    listen (s, 1);
    s = accept (s, (struct sockaddr *)0, (int *)0);
    if ((fd = open ("/etc/passwd", 0)) == -1) {
	perror ("passwd"); return;
    }
    msg.msg_accrights = (caddr_t)&fd;
    msg.msg_accrightslen = sizeof (fd);
    msg.msg_iov = &iov;
    if (sendmsg (s, &msg, 0) == -1)
	perror ("sendmsg");
}
--------------------------------------------------------------------------
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>

main () {
    int s, n, fd;
    struct sockaddr_un a;
    static struct msghdr msg;
    static struct iovec iov;
    char *name = "foo";
    char buf[512];

    if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) {
	perror ("socket"); return;
    }
    a.sun_family = AF_UNIX;
    strcpy (a.sun_path, name);
    if (connect (s, (struct sockaddr *)&a, strlen (name)+2) == -1) {
	perror ("connect"); return;
    }
    msg.msg_accrights = (caddr_t)&fd;
    msg.msg_accrightslen = sizeof(fd);
    msg.msg_iov = &iov;
    if ((n = recvmsg (s, &msg, 0)) == -1) {
	perror ("recvmsg"); return;
    }
    if ((n = read (fd, buf, 512)) == -1) {
	perror ("read"); return;
    }
    write (1, buf, n);
}
--------------------------------------------------------------------------



More information about the Comp.unix.questions mailing list