More or less rewrote _PipeCommand() to be:

a) less error prone, and
b) easier on the eyes.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18573 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-08-22 23:22:35 +00:00
parent 1c494ffa65
commit c11f830b37
@@ -250,50 +250,66 @@ thread_id
ZipperThread::_PipeCommand(int argc, const char** argv, int& in, int& out, ZipperThread::_PipeCommand(int argc, const char** argv, int& in, int& out,
int& err, const char** envp) int& err, const char** envp)
{ {
// This function written by Peter Folk <[email protected]> // This function was originally written by Peter Folk <[email protected]>
// and published in the BeDevTalk FAQ // and published in the BeDevTalk FAQ
// http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209 // http://www.abisoft.com/faq/BeDevTalk_FAQ.html#FAQ-209
thread_id thread;
// Save current FDs // Save current FDs
int old_in = dup(0); int oldIn = dup(STDIN_FILENO);
int old_out = dup(1); int oldOut = dup(STDOUT_FILENO);
int old_err = dup(2); int oldErr = dup(STDERR_FILENO);
int filedes[2]; int inPipe[2], outPipe[2], errPipe[2];
/* Create new pipe FDs as stdin, stdout, stderr */ // Create new pipe FDs as stdin, stdout, stderr
pipe(filedes); if (pipe(inPipe) < 0)
dup2(filedes[0], 0); goto err1;
close(filedes[0]); if (pipe(outPipe) < 0)
in = filedes[1]; // Write to in, appears on cmd's stdin goto err2;
pipe(filedes); if (pipe(errPipe) < 0)
dup2(filedes[1], 1); goto err3;
close(filedes[1]);
out = filedes[0]; // Read from out, taken from cmd's stdout
pipe(filedes);
dup2(filedes[1], 2);
close(filedes[1]);
err = filedes[0]; // Read from err, taken from cmd's stderr
// "load" command. errno = 0;
thread_id ret = load_image(argc, argv, envp);
// thread ret is now suspended. // replace old stdin/stderr/stdout
dup2(inPipe[0], STDIN_FILENO);
close(inPipe[0]);
dup2(outPipe[1], STDOUT_FILENO);
close(outPipe[1]);
dup2(errPipe[1], STDERR_FILENO);
close(errPipe[1]);
if (errno == 0) {
in = inPipe[1]; // Write to in, appears on cmd's stdin
out = outPipe[0]; // Read from out, taken from cmd's stdout
err = errPipe[0]; // Read from err, taken from cmd's stderr
// execute command
thread = load_image(argc, argv, envp);
PRINT(("load_image() thread_id: %ld\n", ret)); PRINT(("load_image() thread_id: %ld\n", ret));
} else
thread = errno;
// Restore old FDs // Restore old FDs
close(0); dup(old_in); close(old_in); close(STDIN_FILENO); dup(oldIn); close(oldIn);
close(1); dup(old_out); close(old_out); close(STDOUT_FILENO); dup(oldOut); close(oldOut);
close(2); dup(old_err); close(old_err); close(STDERR_FILENO); dup(oldErr); close(oldErr);
return thread;
// TODO: err3:
/* close(outPipe[0]);
Theoretically I should do loads of error checking, but close(outPipe[1]);
the calls aren't very likely to fail, and that would err2:
muddy up the example quite a bit. YMMV. close(inPipe[0]);
*/ close(inPipe[1]);
err1:
return ret; close(oldIn);
close(oldOut);
close(oldErr);
return errno;
} }