Back to index

openldap  2.4.31
fork.c
Go to the documentation of this file.
00001 /* fork.c - fork and exec a process, connecting stdin/out w/pipes */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 1998-2012 The OpenLDAP Foundation.
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted only as authorized by the OpenLDAP
00010  * Public License.
00011  *
00012  * A copy of this license is available in the file LICENSE in the
00013  * top-level directory of the distribution or, alternatively, at
00014  * <http://www.OpenLDAP.org/license.html>.
00015  */
00016 /* Portions Copyright (c) 1995 Regents of the University of Michigan.
00017  * All rights reserved.
00018  *
00019  * Redistribution and use in source and binary forms are permitted
00020  * provided that this notice is preserved and that due credit is given
00021  * to the University of Michigan at Ann Arbor. The name of the University
00022  * may not be used to endorse or promote products derived from this
00023  * software without specific prior written permission. This software
00024  * is provided ``as is'' without express or implied warranty.
00025  */
00026 /* ACKNOWLEDGEMENTS:
00027  * This work was originally developed by the University of Michigan
00028  * (as part of U-MICH LDAP).
00029  */
00030 
00031 #include "portable.h"
00032 
00033 #include <stdio.h>
00034 
00035 #include <ac/errno.h>
00036 #include <ac/string.h>
00037 #include <ac/socket.h>
00038 #include <ac/unistd.h>
00039 
00040 #include "slap.h"
00041 #include "shell.h"
00042 
00043 pid_t
00044 forkandexec(
00045     char      **args,
00046     FILE      **rfp,
00047     FILE      **wfp
00048 )
00049 {
00050        int    p2c[2] = { -1, -1 }, c2p[2];
00051        pid_t  pid;
00052 
00053        if ( pipe( p2c ) != 0 || pipe( c2p ) != 0 ) {
00054               Debug( LDAP_DEBUG_ANY, "pipe failed\n", 0, 0, 0 );
00055               close( p2c[0] );
00056               close( p2c[1] );
00057               return( -1 );
00058        }
00059 
00060        /*
00061         * what we're trying to set up looks like this:
00062         *     parent *wfp -> p2c[1] | p2c[0] -> stdin child
00063         *     parent *rfp <- c2p[0] | c2p[1] <- stdout child
00064         */
00065 
00066        fflush( NULL );
00067 # ifdef HAVE_THR
00068        pid = fork1();
00069 # else
00070        pid = fork();
00071 # endif
00072        if ( pid == 0 ) {           /* child */
00073               /*
00074                * child could deadlock here due to resources locked
00075                * by our parent
00076                *
00077                * If so, configure --without-threads.
00078                */
00079               if ( dup2( p2c[0], 0 ) == -1 || dup2( c2p[1], 1 ) == -1 ) {
00080                      Debug( LDAP_DEBUG_ANY, "dup2 failed\n", 0, 0, 0 );
00081                      exit( EXIT_FAILURE );
00082               }
00083        }
00084        close( p2c[0] );
00085        close( c2p[1] );
00086        if ( pid <= 0 ) {
00087               close( p2c[1] );
00088               close( c2p[0] );
00089        }
00090        switch ( pid ) {
00091        case 0:
00092               execv( args[0], args );
00093 
00094               Debug( LDAP_DEBUG_ANY, "execv failed\n", 0, 0, 0 );
00095               exit( EXIT_FAILURE );
00096 
00097        case -1:      /* trouble */
00098               Debug( LDAP_DEBUG_ANY, "fork failed\n", 0, 0, 0 );
00099               return( -1 );
00100        }
00101 
00102        /* parent */
00103        if ( (*rfp = fdopen( c2p[0], "r" )) == NULL || (*wfp = fdopen( p2c[1],
00104            "w" )) == NULL ) {
00105               Debug( LDAP_DEBUG_ANY, "fdopen failed\n", 0, 0, 0 );
00106               if ( *rfp ) {
00107                      fclose( *rfp );
00108                      *rfp = NULL;
00109               } else {
00110                      close( c2p[0] );
00111               }
00112               close( p2c[1] );
00113 
00114               return( -1 );
00115        }
00116 
00117        return( pid );
00118 }