filter_fork.c revision 228753
11556Srgrimes/*- 21556Srgrimes * Copyright (c) 2007 Joerg Sonnenberger 31556Srgrimes * All rights reserved. 41556Srgrimes * 51556Srgrimes * Redistribution and use in source and binary forms, with or without 61556Srgrimes * modification, are permitted provided that the following conditions 71556Srgrimes * are met: 81556Srgrimes * 1. Redistributions of source code must retain the above copyright 91556Srgrimes * notice, this list of conditions and the following disclaimer. 101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111556Srgrimes * notice, this list of conditions and the following disclaimer in the 121556Srgrimes * documentation and/or other materials provided with the distribution. 131556Srgrimes * 141556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 151556Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 161556Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 171556Srgrimes * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 181556Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 191556Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 201556Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 211556Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 221556Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 231556Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 241556Srgrimes */ 251556Srgrimes 261556Srgrimes#include "archive_platform.h" 271556Srgrimes 281556Srgrimes/* This capability is only available on POSIX systems. */ 291556Srgrimes#if defined(HAVE_PIPE) && defined(HAVE_FCNTL) && \ 301556Srgrimes (defined(HAVE_FORK) || defined(HAVE_VFORK)) 311556Srgrimes 321556Srgrimes__FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00Z kientzle $"); 331556Srgrimes 341556Srgrimes#if defined(HAVE_POLL) && (defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)) 351556Srgrimes# if defined(HAVE_POLL_H) 3617987Speter# include <poll.h> 3750471Speter# elif defined(HAVE_SYS_POLL_H) 381556Srgrimes# include <sys/poll.h> 391556Srgrimes# endif 401556Srgrimes#elif defined(HAVE_SELECT) 411556Srgrimes# if defined(HAVE_SYS_SELECT_H) 421556Srgrimes# include <sys/select.h> 431556Srgrimes# elif defined(HAVE_UNISTD_H) 441556Srgrimes# include <unistd.h> 451556Srgrimes# endif 461556Srgrimes#endif 471556Srgrimes#ifdef HAVE_FCNTL_H 481556Srgrimes# include <fcntl.h> 491556Srgrimes#endif 501556Srgrimes#ifdef HAVE_UNISTD_H 511556Srgrimes# include <unistd.h> 521556Srgrimes#endif 5346684Skris 541556Srgrimes#include "filter_fork.h" 551556Srgrimes 561556Srgrimespid_t 571556Srgrimes__archive_create_child(const char *path, int *child_stdin, int *child_stdout) 581556Srgrimes{ 591556Srgrimes pid_t child; 6038521Scracauer int stdin_pipe[2], stdout_pipe[2], tmp; 611556Srgrimes 621556Srgrimes if (pipe(stdin_pipe) == -1) 631556Srgrimes goto state_allocated; 641556Srgrimes if (stdin_pipe[0] == 1 /* stdout */) { 651556Srgrimes if ((tmp = dup(stdin_pipe[0])) == -1) 661556Srgrimes goto stdin_opened; 6738530Scracauer close(stdin_pipe[0]); 681556Srgrimes stdin_pipe[0] = tmp; 691556Srgrimes } 701556Srgrimes if (pipe(stdout_pipe) == -1) 711556Srgrimes goto stdin_opened; 721556Srgrimes if (stdout_pipe[1] == 0 /* stdin */) { 7320425Ssteve if ((tmp = dup(stdout_pipe[1])) == -1) 741556Srgrimes goto stdout_opened; 751556Srgrimes close(stdout_pipe[1]); 761556Srgrimes stdout_pipe[1] = tmp; 771556Srgrimes } 781556Srgrimes 791556Srgrimes#if HAVE_VFORK 801556Srgrimes switch ((child = vfork())) { 811556Srgrimes#else 821556Srgrimes switch ((child = fork())) { 8338521Scracauer#endif 8438521Scracauer case -1: 851556Srgrimes goto stdout_opened; 861556Srgrimes case 0: 871556Srgrimes close(stdin_pipe[1]); 8817987Speter close(stdout_pipe[0]); 891556Srgrimes if (dup2(stdin_pipe[0], 0 /* stdin */) == -1) 901556Srgrimes _exit(254); 911556Srgrimes if (stdin_pipe[0] != 0 /* stdin */) 921556Srgrimes close(stdin_pipe[0]); 9317987Speter if (dup2(stdout_pipe[1], 1 /* stdout */) == -1) 9417987Speter _exit(254); 9517987Speter if (stdout_pipe[1] != 1 /* stdout */) 9620425Ssteve close(stdout_pipe[1]); 9717987Speter execlp(path, path, (char *)NULL); 981556Srgrimes _exit(254); 991556Srgrimes default: 1001556Srgrimes close(stdin_pipe[0]); 1011556Srgrimes close(stdout_pipe[1]); 1021556Srgrimes 1031556Srgrimes *child_stdin = stdin_pipe[1]; 1041556Srgrimes fcntl(*child_stdin, F_SETFL, O_NONBLOCK); 1051556Srgrimes *child_stdout = stdout_pipe[0]; 1061556Srgrimes fcntl(*child_stdout, F_SETFL, O_NONBLOCK); 1071556Srgrimes } 1081556Srgrimes 109 return child; 110 111stdout_opened: 112 close(stdout_pipe[0]); 113 close(stdout_pipe[1]); 114stdin_opened: 115 close(stdin_pipe[0]); 116 close(stdin_pipe[1]); 117state_allocated: 118 return -1; 119} 120 121void 122__archive_check_child(int in, int out) 123{ 124#if defined(HAVE_POLL) && (defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)) 125 struct pollfd fds[2]; 126 int idx; 127 128 idx = 0; 129 if (in != -1) { 130 fds[idx].fd = in; 131 fds[idx].events = POLLOUT; 132 ++idx; 133 } 134 if (out != -1) { 135 fds[idx].fd = out; 136 fds[idx].events = POLLIN; 137 ++idx; 138 } 139 140 poll(fds, idx, -1); /* -1 == INFTIM, wait forever */ 141#elif defined(HAVE_SELECT) 142 fd_set fds_in, fds_out, fds_error; 143 144 FD_ZERO(&fds_in); 145 FD_ZERO(&fds_out); 146 FD_ZERO(&fds_error); 147 if (out != -1) { 148 FD_SET(out, &fds_in); 149 FD_SET(out, &fds_error); 150 } 151 if (in != -1) { 152 FD_SET(in, &fds_out); 153 FD_SET(in, &fds_error); 154 } 155 select(in < out ? out + 1 : in + 1, &fds_in, &fds_out, &fds_error, NULL); 156#else 157 sleep(1); 158#endif 159} 160 161#endif /* defined(HAVE_PIPE) && defined(HAVE_VFORK) && defined(HAVE_FCNTL) */ 162