1 /* fork.c - fork and exec a process, connecting stdin/out w/pipes */
4 * Copyright 1998-2002 The OpenLDAP Foundation, All Rights Reserved.
5 * COPYING RESTRICTIONS APPLY, see COPYRIGHT file
13 #include <ac/string.h>
14 #include <ac/socket.h>
15 #include <ac/unistd.h>
20 #ifdef SHELL_SURROGATE_PARENT
24 /* Use several socketpairs to the surrogate parent, because *
25 * a single communication channel to it could be a bottleneck */
26 ldap_pvt_thread_mutex_t shell_surrogate_fd_mutex[2];
27 int shell_surrogate_fd[2] = { -1, -1 };
28 /* Index to shell_surrogate_fd, and its mutex */
29 ldap_pvt_thread_mutex_t shell_surrogate_index_mutex;
30 static int shell_surrogate_index = 1;
32 pid_t shell_surrogate_pid = -1;
34 #define nread( fd, buf, len ) n_rw( 0, fd, buf, len )
35 #define nwrite( fd, buf, len ) n_rw( 1, fd, buf, len )
49 ? write( fd, buf, len )
50 : read( fd, buf, len ));
62 buf = (char *)buf + i;
69 make_surrogate_parent( void )
71 int pair[2][2], io[2], i, j, p, argc;
72 ber_len_t len, buflen, offset;
76 if( socketpair( AF_LOCAL, SOCK_STREAM, 0, pair[0] ) < 0 ||
77 socketpair( AF_LOCAL, SOCK_STREAM, 0, pair[1] ) < 0 ) {
78 Debug( LDAP_DEBUG_ANY, "socketpair failed\n", 0, 0, 0 );
84 Debug( LDAP_DEBUG_ANY, "fork failed\n", 0, 0, 0 );
89 shell_surrogate_fd[0] = pair[0][0];
90 shell_surrogate_fd[1] = pair[1][0];
96 /* Close unused file descriptors */
97 for( i = 3, j = 32; j && i < 1024; i++ )
98 if( i != pair[0][1] && i != pair[1][1] && close( i ) < 0 )
103 /* Surrogate parent running */
112 /* Read file descriptors io[] from socket */
114 static struct iovec iov = { &dummy, 1 };
119 char control[CMSG_SPACE(sizeof(io))];
121 struct cmsghdr *cmptr;
125 memset( &msg, 0, sizeof msg );
128 msg.msg_control = control_un.control;
129 msg.msg_controllen = sizeof(control_un.control);
131 msg.msg_accrights = (caddr_t) io;
132 msg.msg_accrightslen = sizeof(io);
140 switch( recvmsg( pair[p][1], &msg, MSG_WAITALL ) ) {
144 _exit( EXIT_FAILURE );
146 _exit( EXIT_SUCCESS );
149 if( (cmptr = CMSG_FIRSTHDR(&msg)) == NULL ||
150 cmptr->cmsg_len != CMSG_LEN(sizeof(io)) ||
151 cmptr->cmsg_level != SOL_SOCKET ||
152 cmptr->cmsg_type != SCM_RIGHTS ) {
153 fputs( "bad descriptor message received\n", stderr );
154 exit( EXIT_FAILURE );
156 memcpy( io, CMSG_DATA( cmptr ), sizeof(io) );
158 if( msg.msg_accrightslen != sizeof(io) ) {
159 fputs( "bad descriptor message received\n", stderr );
160 exit( EXIT_FAILURE );
164 /* Read length of arguments and then arguments from socket */
165 if( nread( pair[p][1], &len, sizeof(len) ) != sizeof(len) ) {
166 fputs( "bad descriptor message received\n", stderr );
167 exit( EXIT_FAILURE );
170 buf = realloc( buf, buflen = len );
172 fputs( "realloc failed\n", stderr );
173 exit( EXIT_FAILURE );
176 if( nread( pair[p][1], buf, len ) != len ) {
177 fputs( "bad descriptor message received\n", stderr );
178 exit( EXIT_FAILURE );
182 while( offset < len ) {
185 argv = realloc( argv, argc * sizeof(*argv) );
187 fputs( "realloc failed\n", stderr );
188 exit( EXIT_FAILURE );
191 argv[i++] = buf + offset;
192 offset += strlen( buf + offset ) + 1;
201 if( dup2( io[0], 0 ) == -1 || dup2( io[1], 1 ) == -1 ) {
202 fputs( "dup2 failed\n", stderr );
203 exit( EXIT_FAILURE );
209 execv( argv[0], argv );
211 fputs( "execv failed\n", stderr );
212 exit( EXIT_FAILURE );
214 case -1: /* trouble */
215 fputs( "fork failed\n", stderr );
218 default: /* parent */
223 if( nwrite( pair[p][1], &pid,
224 sizeof(pid_t) ) != sizeof(pid_t) ) {
225 fputs( "could not send pid\n", stderr );
226 exit( EXIT_FAILURE );
231 #endif /* SHELL_SURROGATE_PARENT */
240 int p2c[2] = { -1, -1 }, c2p[2];
243 if ( pipe( p2c ) != 0 || pipe( c2p ) != 0 ) {
244 Debug( LDAP_DEBUG_ANY, "pipe failed\n", 0, 0, 0 );
251 * what we're trying to set up looks like this:
252 * parent *wfp -> p2c[1] | p2c[0] -> stdin child
253 * parent *rfp <- c2p[0] | c2p[1] <- stdout child
256 #ifdef SHELL_SURROGATE_PARENT
259 int io[2] = { p2c[0], c2p[1] }, i, c;
260 static char dummy = '\0';
261 static struct iovec iov = { &dummy, 1 };
266 char control[CMSG_SPACE(sizeof(io))];
268 struct cmsghdr *cmptr;
272 memset( &msg, 0, sizeof msg );
275 msg.msg_control = control_un.control;
276 msg.msg_controllen = sizeof(control_un.control);
277 cmptr = CMSG_FIRSTHDR(&msg);
278 cmptr->cmsg_len = CMSG_LEN(sizeof(io));
279 cmptr->cmsg_level = SOL_SOCKET;
280 cmptr->cmsg_type = SCM_RIGHTS;
281 memcpy( CMSG_DATA(cmptr), io, sizeof(io) );
283 msg.msg_accrights = (caddr_t) io;
284 msg.msg_accrightslen = sizeof(io);
292 ldap_pvt_thread_mutex_lock( &shell_surrogate_index_mutex );
293 i = shell_surrogate_index ^= 1;
294 ldap_pvt_thread_mutex_unlock( &shell_surrogate_index_mutex );
295 ldap_pvt_thread_mutex_lock( &shell_surrogate_fd_mutex[i] );
296 c = (sendmsg( shell_surrogate_fd[i], &msg, 0 ) == 1 &&
297 nwrite( shell_surrogate_fd[i], &args.bv_len,
298 sizeof(args.bv_len) ) == sizeof(args.bv_len) &&
299 nwrite( shell_surrogate_fd[i], args.bv_val,
300 args.bv_len ) == args.bv_len &&
301 nread( shell_surrogate_fd[i], &pid,
302 sizeof(pid) ) == sizeof(pid));
303 ldap_pvt_thread_mutex_unlock( &shell_surrogate_fd_mutex[i] );
307 Debug( LDAP_DEBUG_ANY, "process creation failed\n", 0, 0, 0 );
310 close( shell_surrogate_fd[0] );
311 close( shell_surrogate_fd[1] );
312 shell_surrogate_fd[0] =
313 shell_surrogate_fd[1] = -1;
318 #else /* !SHELL_SURROGATE_PARENT */
326 if ( pid == 0 ) { /* child */
328 * child could deadlock here due to resources locked
331 * If so, configure --without-threads.
333 if ( dup2( p2c[0], 0 ) == -1 || dup2( c2p[1], 1 ) == -1 ) {
334 Debug( LDAP_DEBUG_ANY, "dup2 failed\n", 0, 0, 0 );
335 exit( EXIT_FAILURE );
346 execv( args[0], args );
348 Debug( LDAP_DEBUG_ANY, "execv failed\n", 0, 0, 0 );
349 exit( EXIT_FAILURE );
351 case -1: /* trouble */
352 Debug( LDAP_DEBUG_ANY, "fork failed\n", 0, 0, 0 );
356 #endif /* SHELL_SURROGATE_PARENT */
359 if ( (*rfp = fdopen( c2p[0], "r" )) == NULL || (*wfp = fdopen( p2c[1],
361 Debug( LDAP_DEBUG_ANY, "fdopen failed\n", 0, 0, 0 );