#include "defs.h"

Prototype int SendMsg(int to_fd, int send_fd, DnsRes *dres);
Prototype int RecvMsg(int from_fd, int *recv_fd, DnsRes *dres);

int
SendMsg(int to_fd, int send_fd, DnsRes *dres)
{
    struct msghdr msg;
    struct iovec iov;
    struct {
#if FDPASS_USES_CMSG
	struct cmsghdr cmsg;
#endif
	int fd;
    } cmsg;
    int res = 0;
    int cmsgsize;
    int sent = 0;
         
    bzero(&msg, sizeof(msg));
    bzero(&cmsg, sizeof(cmsg));

    iov.iov_base = (void *)dres;
    iov.iov_len = sizeof(DnsRes);
                
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    if (send_fd >= 0) {
	cmsgsize = sizeof(cmsg);
    } else {
#if FDPASS_USES_CMSG
	cmsgsize = sizeof(struct cmsghdr);
#else
	cmsgsize = 0;
#endif
    }
#if FDPASS_USES_ACC
    msg.msg_accrights = (caddr_t)&cmsg;
    msg.msg_accrightslen = cmsgsize;
#else
    msg.msg_control = (caddr_t)&cmsg;
    msg.msg_controllen = cmsgsize;
#endif
#if FDPASS_USES_CMSG
    msg.msg_flags = 0;
    cmsg.cmsg.cmsg_len = cmsgsize;
    cmsg.cmsg.cmsg_level = SOL_SOCKET;
    cmsg.cmsg.cmsg_type = SCM_RIGHTS;
#endif 
    cmsg.fd = send_fd;

    errno = 0;
        
    /*
     * If we do not turn off nagle, lots of little 'group' transactions
     * can result in major delays even if nagle only kicks in on a few
     * of them.
     */
        
#ifdef TCP_NODELAY
    /*
     * Turn on TCP_NODELAY
     */
    if (send_fd >= 0) {
	int one = 1;
	setsockopt(send_fd, IPPROTO_TCP, TCP_NODELAY, (void *)&one, sizeof(one));
    }
#endif
     
    /*
     * Send the message.  This should never fail.  If it does, try to core
     * the reader subprocess.  Certainly kill it.
     */
        
    if (DebugOpt)
	printf("SendMsg() pid= %d fd=%d size=%d\n", (int)getpid(), cmsg.fd, sizeof(DnsRes));
    while (!sent) {
	res = sendmsg(to_fd, &msg, 0);
	sent = 1;
	if (res < 0) {
	    if (errno == EAGAIN)
		sent = 0;
	    else
		logit(LOG_ERR, "sendmsg error (%s)", strerror(errno));
	}
    }
    return(res);
}

int
RecvMsg(int from_fd, int *recv_fd, DnsRes *dres)
{
    int result = 0;
    struct msghdr msg;
    struct iovec  iov;
    struct {
#if FDPASS_USES_CMSG
	struct cmsghdr cmsg;
#endif
	int fd;
    } cmsg;
  
    bzero(&msg, sizeof(msg));
  
    iov.iov_base = (void *)dres;
    iov.iov_len = sizeof(DnsRes);
 
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
#if FDPASS_USES_ACC
    msg.msg_accrights = (caddr_t)&cmsg;
    msg.msg_accrightslen = sizeof(cmsg);
#else
    msg.msg_control = (caddr_t)&cmsg;
    msg.msg_controllen = sizeof(cmsg);
#endif
#if FDPASS_USES_CMSG
    msg.msg_flags = 0;
    cmsg.cmsg.cmsg_len = sizeof(cmsg);
#endif
    cmsg.fd = -1;
    errno = 0;

    /*
     * receive message w/ file descriptor   
     */

    result = recvmsg(from_fd, &msg, MSG_EOR|MSG_WAITALL);
    if (result >= 0 || errno == EAGAIN) {
	*recv_fd = cmsg.fd;
	if (DebugOpt && errno != EAGAIN)
	    printf("RecvMsg() pid=%d fd=%d size=%d\n",
					(int)getpid(), cmsg.fd, result);
    } else {
	logit(LOG_ERR, "recvmsg error (%s)", strerror(errno));
    }
    return(result);
}


syntax highlighted by Code2HTML, v. 0.9.1