/* * 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; }