views:

377

answers:

4

I have written code for passing file descriptors between unrelated processes using streams. The server should wait for the client to send a file descriptor. Here is the server code:

#include <sys/types.h>   
#include <sys/stat.h>  
#include <fcntl.h>  
#include <stropts.h>  
#include <stdio.h>  
#include <errno.h>  
#include <unistd.h>  

int  main(int argc, char *argv[])
{  
    int fd;  
    int pipefd[2];  
    pipe(pipefd);  
    close(pipefd[1]);  
    recvfd(pipefd[0]);  
    return 0;
}

void recvfd(int p)  
{
    struct strrecvfd rfdbuf;  
    struct stat statbuf;   
    int i;  
    i=ioctl(p, I_RECVFD, &rfdbuf);  
    printf("errno=%d\n",errno);  
    printf("recvfd=%d\n", rfdbuf.fd);  
}

But I receive the error number 9 - Bad file descriptor.

A: 

Is this the actual code ? Cause nowhere do you create or receive a valid filedescriptor.

nos
+2  A: 

NB: the question has been extensively modified since this answer was written.


Where to begin?

  • main() returns an int.
  • pipefd is not initialized.
  • You close a random file descriptor.
  • You call recvfd() on another random file descriptor.
  • You don't return a value from main().
  • You don't use the #define value.
  • You don't show the #include files needed to make this compile.
  • Unused variable fd.
  • Unused variable statbuf.
  • Unchecked return value i.

Basic problem - use of uninitialized variables.

Subsidiary problem - limited error checking.


Additional problem: conceptually, you want a server that can be passed a file descriptor. You need that server to be reading from a file descriptor that other (unrelated) processes can create. You will need to look at the manuals rather carefully, but will probably need the server listening on a Unix-domain socket, or perhaps reading on a (named) FIFO. Other programs can then open the socket or FIFO and send their own file descriptor to the server.

Jonathan Leffler
Technically, it's ok to omit the return type from main() (but for main _only_), in which case `int' is assumed. Similarly, it's ok to omit the return statement from main (again, main _only_), in which case there is an implicit 'return 0'. It's still bad practice, though.
Adam Rosenfield
Not in C99, which is the current C standard. There are no 'implicit int' return types etc in C99.
Jonathan Leffler
A: 

You never initialize pipefd! Missing a

pipe(pipefd);

line before the close call...?

Alex Martelli
A: 

You don't mention what OS you are running. I_RECVFD is part of the STREAMS extensions which are normally only present in System V based Unixy operating systems (AIX and Solaris for example). Others, like Linux and BSD, do not support it and probably never will as Posix now has an alternative using sendmsg() and recvmsg().

I'm afraid that I don't know why Linux has #defines I_RECVFD if it does not support it.

Dipstick
I had to use ioctl() with fifos (and not pipes) and like you said, it does not work on Linux but works on Solaris.
Anonymous