comparison dbutil.c @ 484:effb4a25b1ae

Don't capture stderr from spawned processes in proxycommand mode
author Matt Johnston <matt@ucc.asn.au>
date Wed, 17 Sep 2008 14:35:36 +0000
parents 7ad49f34a122
children d59f628e7baa
comparison
equal deleted inserted replaced
483:738313e73b1c 484:effb4a25b1ae
144 if (!debug_trace) { 144 if (!debug_trace) {
145 return; 145 return;
146 } 146 }
147 147
148 va_start(param, format); 148 va_start(param, format);
149 fprintf(stderr, "TRACE: "); 149 fprintf(stderr, "TRACE (%d): ", getpid());
150 vfprintf(stderr, format, param); 150 vfprintf(stderr, format, param);
151 fprintf(stderr, "\n"); 151 fprintf(stderr, "\n");
152 va_end(param); 152 va_end(param);
153 } 153 }
154 #endif /* DEBUG_TRACE */ 154 #endif /* DEBUG_TRACE */
389 return sock; 389 return sock;
390 } 390 }
391 391
392 /* Sets up a pipe for a, returning three non-blocking file descriptors 392 /* Sets up a pipe for a, returning three non-blocking file descriptors
393 * and the pid. exec_fn is the function that will actually execute the child process, 393 * and the pid. exec_fn is the function that will actually execute the child process,
394 * it will be run after the child has fork()ed, and is passed exec_data. */ 394 * it will be run after the child has fork()ed, and is passed exec_data.
395 * If ret_errfd == NULL then stderr will not be captured.
396 * ret_pid can be passed as NULL to discard the pid. */
395 int spawn_command(void(*exec_fn)(void *user_data), void *exec_data, 397 int spawn_command(void(*exec_fn)(void *user_data), void *exec_data,
396 int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) { 398 int *ret_writefd, int *ret_readfd, int *ret_errfd, pid_t *ret_pid) {
397 int infds[2]; 399 int infds[2];
398 int outfds[2]; 400 int outfds[2];
399 int errfds[2]; 401 int errfds[2];
401 403
402 const int FDIN = 0; 404 const int FDIN = 0;
403 const int FDOUT = 1; 405 const int FDOUT = 1;
404 406
405 /* redirect stdin/stdout/stderr */ 407 /* redirect stdin/stdout/stderr */
406 if (pipe(infds) != 0) 408 if (pipe(infds) != 0) {
407 return DROPBEAR_FAILURE; 409 return DROPBEAR_FAILURE;
408 if (pipe(outfds) != 0) 410 }
411 if (pipe(outfds) != 0) {
409 return DROPBEAR_FAILURE; 412 return DROPBEAR_FAILURE;
410 if (pipe(errfds) != 0) 413 }
414 if (ret_errfd && pipe(errfds) != 0) {
411 return DROPBEAR_FAILURE; 415 return DROPBEAR_FAILURE;
416 }
412 417
413 #ifdef __uClinux__ 418 #ifdef __uClinux__
414 pid = vfork(); 419 pid = vfork();
415 #else 420 #else
416 pid = fork(); 421 pid = fork();
417 #endif 422 #endif
418 423
419 if (pid < 0) 424 if (pid < 0) {
420 return DROPBEAR_FAILURE; 425 return DROPBEAR_FAILURE;
426 }
421 427
422 if (!pid) { 428 if (!pid) {
423 /* child */ 429 /* child */
424 430
425 TRACE(("back to normal sigchld")) 431 TRACE(("back to normal sigchld"))
430 436
431 /* redirect stdin/stdout */ 437 /* redirect stdin/stdout */
432 438
433 if ((dup2(infds[FDIN], STDIN_FILENO) < 0) || 439 if ((dup2(infds[FDIN], STDIN_FILENO) < 0) ||
434 (dup2(outfds[FDOUT], STDOUT_FILENO) < 0) || 440 (dup2(outfds[FDOUT], STDOUT_FILENO) < 0) ||
435 (dup2(errfds[FDOUT], STDERR_FILENO) < 0)) { 441 (ret_errfd && dup2(errfds[FDOUT], STDERR_FILENO) < 0)) {
436 TRACE(("leave noptycommand: error redirecting FDs")) 442 TRACE(("leave noptycommand: error redirecting FDs"))
437 dropbear_exit("child dup2() failure"); 443 dropbear_exit("child dup2() failure");
438 } 444 }
439 445
440 close(infds[FDOUT]); 446 close(infds[FDOUT]);
441 close(infds[FDIN]); 447 close(infds[FDIN]);
442 close(outfds[FDIN]); 448 close(outfds[FDIN]);
443 close(outfds[FDOUT]); 449 close(outfds[FDOUT]);
444 close(errfds[FDIN]); 450 if (ret_errfd)
445 close(errfds[FDOUT]); 451 {
452 close(errfds[FDIN]);
453 close(errfds[FDOUT]);
454 }
446 455
447 exec_fn(exec_data); 456 exec_fn(exec_data);
448 /* not reached */ 457 /* not reached */
449 return DROPBEAR_FAILURE; 458 return DROPBEAR_FAILURE;
450 } else { 459 } else {
451 /* parent */ 460 /* parent */
452 close(infds[FDIN]); 461 close(infds[FDIN]);
453 close(outfds[FDOUT]); 462 close(outfds[FDOUT]);
454 close(errfds[FDOUT]); 463
455
456 setnonblocking(errfds[FDIN]);
457 setnonblocking(outfds[FDIN]); 464 setnonblocking(outfds[FDIN]);
458 setnonblocking(infds[FDOUT]); 465 setnonblocking(infds[FDOUT]);
459 466
460 *ret_pid = pid; 467 if (ret_errfd) {
468 close(errfds[FDOUT]);
469 setnonblocking(errfds[FDIN]);
470 }
471
472 if (ret_pid) {
473 *ret_pid = pid;
474 }
475
461 *ret_writefd = infds[FDOUT]; 476 *ret_writefd = infds[FDOUT];
462 *ret_readfd = outfds[FDIN]; 477 *ret_readfd = outfds[FDIN];
463 *ret_errfd = errfds[FDIN]; 478 if (ret_errfd) {
479 *ret_errfd = errfds[FDIN];
480 }
464 return DROPBEAR_SUCCESS; 481 return DROPBEAR_SUCCESS;
465 } 482 }
466 } 483 }
467 484
468 /* Runs a command with "sh -c". Will close FDs (except stdin/stdout/stderr) and 485 /* Runs a command with "sh -c". Will close FDs (except stdin/stdout/stderr) and