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;
122 msg.msg_control = control_un.control;
123 msg.msg_controllen = sizeof(control_un.control);
125 msg.msg_accrights = (caddr_t) io;
126 msg.msg_accrightslen = sizeof(io);
133 switch( recvmsg( pair[p][1], &msg, MSG_WAITALL ) ) {
137 _exit( EXIT_FAILURE );
139 _exit( EXIT_SUCCESS );
142 if( (cmptr = CMSG_FIRSTHDR(&msg)) == NULL ||
143 cmptr->cmsg_len != CMSG_LEN(sizeof(io)) ||
144 cmptr->cmsg_level != SOL_SOCKET ||
145 cmptr->cmsg_type != SCM_RIGHTS ) {
146 fputs( "bad descriptor message received\n", stderr );
147 exit( EXIT_FAILURE );
149 memcpy( io, CMSG_DATA( cmptr ), sizeof(io) );
151 if( msg.msg_accrightslen != sizeof(io) ) {
152 fputs( "bad descriptor message received\n", stderr );
153 exit( EXIT_FAILURE );
157 /* Read length of arguments and then arguments from socket */
158 if( nread( pair[p][1], &len, sizeof(len) ) != sizeof(len) ) {
159 fputs( "bad descriptor message received\n", stderr );
160 exit( EXIT_FAILURE );
163 buf = realloc( buf, buflen = len );
165 fputs( "realloc failed\n", stderr );
166 exit( EXIT_FAILURE );
169 if( nread( pair[p][1], buf, len ) != len ) {
170 fputs( "bad descriptor message received\n", stderr );
171 exit( EXIT_FAILURE );
175 while( offset < len ) {
178 argv = realloc( argv, argc * sizeof(*argv) );
180 fputs( "realloc failed\n", stderr );
181 exit( EXIT_FAILURE );
184 argv[i++] = buf + offset;
185 offset += strlen( buf + offset ) + 1;
194 if( dup2( io[0], 0 ) == -1 || dup2( io[1], 1 ) == -1 ) {
195 fputs( "dup2 failed\n", stderr );
196 exit( EXIT_FAILURE );
202 execv( argv[0], argv );
204 fputs( "execv failed\n", stderr );
205 exit( EXIT_FAILURE );
207 case -1: /* trouble */
208 fputs( "fork failed\n", stderr );
211 default: /* parent */
216 if( nwrite( pair[p][1], &pid,
217 sizeof(pid_t) ) != sizeof(pid_t) ) {
218 fputs( "could not send pid\n", stderr );
219 exit( EXIT_FAILURE );
224 #endif /* SHELL_SURROGATE_PARENT */
233 int p2c[2] = { -1, -1 }, c2p[2];
236 if ( pipe( p2c ) != 0 || pipe( c2p ) != 0 ) {
237 Debug( LDAP_DEBUG_ANY, "pipe failed\n", 0, 0, 0 );
244 * what we're trying to set up looks like this:
245 * parent *wfp -> p2c[1] | p2c[0] -> stdin child
246 * parent *rfp <- c2p[0] | c2p[1] <- stdout child
249 #ifdef SHELL_SURROGATE_PARENT
252 int io[2] = { p2c[0], c2p[1] }, i, c;
253 static char dummy = '\0';
254 static struct iovec iov = { &dummy, 1 };
259 char control[CMSG_SPACE(sizeof(io))];
261 struct cmsghdr *cmptr;
262 msg.msg_control = control_un.control;
263 msg.msg_controllen = sizeof(control_un.control);
264 cmptr = CMSG_FIRSTHDR(&msg);
265 cmptr->cmsg_len = CMSG_LEN(sizeof(io));
266 cmptr->cmsg_level = SOL_SOCKET;
267 cmptr->cmsg_type = SCM_RIGHTS;
268 memcpy( CMSG_DATA(cmptr), io, sizeof(io) );
270 msg.msg_accrights = (caddr_t) io;
271 msg.msg_accrightslen = sizeof(io);
278 ldap_pvt_thread_mutex_lock( &shell_surrogate_index_mutex );
279 i = shell_surrogate_index ^= 1;
280 ldap_pvt_thread_mutex_unlock( &shell_surrogate_index_mutex );
281 ldap_pvt_thread_mutex_lock( &shell_surrogate_fd_mutex[i] );
282 c = (sendmsg( shell_surrogate_fd[i], &msg, 0 ) == 1 &&
283 nwrite( shell_surrogate_fd[i], &args.bv_len,
284 sizeof(args.bv_len) ) == sizeof(args.bv_len) &&
285 nwrite( shell_surrogate_fd[i], args.bv_val,
286 args.bv_len ) == args.bv_len &&
287 nread( shell_surrogate_fd[i], &pid,
288 sizeof(pid) ) == sizeof(pid));
289 ldap_pvt_thread_mutex_unlock( &shell_surrogate_fd_mutex[i] );
293 Debug( LDAP_DEBUG_ANY, "process creation failed\n", 0, 0, 0 );
296 close( shell_surrogate_fd[0] );
297 close( shell_surrogate_fd[1] );
298 shell_surrogate_fd[0] =
299 shell_surrogate_fd[1] = -1;
304 #else /* !SHELL_SURROGATE_PARENT */
312 if ( pid == 0 ) { /* child */
314 * child could deadlock here due to resources locked
317 * If so, configure --without-threads.
319 if ( dup2( p2c[0], 0 ) == -1 || dup2( c2p[1], 1 ) == -1 ) {
320 Debug( LDAP_DEBUG_ANY, "dup2 failed\n", 0, 0, 0 );
321 exit( EXIT_FAILURE );
332 execv( args[0], args );
334 Debug( LDAP_DEBUG_ANY, "execv failed\n", 0, 0, 0 );
335 exit( EXIT_FAILURE );
337 case -1: /* trouble */
338 Debug( LDAP_DEBUG_ANY, "fork failed\n", 0, 0, 0 );
342 #endif /* SHELL_SURROGATE_PARENT */
345 if ( (*rfp = fdopen( c2p[0], "r" )) == NULL || (*wfp = fdopen( p2c[1],
347 Debug( LDAP_DEBUG_ANY, "fdopen failed\n", 0, 0, 0 );