fdrecv.c (1376B)
1 #include <errno.h> 2 #include <fcntl.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; 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 36 while(fd < 0) { 37 wait_readable(socket_fd); 38 fd = ancil_recv_fd(socket_fd, 42); 39 if(fd < 0 && errno != EAGAIN) { 40 strerr_dief1sys(111, "recvmsg()"); 41 } 42 } 43 44 /* disable close-on-exec flag if present on fd */ 45 if(fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, NULL) & ~FD_CLOEXEC) == -1) { 46 strerr_dief1sys(111, "fcntl() disabling FD_CLOEXEC"); 47 } 48 49 size_t env_size = strlen(argv[2]) + uint_fmt(0, fd) + 2; 50 char envstr[env_size]; 51 char *p = stpncpy(envstr, argv[2], env_size); 52 *p++ = '='; 53 uint_fmt(p, fd); 54 xmexec_n(argv+3, envstr, env_size-1, 1); 55 }