1/* fork.c - fork and exec a process, connecting stdin/out w/pipes */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 1998-2011 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16/* Portions Copyright (c) 1995 Regents of the University of Michigan. 17 * All rights reserved. 18 * 19 * Redistribution and use in source and binary forms are permitted 20 * provided that this notice is preserved and that due credit is given 21 * to the University of Michigan at Ann Arbor. The name of the University 22 * may not be used to endorse or promote products derived from this 23 * software without specific prior written permission. This software 24 * is provided ``as is'' without express or implied warranty. 25 */ 26/* ACKNOWLEDGEMENTS: 27 * This work was originally developed by the University of Michigan 28 * (as part of U-MICH LDAP). 29 */ 30 31#include "portable.h" 32 33#include <stdio.h> 34 35#include <ac/errno.h> 36#include <ac/string.h> 37#include <ac/socket.h> 38#include <ac/unistd.h> 39 40#include "slap.h" 41#include "shell.h" 42 43pid_t 44forkandexec( 45 char **args, 46 FILE **rfp, 47 FILE **wfp 48) 49{ 50 int p2c[2] = { -1, -1 }, c2p[2]; 51 pid_t pid; 52 53 if ( pipe( p2c ) != 0 || pipe( c2p ) != 0 ) { 54 Debug( LDAP_DEBUG_ANY, "pipe failed\n", 0, 0, 0 ); 55 close( p2c[0] ); 56 close( p2c[1] ); 57 return( -1 ); 58 } 59 60 /* 61 * what we're trying to set up looks like this: 62 * parent *wfp -> p2c[1] | p2c[0] -> stdin child 63 * parent *rfp <- c2p[0] | c2p[1] <- stdout child 64 */ 65 66 fflush( NULL ); 67# ifdef HAVE_THR 68 pid = fork1(); 69# else 70 pid = fork(); 71# endif 72 if ( pid == 0 ) { /* child */ 73 /* 74 * child could deadlock here due to resources locked 75 * by our parent 76 * 77 * If so, configure --without-threads. 78 */ 79 if ( dup2( p2c[0], 0 ) == -1 || dup2( c2p[1], 1 ) == -1 ) { 80 Debug( LDAP_DEBUG_ANY, "dup2 failed\n", 0, 0, 0 ); 81 exit( EXIT_FAILURE ); 82 } 83 } 84 close( p2c[0] ); 85 close( c2p[1] ); 86 if ( pid <= 0 ) { 87 close( p2c[1] ); 88 close( c2p[0] ); 89 } 90 switch ( pid ) { 91 case 0: 92 execv( args[0], args ); 93 94 Debug( LDAP_DEBUG_ANY, "execv failed\n", 0, 0, 0 ); 95 exit( EXIT_FAILURE ); 96 97 case -1: /* trouble */ 98 Debug( LDAP_DEBUG_ANY, "fork failed\n", 0, 0, 0 ); 99 return( -1 ); 100 } 101 102 /* parent */ 103 if ( (*rfp = fdopen( c2p[0], "r" )) == NULL || (*wfp = fdopen( p2c[1], 104 "w" )) == NULL ) { 105 Debug( LDAP_DEBUG_ANY, "fdopen failed\n", 0, 0, 0 ); 106 if ( *rfp ) { 107 fclose( *rfp ); 108 *rfp = NULL; 109 } else { 110 close( c2p[0] ); 111 } 112 close( p2c[1] ); 113 114 return( -1 ); 115 } 116 117 return( pid ); 118} 119