Passing file descriptors thru rexec() socket

Passing file descriptors thru rexec() socket

Post by Erik Demai » Mon, 22 May 1995 04:00:00



Hello,

I've been having some troubles passing file descriptors between a
"parent" process and a remote "child" process.  This is not the typical
child/parent relation;  the child was spawned using rexec().  The problem
occurs even when the remote host is just "localhost."  I used the socket
returned by rexec() to pass the original stdin (fd 0) to the new program.
I tried using the sendfile/recvfile (BSD 4.3 versions) from Stevens' UNIX
Network Programming book, and they didn't work -- the sendmsg (in sendfile)
gave the EINVAL (Invalid Parameter) error, probably the most non-descriptive
error message.  Note that when the processes have a parent/child relation
(spawned using execl()), these routines work great.  To further investigate,
I setup client/server programs which used datagram Berkeley sockets to pass a
file descriptor (setting msg_name and msg_namelen in the msghdr structure for
sending).  This also didn't work.

BTW, I know rexec() correctly spawned the remote child.  It prompted for
a username/password.  As well, correct diagnostics were printed by the
program (I read from the rexec() socket and printed any results).  I also
tried the send_fd and recv_fd routines from Stevens' Advanced Programming in
the UNIX Environment book.  recv_fd then gave the error "... but no file
descriptor."

If you have any suggestions as to what my problem is, please advise.
I've enclosed the source code of my test program if you'd like to look at it.

Erik Demaine

P.S. All code was run on a SPARC 2 with SunOS 4.1.3.
--


URL: http://ug.cs.dal.ca:3400/~edemaine/edemaine.html
--> A glob is a round substance of thick liquid. A blob is an unformed object.

----------------------- SOURCE CODE FOLLOWS [test.c] -----------------------

#include <stdio.h>
#include <netdb.h>
#include <errno.h>

main (int argc, char *argv[])
{
   int child;
   int fd, pfd[2], nothing[2];
   char c;

   if (argc == 2)
   {
      printf ("child: Starting.\n");
      child = 1;
   } else
      child = 0;

   if (child)
   {
      fd = recv_fd (0);
      printf ("Got it: %d\n", fd);
      for (;;)
      {
         read (fd, &c, 1);
         printf ("child: Character %c\n", c);
      }
   }
   else
   {
      int sock;
      struct servent *sp;
      char *host = "afton";
      sp = getservbyname ("exec", "tcp");
      if (sp == NULL)
         perror ("eek");
      sock = rexec (&host, sp->s_port, NULL, NULL, "/users/students/edemaine/hop/temp/test Child", 0);
      if (sock < 0)
      {
         perror ("rexec failed");
         exit (-sock);
      }
      printf ("parent: Here goes.\n");
      if (send_fd (sock, 0))
      {
         perror ("send_fd failed");
         printf ("%d\n", errno);
         exit (1);
      }
      printf ("parent: Enter text to write to child\n");
      while (read (sock, &c, 1) > 0)
         printf ("%c", c);
   }

Quote:}

/* UNIX Network Programming code inserted: */

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

int send_fd (int sockfd, int fd)
{
   struct iovec iov[1];
   struct msghdr msg;

   iov[0].iov_base = (char *) 0;
   iov[0].iov_len = 0;
   msg.msg_iov = iov;
   msg.msg_iovlen = 1;
   msg.msg_name = (caddr_t) 0;
   /* I also tried setting msg.msg_namelen to various values - no luck */
   msg.msg_accrights = (caddr_t) &fd;
   msg.msg_accrightslen = sizeof (fd);

   if (sendmsg (sockfd, &msg, 0) < 0)
      return -1;
   return 0;

Quote:}

int recv_fd (int sockfd)
{
   int fd;
   struct iovec iov[1];
   struct msghdr msg;

   iov[0].iov_base = (char *) 0;
   iov[0].iov_len = 0;
   msg.msg_iov = iov;
   msg.msg_iovlen = 1;
   msg.msg_name = (caddr_t) 0;
   msg.msg_accrights = (caddr_t) &fd;
   msg.msg_accrightslen = sizeof (fd);

   if (recvmsg (sockfd, &msg, 0) < 0)
      return -1;
   return fd;

Quote:}

/* EOF */
 
 
 

Passing file descriptors thru rexec() socket

Post by Barry Margol » Mon, 22 May 1995 04:00:00



>I've been having some troubles passing file descriptors between a
>"parent" process and a remote "child" process.  This is not the typical
>child/parent relation;  the child was spawned using rexec().  The problem
>occurs even when the remote host is just "localhost."

File descriptors can only be passed through Unix domain sockets.  Rexec()
always uses Internet domain sockets, even when the remote host is
localhost.
--
Barry Margolin
BBN Planet Corporation, Cambridge, MA


 
 
 

1. autoinstall patches and passing file descriptors via sockets

Does anyone know how to use the Solaris autoinstall client
software to install patches automatically after installing
Solaris on the new disk?  The biggest problem I see is that
the new system's filesystem is mounted in /a during the
install and the "installpatch" stuff seems to depend on every-
thing being mounted on / instead.  The "Solaris 2.2 System
Configuration and Installation Guide" doesn't mention anything
about this...

 thanks


p.s., there is a bug in Solaris 2.2 that crashes the kernel
if a user-level program passes a file descriptor to another
process using a Unix domain socket...the patch is named
100999-11 and is not on the usual thor ftp site...

2. Cookie?

3. passing an open file or socket descriptor

4. Connecting a linux and a win9x PC together.

5. UNIX domain sockets - file descriptor passing

6. Route add

7. glibc and passing live file descriptors through sockets

8. executable prog's

9. PASSING FD THRU UNIX DOMAIN SOCKET

10. passing structs thru sockets?

11. Help : Passing Socket Descriptor

12. Help: Passing Socket Descriptor