ccx-utils

Miscellaneous utilities written in C
git clone https://ccx.te2000.cz/git/ccx-utils
Log | Files | Refs

fdrecvto.c (1300B)


      1 #include <errno.h>
      2 #include <unistd.h>
      3 #include <sys/select.h>
      4 
      5 #include <skalibs/types.h>
      6 #include <skalibs/strerr.h>
      7 #include <skalibs/djbunix.h>
      8 #include <skalibs/exec.h>
      9 #include <skalibs/ancil.h>
     10 
     11 #define USAGE "fdrecv socket_fd fd_env_var prog..."
     12 #define PROG "fdrecv"
     13 
     14 void wait_readable(int fd) {
     15   fd_set rfds, xfds;
     16   int    retval = 0;
     17   FD_ZERO(&rfds);
     18   FD_ZERO(&xfds);
     19   while(retval < 1) {
     20     FD_SET(fd, &rfds);
     21     FD_SET(fd, &xfds);
     22     retval = select(fd+1, &rfds, NULL, &xfds, NULL);
     23     if (retval == -1 && errno != EINTR) {
     24       strerr_dief1sys(111, "select()");
     25     }
     26   }
     27 }
     28 
     29 int main (int argc, char const *const *argv)
     30 {
     31   unsigned int socket_fd, target_fd;
     32   int fd = -1;
     33   if ((argc < 4)) strerr_dieusage(100, USAGE) ;
     34   if (!uint0_scan(argv[1], &socket_fd)) strerr_dieusage(100, USAGE) ;
     35   if (!uint0_scan(argv[2], &target_fd)) strerr_dieusage(100, USAGE) ;
     36 
     37   while(fd < 0) {
     38     wait_readable(socket_fd);
     39     fd = ancil_recv_fd(socket_fd, 42);
     40     if(fd < 0 && errno != EAGAIN) {
     41 	strerr_dief1sys(111, "recvmsg()");
     42     }
     43   }
     44   if(fd == target_fd) {
     45     int tmp_fd = dup(fd);
     46     if(tmp_fd < 0) {
     47       strerr_dief1sys(111, "dup()");
     48     }
     49     close(fd);
     50     fd = tmp_fd;
     51   }
     52   if(dup2(fd, target_fd) < 0) {
     53     strerr_dief1sys(111, "dup2()");
     54   }
     55 
     56   xexec(argv+3) ;
     57 }