#include "sm/generic.h"
SM_RCSID("@(#)$Id: sendfd.c,v 1.6 2005/06/16 20:39:02 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/varargs.h"
#include "sm/limits.h"
#include "sm/types.h"
#include "sm/heap.h"

/*
**  not used by any application; see write_fd.c instead.
*/

#if LIB44_FD
#include <sys/types.h>
#include <sys/socket.h>		/* struct msghdr */
#include <sys/uio.h>		/* struct iovec */
#include <errno.h>
#include <stddef.h>

/* XXX !!! */
static struct cmsghdr	*cmptr = NULL;	/* buffer is malloc'ed first time */
#define CONTROLLEN	(sizeof(struct cmsghdr) + sizeof(int))
		/* size of control buffer to send/recv one file descriptor */

/* Pass a file descriptor to another process.
 * If fd<0, then -fd is sent back instead as the error status. */

sm_ret_T
send_fd(int clifd, int fd)
{
	struct iovec	iov[2];
	struct msghdr	msg;
	char		buf[2];	/* send_fd()/recv_fd() 2-byte protocol */
	int		r;

	iov[0].iov_base = buf;
	iov[0].iov_len  = 2;
	iov[1].iov_base = buf;
	iov[1].iov_len  = 2;
	msg.msg_iov     = iov;
	msg.msg_iovlen  = 1;
	msg.msg_name    = NULL;
	msg.msg_namelen = 0;
	msg.msg_flags	= 0;
	if (fd < 0)
	{
		msg.msg_control    = NULL;
		msg.msg_controllen = 0;
		buf[1] = -fd;	/* nonzero status means error */
		if (buf[1] == 0)
			buf[1] = 1;	/* -256, etc. would screw up protocol */
	}
	else
	{
		if (cmptr == NULL && (cmptr = sm_malloc(CONTROLLEN)) == NULL)
			return sm_error_temp(SM_EM_IO, ENOMEM);
		cmptr->cmsg_level  = SOL_SOCKET;
		cmptr->cmsg_type   = SCM_RIGHTS;
		cmptr->cmsg_len    = CONTROLLEN;
		msg.msg_control    = (caddr_t) cmptr;
		msg.msg_controllen = CONTROLLEN;
		*(int *)CMSG_DATA(cmptr) = fd;		/* the fd to pass */
		buf[1] = 0;		/* zero status means OK */
	}
	buf[0] = 0;			/* null byte flag to recv_fd() */

	errno = 0;
	r = sendmsg(clifd, &msg, 0);
	if (r != 2)
		return sm_error_perm(SM_EM_IO, errno);
	return(0);
}
#endif /* LIB44_FD */

#if LIBSUN_FD
#include <sys/types.h>
#include <sys/socket.h>		/* struct msghdr */
#include <sys/uio.h>		/* struct iovec */
#include <errno.h>
#include <stddef.h>

/* Pass a file descriptor to another process.
 * If fd<0, then -fd is sent back instead as the error status. */

int
send_fd(int clifd, int fd)
{
	struct iovec	iov[1];
	struct msghdr	msg;
	char		buf[2];	/* send_fd()/recv_fd() 2-byte protocol */

	iov[0].iov_base = buf;
	iov[0].iov_len  = 2;
	msg.msg_iov     = iov;
	msg.msg_iovlen  = 1;
	msg.msg_name    = NULL;
	msg.msg_namelen = 0;

	if (fd < 0)
	{
		msg.msg_accrights    = NULL;
		msg.msg_accrightslen = 0;
		buf[1] = -fd;	/* nonzero status means error */
		if (buf[1] == 0)
			buf[1] = 1;	/* -256, etc. would screw up protocol */
	}
	else
	{
		msg.msg_accrights    = (caddr_t) &fd;	/* addr of descriptor */
		msg.msg_accrightslen = sizeof(int);	/* pass 1 descriptor */
		buf[1] = 0;		/* zero status means OK */
	}
	buf[0] = 0;			/* null byte flag to recv_fd() */

	if (sendmsg(clifd, &msg, 0) != 2)
		return(-1);

	return(0);
}
#endif /* LIBSUN_FD */

#if LIBSYSV_FD
#include	<sys/types.h>
#include	<stropts.h>

/* Pass a file descriptor to another process.
 * If fd<0, then -fd is sent back instead as the error status. */

int
send_fd(int clifd, int fd)
{
	char	buf[2];		/* send_fd()/recv_fd() 2-byte protocol */

	buf[0] = 0;		/* null byte flag to recv_fd() */
	if (fd < 0)
	{
		buf[1] = -fd;	/* nonzero status means error */
		if (buf[1] == 0)
			buf[1] = 1;	/* -256, etc. would screw up protocol */
	}
	else
	{
		buf[1] = 0;		/* zero status means OK */
	}

	if (write(clifd, buf, 2) != 2)
		return(-1);

	if (fd >= 0)
		if (ioctl(clifd, I_SENDFD, fd) < 0)
			return(-1);
	return(0);
}
#endif /* LIBSYSV_FD */



syntax highlighted by Code2HTML, v. 0.9.1