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  }