github.com/schwarzm/garden-linux@v0.0.0-20150507151835-33bca2147c47/old/linux_backend/src/wsh/un.c (about)

     1  #define _GNU_SOURCE
     2  
     3  #include <assert.h>
     4  #include <errno.h>
     5  #include <fcntl.h>
     6  #include <stdio.h>
     7  #include <stdlib.h>
     8  #include <sys/socket.h>
     9  #include <sys/un.h>
    10  #include <unistd.h>
    11  
    12  #include "un.h"
    13  
    14  int un__socket() {
    15    int fd;
    16  
    17    if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
    18      perror("socket");
    19      exit(1);
    20    }
    21  
    22    return fd;
    23  }
    24  
    25  int un_listen(const char *path) {
    26    int fd;
    27    struct sockaddr_un sa;
    28  
    29    fd = un__socket();
    30  
    31    sa.sun_family = AF_UNIX;
    32    assert(strlen(path) < sizeof(sa.sun_path));
    33    strcpy(sa.sun_path, path);
    34    unlink(sa.sun_path);
    35  
    36    if (bind(fd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
    37      perror("bind");
    38      exit(1);
    39    }
    40  
    41    if (listen(fd, 5) == -1) {
    42      perror("listen");
    43      exit(1);
    44    }
    45  
    46    return fd;
    47  }
    48  
    49  int un_connect(const char *path) {
    50    int fd;
    51    struct sockaddr_un sa;
    52    int rv;
    53  
    54    fd = un__socket();
    55  
    56    sa.sun_family = AF_UNIX;
    57    assert(strlen(path) < sizeof(sa.sun_path));
    58    strcpy(sa.sun_path, path);
    59  
    60    rv = connect(fd, (struct sockaddr *)&sa, sizeof(sa));
    61    if (rv == -1) {
    62      close(fd);
    63      return rv;
    64    }
    65  
    66    return fd;
    67  }
    68  
    69  int un_send_fds(int fd, char *data, int datalen, int *fds, int fdslen) {
    70    struct msghdr mh;
    71    struct cmsghdr *cmh = NULL;
    72    char buf[2048];
    73    size_t buflen = CMSG_SPACE(sizeof(int) * fdslen);
    74    struct iovec iov[1];
    75  
    76    assert(sizeof(buf) >= buflen);
    77  
    78    memset(&mh, 0, sizeof(mh));
    79  
    80    mh.msg_control = buf;
    81    mh.msg_controllen = buflen;
    82    mh.msg_iov = iov;
    83    mh.msg_iovlen = 1;
    84    iov[0].iov_base = data;
    85    iov[0].iov_len = datalen;
    86  
    87    cmh = CMSG_FIRSTHDR(&mh);
    88    cmh->cmsg_level = SOL_SOCKET;
    89    cmh->cmsg_type = SCM_RIGHTS;
    90    cmh->cmsg_len = CMSG_LEN(sizeof(int) * fdslen);
    91    memcpy(CMSG_DATA(cmh), fds, sizeof(int) * fdslen);
    92    mh.msg_controllen = cmh->cmsg_len;
    93  
    94    int rv;
    95  
    96    do {
    97      rv = sendmsg(fd, &mh, 0);
    98    } while (rv == -1 && errno == EINTR);
    99  
   100    return rv;
   101  }
   102  
   103  int un_recv_fds(int fd, char *data, int datalen, int *fds, int fdslen) {
   104    struct msghdr mh;
   105    struct cmsghdr *cmh = NULL;
   106    char buf[2048];
   107    size_t buflen = CMSG_SPACE(sizeof(int) * fdslen);
   108    struct iovec iov[1];
   109  
   110    assert(sizeof(buf) >= buflen);
   111  
   112    memset(&mh, 0, sizeof(mh));
   113  
   114    mh.msg_control = buf;
   115    mh.msg_controllen = buflen;
   116    mh.msg_iov = iov;
   117    mh.msg_iovlen = 1;
   118    iov[0].iov_base = data;
   119    iov[0].iov_len = datalen;
   120  
   121    int rv = -1;
   122    errno = 0;
   123  
   124    do {
   125      rv = recvmsg(fd, &mh, 0);
   126    } while (rv == -1 && (errno == EINTR || errno == EAGAIN));
   127  
   128    if (rv <= 0) {
   129      goto done;
   130    }
   131  
   132    if (fds != NULL) {
   133      cmh = CMSG_FIRSTHDR(&mh);
   134      assert(cmh != NULL);
   135      assert(cmh->cmsg_level == SOL_SOCKET);
   136      assert(cmh->cmsg_type == SCM_RIGHTS);
   137      assert(cmh->cmsg_len == CMSG_LEN(sizeof(int) * fdslen));
   138  
   139      int *fds_ = (int *)CMSG_DATA(cmh);
   140      int i;
   141  
   142      for (i = 0; i < fdslen; i++) {
   143        fds[i] = fds_[i];
   144      }
   145    }
   146  
   147    while (rv < datalen) {
   148      int temp_rv = recv(fd, data + rv, (datalen - rv), MSG_WAITALL);
   149      if (temp_rv <= 0) {
   150        goto done;
   151      }
   152  
   153      rv += temp_rv;
   154    }
   155  
   156  done:
   157    return rv;
   158  }