/*
* Copyright (c) 2002-2005 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include "sm/generic.h"
SM_RCSID("@(#)$Id: read_fd.c,v 1.13 2005/03/21 22:56:24 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/io.h"
#include "sm/varargs.h"
#include "sm/limits.h"
#include "sm/types.h"
#include "sm/socket.h" /* struct msghdr */
#include "sm/uio.h" /* struct iovec */
#include "sm/cmsg.h"
/*
** READ_FD -- read filedescriptor recvfd over open file fd and some data
**
** Parameters:
** fd -- fd to use for communication
** ptr -- buffer in which to store additional data
** nbytes -- size of buffer
** recvfd -- pointer to fd to receive (output)
**
** Returns:
** result of sendmsg()
*/
ssize_t
sm_read_fd(fd_T fd, void *ptr, size_t nbytes, int *recvfd)
{
struct msghdr msg;
struct iovec iov[1];
ssize_t n;
#if ! HAVE_MSGHDR_MSG_CONTROL
int newfd;
#endif
#if HAVE_MSGHDR_MSG_CONTROL
char control[CMSG_SPACE(sizeof(int))];
struct cmsghdr *cmptr;
msg.msg_control = (caddr_t)control;
msg.msg_controllen = CMSG_LEN(sizeof(int));
#else /* HAVE_MSGHDR_MSG_CONTROL */
msg.msg_accrights = (caddr_t) &newfd;
msg.msg_accrightslen = sizeof(int);
#endif /* HAVE_MSGHDR_MSG_CONTROL */
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov[0].iov_base = ptr;
iov[0].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
n = sm_recvmsg(fd, &msg, 0);
if (n <= 0)
return n;
#if HAVE_MSGHDR_MSG_CONTROL
if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL &&
cmptr->cmsg_len == CMSG_LEN(sizeof(int)))
{
if (cmptr->cmsg_level != SOL_SOCKET)
{
#if 0
// err_quit(smioerr, EX_SOFTWARE,
// "control level != SOL_SOCKET");
#endif
return -1;
}
if (cmptr->cmsg_type != SCM_RIGHTS)
{
#if 0
// err_quit(smioerr, EX_SOFTWARE,
// "control type != SCM_RIGHTS");
#endif
return -1;
}
*recvfd = *((int *) CMSG_DATA(cmptr));
} else
*recvfd = -1; /* descriptor was not passed */
#else /* HAVE_MSGHDR_MSG_CONTROL */
if (msg.msg_accrightslen == sizeof(int))
*recvfd = newfd;
else
*recvfd = -1; /* descriptor was not passed */
#endif /* HAVE_MSGHDR_MSG_CONTROL */
return n;
}
syntax highlighted by Code2HTML, v. 0.9.1