home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!mcsun!sunic!dkuug!diku!thorinn
- From: thorinn@diku.dk (Lars Henrik Mathiesen)
- Newsgroups: comp.unix.programmer
- Subject: Re: Passing file descriptors between processes
- Message-ID: <1992Nov17.155819.17834@odin.diku.dk>
- Date: 17 Nov 92 15:58:19 GMT
- References: <TML.92Nov17125115@tiuhti.tik.vtt.fi>
- Sender: thorinn@tyr.diku.dk
- Organization: Department of Computer Science, U of Copenhagen
- Lines: 111
-
- tml@tik.vtt.fi (Tor Lillqvist) writes:
- >I vaguely remember that is is possible (at least in pure BSD) to pass
- >open file descriptors between processes. I think UNIX domain sockets
- >had something to do with it.
-
- Indeed they do, as illustrated by the small example program that I
- shall append. (It creates a socketpair, forks, opens a file and reads
- the first byte, passes the descriptor to the other process and reads
- some more --- with some test output to show that it works as claimed.)
-
- >But I can't find anything about it in the HP-UX or SunOS manual
- >pages. Could somebody refresh my memory please?
-
- It does work on SunOS 4.1.1 and HP-UX 8.07. On both systems, the
- manual section for recvmsg(2) mentions access rights, but does not
- explicitly say that these are file descriptors; while the unix(4F/7P)
- sections contain references to the Network Programming document/IPC
- programmer's manual, I am not sure that those documents are any more
- helpful --- the 4.3 IPC Tutorials certainly are not.
-
- Lars Mathiesen (U of Copenhagen CS Dep) <thorinn@diku.dk> (Humour NOT marked)
-
- -----s-n-i-p-p-e-t-y---s-n-i-p-p-e-t-y---s-n-i-p-p-e-t-y---s-n-i-p-----
- #include <sys/file.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/uio.h>
- #include <stdio.h>
-
- main(argc, argv)
- char **argv;
- {
- char buf[BUFSIZ];
- int sv[2], pid, fd = -1, n;
- struct iovec iov;
- struct msghdr mh;
-
- if (argc != 2) {
- fprintf(stderr, "Usage: pass_access file\n");
- exit(2);
- }
- /* Set up a message header:
- No send/receive address
- One buffer in iovec (otherwise recvmsg won't wait for sendmsg)
- A file descriptor area of length one.
- */
- mh.msg_name = 0;
- mh.msg_namelen = 0;
- iov.iov_base = buf;
- iov.iov_len = BUFSIZ;
- mh.msg_iov = &iov;
- mh.msg_iovlen = 1;
- mh.msg_accrights = (caddr_t)&fd;
- mh.msg_accrightslen = sizeof fd;
-
- /* Create a pair of connected sockets */
- if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sv) < 0) {
- perror("socketpair");
- exit(1);
- }
- if ((pid = fork()) < 0) {
- perror("fork");
- exit(1);
- }
- if (pid == 0) {
- /* Child: close a descriptor to illustrate that
- access rights are passed in internal form
- */
- close(sv[0]);
- /* Open a random file */
- if ((fd = open(argv[1], O_RDONLY)) < 0) {
- fputs(argv[1], stderr);
- perror(": open");
- exit(1);
- }
- if ((n = read(fd, buf, 1)) < 0) {
- perror("child read");
- exit(1);
- }
- printf("Child: fd = %d, first char '%c'\n", fd, n ? buf[0] : '?');
- fflush(stdout);
- /* Send a null message with access right tacked on */
- iov.iov_len = 0;
- if ((n = sendmsg(sv[1], &mh, 0)) < 0) {
- perror("sendmsg");
- exit(1);
- }
- printf("Child: sent %d bytes\n", n);
- fflush(stdout);
- exit(0);
- }
- /* Parent: Close send socket to prevent hang if child never sends */
- close(sv[1]);
- /* Get message and access right */
- if ((n = recvmsg(sv[0], &mh, 0)) < 0) {
- perror("recvmsg");
- exit(1);
- }
- printf("Parent: fd = %d, received %d bytes\n", fd, n);
- fflush(stdout);
- /* Copy contents of (small) file */
- if ((n = read(fd, buf, BUFSIZ)) < 0) {
- perror("read");
- exit(1);
- }
- if ((n = write(1, buf, n)) < 0) {
- perror("write");
- exit(1);
- }
- exit(0);
- }
-