/* code lifted from Stevens' APUE */
#include <errno.h> /* for definition of errno */
#include <stdarg.h> /* ANSI C header file */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <string.h>
#include <unistd.h>
#include "pass_fd.h"
#if VARIANT_SVR4
int
s_pipe(int fd[2])
{
return( pipe(fd) );
}
#elif defined(VARIANT_43BSD) || defined(VARIANT_44BSD)
int
s_pipe(int fd[2])
{
return( socketpair(AF_UNIX, SOCK_STREAM, 0, fd) );
}
#else
#error "Couldn't guess variant"
#endif
#if VARIANT_43BSD
int
send_fd(int clifd, int fd)
{
struct iovec iov[1];
struct msghdr msg;
char buf[2];
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;
if (buf[1] == 0)
buf[1] = 1;
}
else {
msg.msg_accrights = (caddr_t) &fd;
msg.msg_accrightslen = sizeof(int);
buf[1] = 0;
}
buf[0] = 0;
if (sendmsg(clifd, &msg, 0) != 2)
return(-1);
return(0);
}
int
recv_fd(int servfd)
{
int newfd, nread, status;
char *ptr, buf[2];
struct iovec iov[1];
struct msghdr msg;
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;
msg.msg_accrights = (caddr_t) &newfd;
msg.msg_accrightslen = sizeof(int);
if ( (nread = recvmsg(servfd, &msg, 0)) <= 0)
return(-1);
return(newfd);/* descriptor, or -status */
}
#else
/* based on code from Postfix 2.3.3 (vk) */
union {
struct cmsghdr just_for_alignment;
char control[CMSG_SPACE(sizeof(int))];
} control_un;
int
send_fd(int over, int sendfd)
{
struct iovec iov[1];
struct msghdr msg;
struct cmsghdr *cmptr;
memset((char *) &msg, 0, sizeof(msg));
msg.msg_control = control_un.control;
msg.msg_controllen = CMSG_LEN(sizeof(sendfd));
cmptr = CMSG_FIRSTHDR(&msg);
cmptr->cmsg_len = CMSG_LEN(sizeof(sendfd));
cmptr->cmsg_level = SOL_SOCKET;
cmptr->cmsg_type = SCM_RIGHTS;
*(int *) CMSG_DATA(cmptr) = sendfd;
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov[0].iov_base = "";
iov[0].iov_len = 1;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
if (sendmsg(over, &msg, 0) < 0)
return -1;
return 0;
}
int
recv_fd(int over)
{
struct msghdr msg;
struct iovec iov[1];
char buf[1];
struct cmsghdr *cmptr;
memset((char *) &msg, 0, sizeof(msg));
msg.msg_control = control_un.control;
msg.msg_controllen = CMSG_LEN(sizeof(int));
msg.msg_name = 0;
msg.msg_namelen = 0;
iov[0].iov_base = buf;
iov[0].iov_len = sizeof(buf);
msg.msg_iov = iov;
msg.msg_iovlen = 1;
if (recvmsg(over, &msg, 0) < 0)
return (-1);
if ((cmptr = CMSG_FIRSTHDR(&msg)) != 0
&& cmptr->cmsg_len == CMSG_LEN(sizeof(int))) {
if (cmptr->cmsg_level != SOL_SOCKET || cmptr->cmsg_type != SCM_RIGHTS)
return(-1); /* error */
return (*(int *) CMSG_DATA(cmptr)); /* the file handle */
} else
return (-1);
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1