1228753Smm/*- 2228753Smm * Copyright (c) 2007 Joerg Sonnenberger 3228753Smm * All rights reserved. 4228753Smm * 5228753Smm * Redistribution and use in source and binary forms, with or without 6228753Smm * modification, are permitted provided that the following conditions 7228753Smm * are met: 8228753Smm * 1. Redistributions of source code must retain the above copyright 9228753Smm * notice, this list of conditions and the following disclaimer. 10228753Smm * 2. Redistributions in binary form must reproduce the above copyright 11228753Smm * notice, this list of conditions and the following disclaimer in the 12228753Smm * documentation and/or other materials provided with the distribution. 13228753Smm * 14228753Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15228753Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16228753Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17228753Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18228753Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19228753Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20228753Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21228753Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22228753Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23228753Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24228753Smm */ 25228753Smm 26228753Smm#include "archive_platform.h" 27228753Smm 28228753Smm/* This capability is only available on POSIX systems. */ 29228753Smm#if defined(HAVE_PIPE) && defined(HAVE_FCNTL) && \ 30228753Smm (defined(HAVE_FORK) || defined(HAVE_VFORK)) 31228753Smm 32229592Smm__FBSDID("$FreeBSD$"); 33228753Smm 34228753Smm#if defined(HAVE_POLL) && (defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)) 35228753Smm# if defined(HAVE_POLL_H) 36228753Smm# include <poll.h> 37228753Smm# elif defined(HAVE_SYS_POLL_H) 38228753Smm# include <sys/poll.h> 39228753Smm# endif 40228753Smm#elif defined(HAVE_SELECT) 41228753Smm# if defined(HAVE_SYS_SELECT_H) 42228753Smm# include <sys/select.h> 43228753Smm# elif defined(HAVE_UNISTD_H) 44228753Smm# include <unistd.h> 45228753Smm# endif 46228753Smm#endif 47228753Smm#ifdef HAVE_FCNTL_H 48228753Smm# include <fcntl.h> 49228753Smm#endif 50228753Smm#ifdef HAVE_UNISTD_H 51228753Smm# include <unistd.h> 52228753Smm#endif 53228753Smm 54228753Smm#include "filter_fork.h" 55228753Smm 56228753Smmpid_t 57228753Smm__archive_create_child(const char *path, int *child_stdin, int *child_stdout) 58228753Smm{ 59228753Smm pid_t child; 60228753Smm int stdin_pipe[2], stdout_pipe[2], tmp; 61228753Smm 62228753Smm if (pipe(stdin_pipe) == -1) 63228753Smm goto state_allocated; 64228753Smm if (stdin_pipe[0] == 1 /* stdout */) { 65228753Smm if ((tmp = dup(stdin_pipe[0])) == -1) 66228753Smm goto stdin_opened; 67228753Smm close(stdin_pipe[0]); 68228753Smm stdin_pipe[0] = tmp; 69228753Smm } 70228753Smm if (pipe(stdout_pipe) == -1) 71228753Smm goto stdin_opened; 72228753Smm if (stdout_pipe[1] == 0 /* stdin */) { 73228753Smm if ((tmp = dup(stdout_pipe[1])) == -1) 74228753Smm goto stdout_opened; 75228753Smm close(stdout_pipe[1]); 76228753Smm stdout_pipe[1] = tmp; 77228753Smm } 78228753Smm 79228753Smm#if HAVE_VFORK 80228753Smm switch ((child = vfork())) { 81228753Smm#else 82228753Smm switch ((child = fork())) { 83228753Smm#endif 84228753Smm case -1: 85228753Smm goto stdout_opened; 86228753Smm case 0: 87228753Smm close(stdin_pipe[1]); 88228753Smm close(stdout_pipe[0]); 89228753Smm if (dup2(stdin_pipe[0], 0 /* stdin */) == -1) 90228753Smm _exit(254); 91228753Smm if (stdin_pipe[0] != 0 /* stdin */) 92228753Smm close(stdin_pipe[0]); 93228753Smm if (dup2(stdout_pipe[1], 1 /* stdout */) == -1) 94228753Smm _exit(254); 95228753Smm if (stdout_pipe[1] != 1 /* stdout */) 96228753Smm close(stdout_pipe[1]); 97228753Smm execlp(path, path, (char *)NULL); 98228753Smm _exit(254); 99228753Smm default: 100228753Smm close(stdin_pipe[0]); 101228753Smm close(stdout_pipe[1]); 102228753Smm 103228753Smm *child_stdin = stdin_pipe[1]; 104228753Smm fcntl(*child_stdin, F_SETFL, O_NONBLOCK); 105228753Smm *child_stdout = stdout_pipe[0]; 106228753Smm fcntl(*child_stdout, F_SETFL, O_NONBLOCK); 107228753Smm } 108228753Smm 109228753Smm return child; 110228753Smm 111228753Smmstdout_opened: 112228753Smm close(stdout_pipe[0]); 113228753Smm close(stdout_pipe[1]); 114228753Smmstdin_opened: 115228753Smm close(stdin_pipe[0]); 116228753Smm close(stdin_pipe[1]); 117228753Smmstate_allocated: 118228753Smm return -1; 119228753Smm} 120228753Smm 121228753Smmvoid 122228753Smm__archive_check_child(int in, int out) 123228753Smm{ 124228753Smm#if defined(HAVE_POLL) && (defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H)) 125228753Smm struct pollfd fds[2]; 126228753Smm int idx; 127228753Smm 128228753Smm idx = 0; 129228753Smm if (in != -1) { 130228753Smm fds[idx].fd = in; 131228753Smm fds[idx].events = POLLOUT; 132228753Smm ++idx; 133228753Smm } 134228753Smm if (out != -1) { 135228753Smm fds[idx].fd = out; 136228753Smm fds[idx].events = POLLIN; 137228753Smm ++idx; 138228753Smm } 139228753Smm 140228753Smm poll(fds, idx, -1); /* -1 == INFTIM, wait forever */ 141228753Smm#elif defined(HAVE_SELECT) 142228753Smm fd_set fds_in, fds_out, fds_error; 143228753Smm 144228753Smm FD_ZERO(&fds_in); 145228753Smm FD_ZERO(&fds_out); 146228753Smm FD_ZERO(&fds_error); 147228753Smm if (out != -1) { 148228753Smm FD_SET(out, &fds_in); 149228753Smm FD_SET(out, &fds_error); 150228753Smm } 151228753Smm if (in != -1) { 152228753Smm FD_SET(in, &fds_out); 153228753Smm FD_SET(in, &fds_error); 154228753Smm } 155228753Smm select(in < out ? out + 1 : in + 1, &fds_in, &fds_out, &fds_error, NULL); 156228753Smm#else 157228753Smm sleep(1); 158228753Smm#endif 159228753Smm} 160228753Smm 161228753Smm#endif /* defined(HAVE_PIPE) && defined(HAVE_VFORK) && defined(HAVE_FCNTL) */ 162