filter_fork.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*-
  2. * Copyright (c) 2007 Joerg Sonnenberger
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  15. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  16. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  17. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  18. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  19. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  20. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  21. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  22. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  23. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  24. */
  25. #include "archive_platform.h"
  26. /* This capability is only available on POSIX systems. */
  27. #if defined(HAVE_PIPE) && defined(HAVE_FCNTL) && \
  28. (defined(HAVE_FORK) || defined(HAVE_VFORK))
  29. __FBSDID("$FreeBSD: src/lib/libarchive/filter_fork.c,v 1.5 2008/09/12 05:33:00 kientzle Exp $");
  30. #if defined(HAVE_POLL)
  31. # if defined(HAVE_POLL_H)
  32. # include <poll.h>
  33. # elif defined(HAVE_SYS_POLL_H)
  34. # include <sys/poll.h>
  35. # endif
  36. #elif defined(HAVE_SELECT)
  37. # if defined(HAVE_SYS_SELECT_H)
  38. # include <sys/select.h>
  39. # elif defined(HAVE_UNISTD_H)
  40. # include <unistd.h>
  41. # endif
  42. #endif
  43. #ifdef HAVE_FCNTL_H
  44. # include <fcntl.h>
  45. #endif
  46. #ifdef HAVE_UNISTD_H
  47. # include <unistd.h>
  48. #endif
  49. #include "filter_fork.h"
  50. pid_t
  51. __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
  52. {
  53. pid_t child;
  54. int stdin_pipe[2], stdout_pipe[2], tmp;
  55. if (pipe(stdin_pipe) == -1)
  56. goto state_allocated;
  57. if (stdin_pipe[0] == 1 /* stdout */) {
  58. if ((tmp = dup(stdin_pipe[0])) == -1)
  59. goto stdin_opened;
  60. close(stdin_pipe[0]);
  61. stdin_pipe[0] = tmp;
  62. }
  63. if (pipe(stdout_pipe) == -1)
  64. goto stdin_opened;
  65. if (stdout_pipe[1] == 0 /* stdin */) {
  66. if ((tmp = dup(stdout_pipe[1])) == -1)
  67. goto stdout_opened;
  68. close(stdout_pipe[1]);
  69. stdout_pipe[1] = tmp;
  70. }
  71. #if HAVE_VFORK
  72. switch ((child = vfork())) {
  73. #else
  74. switch ((child = fork())) {
  75. #endif
  76. case -1:
  77. goto stdout_opened;
  78. case 0:
  79. close(stdin_pipe[1]);
  80. close(stdout_pipe[0]);
  81. if (dup2(stdin_pipe[0], 0 /* stdin */) == -1)
  82. _exit(254);
  83. if (stdin_pipe[0] != 0 /* stdin */)
  84. close(stdin_pipe[0]);
  85. if (dup2(stdout_pipe[1], 1 /* stdout */) == -1)
  86. _exit(254);
  87. if (stdout_pipe[1] != 1 /* stdout */)
  88. close(stdout_pipe[1]);
  89. execlp(path, path, (char *)NULL);
  90. _exit(254);
  91. default:
  92. close(stdin_pipe[0]);
  93. close(stdout_pipe[1]);
  94. *child_stdin = stdin_pipe[1];
  95. fcntl(*child_stdin, F_SETFL, O_NONBLOCK);
  96. *child_stdout = stdout_pipe[0];
  97. fcntl(*child_stdout, F_SETFL, O_NONBLOCK);
  98. }
  99. return child;
  100. stdout_opened:
  101. close(stdout_pipe[0]);
  102. close(stdout_pipe[1]);
  103. stdin_opened:
  104. close(stdin_pipe[0]);
  105. close(stdin_pipe[1]);
  106. state_allocated:
  107. return -1;
  108. }
  109. void
  110. __archive_check_child(int in, int out)
  111. {
  112. #if defined(HAVE_POLL)
  113. struct pollfd fds[2];
  114. int idx;
  115. idx = 0;
  116. if (in != -1) {
  117. fds[idx].fd = in;
  118. fds[idx].events = POLLOUT;
  119. ++idx;
  120. }
  121. if (out != -1) {
  122. fds[idx].fd = out;
  123. fds[idx].events = POLLIN;
  124. ++idx;
  125. }
  126. poll(fds, idx, -1); /* -1 == INFTIM, wait forever */
  127. #elif defined(HAVE_SELECT)
  128. fd_set fds_in, fds_out, fds_error;
  129. FD_ZERO(&fds_in);
  130. FD_ZERO(&fds_out);
  131. FD_ZERO(&fds_error);
  132. if (out != -1) {
  133. FD_SET(out, &fds_in);
  134. FD_SET(out, &fds_error);
  135. }
  136. if (in != -1) {
  137. FD_SET(in, &fds_out);
  138. FD_SET(in, &fds_error);
  139. }
  140. select(in < out ? out + 1 : in + 1, &fds_in, &fds_out, &fds_error, NULL);
  141. #else
  142. sleep(1);
  143. #endif
  144. }
  145. #endif /* defined(HAVE_PIPE) && defined(HAVE_VFORK) && defined(HAVE_FCNTL) */