File indexing completed on 2024-04-28 05:46:49

0001 /*****************************************************************************
0002  *   Copyright 2014 - 2015 Yichao Yu <yyc1992@gmail.com>                     *
0003  *                                                                           *
0004  *   This program is free software; you can redistribute it and/or modify    *
0005  *   it under the terms of the GNU Lesser General Public License as          *
0006  *   published by the Free Software Foundation; either version 2.1 of the    *
0007  *   License, or (at your option) version 3, or any later version accepted   *
0008  *   by the membership of KDE e.V. (or its successor approved by the         *
0009  *   membership of KDE e.V.), which shall act as a proxy defined in          *
0010  *   Section 6 of version 3 of the license.                                  *
0011  *                                                                           *
0012  *   This program is distributed in the hope that it will be useful,         *
0013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of          *
0014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       *
0015  *   Lesser General Public License for more details.                         *
0016  *                                                                           *
0017  *   You should have received a copy of the GNU Lesser General Public        *
0018  *   License along with this library. If not,                                *
0019  *   see <http://www.gnu.org/licenses/>.                                     *
0020  *****************************************************************************/
0021 
0022 #include "fd_utils.h"
0023 #include <sys/socket.h>
0024 #include <fcntl.h>
0025 
0026 QTC_EXPORT bool
0027 qtcSendFD(int sock, int fd)
0028 {
0029     QTC_RET_IF_FAIL(fd >= 0 && sock >= 0, false);
0030     char buf = 0;
0031     iovec iov;
0032     iov.iov_base = &buf;
0033     iov.iov_len = 1;
0034     union {
0035         struct cmsghdr cmsghdr;
0036         char control[CMSG_SPACE(sizeof(int))];
0037     } cmsgu;
0038     memset(&cmsgu, 0, sizeof(cmsgu));
0039     msghdr msg;
0040     msg.msg_iov = &iov;
0041     msg.msg_iovlen = 1;
0042     msg.msg_control = cmsgu.control;
0043     msg.msg_controllen = sizeof(cmsgu.control);
0044     cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
0045     cmsg->cmsg_len = CMSG_LEN(sizeof(int));
0046     cmsg->cmsg_level = SOL_SOCKET;
0047     cmsg->cmsg_type = SCM_RIGHTS;
0048     memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
0049     return sendmsg(sock, &msg, 0) >= 0;
0050 }
0051 
0052 QTC_EXPORT int
0053 qtcRecvFD(int sock)
0054 {
0055     QTC_RET_IF_FAIL(sock >= 0, -1);
0056     char buf = 0;
0057     iovec iov;
0058     iov.iov_base = &buf;
0059     iov.iov_len = 1;
0060     union {
0061         struct cmsghdr cmsghdr;
0062         char control[CMSG_SPACE(sizeof(int))];
0063     } cmsgu;
0064     memset(&cmsgu, 0, sizeof(cmsgu));
0065     msghdr msg;
0066     msg.msg_iov = &iov;
0067     msg.msg_iovlen = 1;
0068     msg.msg_control = cmsgu.control;
0069     msg.msg_controllen = sizeof(cmsgu.control);
0070     QTC_RET_IF_FAIL(recvmsg(sock, &msg, 0) >= 0, -1);
0071     struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
0072     QTC_RET_IF_FAIL(cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int)) &&
0073                     cmsg->cmsg_level == SOL_SOCKET &&
0074                     cmsg->cmsg_type == SCM_RIGHTS, -1);
0075     int fd;
0076     memcpy(&fd, CMSG_DATA(cmsg), sizeof(int));
0077     return fd;
0078 }
0079 
0080 QTC_EXPORT bool
0081 qtcFDSetCloexec(int fd, bool cloexec)
0082 {
0083     long flags;
0084     flags = fcntl(fd, F_GETFD, 0);
0085     if (flags == -1) {
0086         return false;
0087     }
0088     if (cloexec) {
0089         flags |= FD_CLOEXEC;
0090     } else {
0091         flags &= ~FD_CLOEXEC;
0092     }
0093     return fcntl(fd, F_SETFD, flags) != -1;
0094 }
0095 
0096 QTC_EXPORT bool
0097 qtcFDSetNonBlock(int fd, bool nonblock)
0098 {
0099     long flags;
0100     flags = fcntl(fd, F_GETFL, 0);
0101     if (flags == -1) {
0102         return false;
0103     }
0104     if (nonblock) {
0105         nonblock |= O_NONBLOCK;
0106     } else {
0107         nonblock &= ~O_NONBLOCK;
0108     }
0109     return fcntl(fd, F_SETFL, flags) != -1;
0110 }