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 }