Mercurial > dropbear
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 |