github.com/schwarzm/garden-linux@v0.0.0-20150507151835-33bca2147c47/old/linux_backend/src/wsh/pump.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/select.h> 9 #include <unistd.h> 10 11 #include "pump.h" 12 #include "util.h" 13 14 void pump_init(pump_t *p) { 15 p->nfd = 0; 16 17 FD_ZERO(&p->rfds); 18 FD_ZERO(&p->wfds); 19 FD_ZERO(&p->efds); 20 } 21 22 void pump_pair_init(pump_pair_t *pp, pump_t *p, int rfd, int wfd) { 23 pp->p = p; 24 pp->rfd = rfd; 25 pp->wfd = wfd; 26 27 /* Both sides may refer to the same file description if they refer to a PTY, 28 * so configuring them differently may not have the desired effects. 29 * Therefore, simply configure both sides to be blocking. */ 30 fcntl_set_nonblock(rfd, 0); 31 fcntl_set_nonblock(wfd, 0); 32 } 33 34 void pump_pair_close(pump_pair_t *pp) { 35 close(pp->rfd); 36 pp->rfd = -1; 37 close(pp->wfd); 38 pp->wfd = -1; 39 } 40 41 int pump_add_fd(pump_t *p, int fd, int mode) { 42 if (fd < 0) { 43 return 0; 44 } 45 46 if (fd > p->nfd) { 47 p->nfd = fd; 48 } 49 50 if (mode & PUMP_READ) { 51 FD_SET(fd, &p->rfds); 52 } 53 54 if (mode & PUMP_WRITE) { 55 FD_SET(fd, &p->wfds); 56 } 57 58 if (mode & PUMP_EXCEPT) { 59 FD_SET(fd, &p->efds); 60 } 61 62 return 1; 63 } 64 65 int pump_add_pair(pump_t *p, pump_pair_t *pp) { 66 int j = 0; 67 68 j += pump_add_fd(p, pp->rfd, PUMP_READ | PUMP_EXCEPT); 69 j += pump_add_fd(p, pp->wfd, PUMP_WRITE | PUMP_EXCEPT); 70 71 return j; 72 } 73 74 int pump_ready(pump_t *p, int fd, int mode) { 75 int rv = 0; 76 77 if (mode & PUMP_READ) { 78 rv |= FD_ISSET(fd, &p->rfds); 79 } 80 81 if (mode & PUMP_WRITE) { 82 rv |= FD_ISSET(fd, &p->wfds); 83 } 84 85 if (mode & PUMP_EXCEPT) { 86 rv |= FD_ISSET(fd, &p->efds); 87 } 88 89 return rv; 90 } 91 92 int pump_select(pump_t *p) { 93 return select(FD_SETSIZE, &p->rfds, NULL, &p->efds, NULL); 94 } 95 96 int pump_pair_splice(pump_pair_t *pp) { 97 int rv; 98 99 if (!FD_ISSET(pp->rfd, &pp->p->rfds)) { 100 return 0; 101 } 102 103 if (!FD_ISSET(pp->wfd, &pp->p->wfds)) { 104 return 0; 105 } 106 107 rv = splice(pp->rfd, NULL, pp->wfd, NULL, 64 * 1024, SPLICE_F_NONBLOCK); 108 if (rv == -1) { 109 perror("splice"); 110 exit(1); 111 } else if (rv == 0) { 112 pump_pair_close(pp); 113 } 114 115 return rv; 116 } 117 118 int pump_pair_copy(pump_pair_t *pp) { 119 char buf[64 * 1024]; 120 char *ptr = buf; 121 int nr, nw; 122 123 if (!FD_ISSET(pp->rfd, &pp->p->rfds)) { 124 return 0; 125 } 126 127 do { 128 nr = read(pp->rfd, buf, sizeof(buf)); 129 } while (nr == -1 && errno == EINTR); 130 131 if (nr <= 0) { 132 pump_pair_close(pp); 133 return nr; 134 } 135 136 while (nr) { 137 do { 138 nw = write(pp->wfd, ptr, nr); 139 } while (nw == -1 && errno == EINTR); 140 141 if (nw <= 0) { 142 pump_pair_close(pp); 143 return nw; 144 } 145 146 ptr += nw; 147 nr -= nw; 148 } 149 150 return 0; 151 }