Move an series of fd pointers into 0, 1, ... */
| 70 | |
| 71 | /* Move an series of fd pointers into 0, 1, ... */ |
| 72 | static bool shuffle_fds(int **fds, size_t num_fds) |
| 73 | { |
| 74 | /* If we need to move an fd out the way, this is a good place to start |
| 75 | * looking */ |
| 76 | size_t next_free_fd = num_fds; |
| 77 | for (size_t i = 0; i < num_fds; i++) { |
| 78 | int in_the_way; |
| 79 | |
| 80 | /* Already in the right place? Great! */ |
| 81 | if (*fds[i] == i) |
| 82 | continue; |
| 83 | /* Is something we care about in the way? */ |
| 84 | in_the_way = fd_used(fds + i, num_fds - i, i); |
| 85 | if (in_the_way != -1) { |
| 86 | /* Find a high-numbered unused fd. */ |
| 87 | while (fd_used(fds + i, num_fds - i, next_free_fd) != -1) |
| 88 | next_free_fd++; |
| 89 | /* Trick: in_the_way is offset by i! */ |
| 90 | if (!move_fd(fds[i + in_the_way], next_free_fd)) |
| 91 | return false; |
| 92 | next_free_fd++; |
| 93 | } |
| 94 | |
| 95 | /* Now there should be nothing in the way. */ |
| 96 | assert(fd_used(fds, num_fds, i) == -1); |
| 97 | if (!move_fd(fds[i], i)) |
| 98 | return false; |
| 99 | } |
| 100 | return true; |
| 101 | } |
| 102 | |
| 103 | struct subd_req { |
| 104 | struct list_node list; |