2 * Copyright 2007 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Ramshankar, v.ramshankar@gmail.com
7 * Stephan Aßmus <superstippi@gmx.de>
10 //! BCommandPipe class to handle reading shell output
11 // (stdout/stderr) of other programs into memory.
12 #include "CommandPipe.h"
19 #include <Messenger.h>
23 BCommandPipe::BCommandPipe()
31 BCommandPipe::~BCommandPipe()
38 BCommandPipe::AddArg(const char* arg
)
40 if (arg
== NULL
|| arg
[0] == '\0')
43 char* argCopy
= strdup(arg
);
47 if (!fArgList
.AddItem(reinterpret_cast<void*>(argCopy
))) {
57 BCommandPipe::PrintToStream() const
59 for (int32 i
= 0L; i
< fArgList
.CountItems(); i
++)
60 printf("%s ", reinterpret_cast<char*>(fArgList
.ItemAtFast(i
)));
67 BCommandPipe::FlushArgs()
69 // Delete all arguments from the list
70 for (int32 i
= fArgList
.CountItems() - 1; i
>= 0; i
--)
71 free(fArgList
.ItemAtFast(i
));
94 BCommandPipe::Argv(int32
& argc
) const
96 // NOTE: Freeing is left to caller as indicated in the header!
97 argc
= fArgList
.CountItems();
98 const char** argv
= reinterpret_cast<const char**>(
99 malloc((argc
+ 1) * sizeof(char*)));
100 for (int32 i
= 0; i
< argc
; i
++)
101 argv
[i
] = reinterpret_cast<const char*>(fArgList
.ItemAtFast(i
));
112 BCommandPipe::PipeAll(int* stdOutAndErr
) const
114 // This function pipes both stdout and stderr to the same filedescriptor
119 oldStdOut
= dup(STDOUT_FILENO
);
120 oldStdErr
= dup(STDERR_FILENO
);
121 close(STDOUT_FILENO
);
122 close(STDERR_FILENO
);
123 // TODO: This looks broken, using "stdOutAndErr[1]" twice!
124 dup2(stdOutAndErr
[1], STDOUT_FILENO
);
125 dup2(stdOutAndErr
[1], STDERR_FILENO
);
127 // Construct the argv vector
129 const char** argv
= Argv(argc
);
131 // Load the app image... and pass the args
132 thread_id appThread
= load_image((int)argc
, argv
,
133 const_cast<const char**>(environ
));
135 dup2(oldStdOut
, STDOUT_FILENO
);
136 dup2(oldStdErr
, STDERR_FILENO
);
147 BCommandPipe::Pipe(int* stdOut
, int* stdErr
) const
153 oldStdOut
= dup(STDOUT_FILENO
);
154 oldStdErr
= dup(STDERR_FILENO
);
155 close(STDOUT_FILENO
);
156 close(STDERR_FILENO
);
157 dup2(stdOut
[1], STDOUT_FILENO
);
158 dup2(stdErr
[1], STDERR_FILENO
);
160 // Construct the argv vector
162 const char** argv
= Argv(argc
);
164 // Load the app image... and pass the args
165 thread_id appThread
= load_image((int)argc
, argv
, const_cast<
166 const char**>(environ
));
168 dup2(oldStdOut
, STDOUT_FILENO
);
169 dup2(oldStdErr
, STDERR_FILENO
);
180 BCommandPipe::Pipe(int* stdOut
) const
182 // Redirects only output (stdout) to caller, stderr is closed
184 thread_id tid
= Pipe(stdOut
, stdErr
);
192 BCommandPipe::PipeInto(FILE** _out
, FILE** _err
)
196 thread_id tid
= Pipe(fStdOut
, fStdErr
);
206 *_out
= fdopen(fStdOut
[0], "r");
207 *_err
= fdopen(fStdErr
[0], "r");
214 BCommandPipe::PipeInto(FILE** _outAndErr
)
218 thread_id tid
= PipeAll(fStdOut
);
225 *_outAndErr
= fdopen(fStdOut
[0], "r");
236 // Runs the command without bothering to redirect streams, this is similar
237 // to system() but uses pipes and wait_for_thread.... Synchronous.
238 int stdOut
[2], stdErr
[2];
240 wait_for_thread(Pipe(stdOut
, stdErr
), &exitCode
);
250 BCommandPipe::RunAsync()
252 // Runs the command without bothering to redirect streams, this is similar
253 // to system() but uses pipes.... Asynchronous.
265 BCommandPipe::ReadLines(FILE* file
, LineReader
* lineReader
)
267 // Reads output of file, line by line. Each line is passed to lineReader
268 // for inspection, and the IsCanceled() method is repeatedly called.
270 if (file
== NULL
|| lineReader
== NULL
)
275 while (!feof(file
)) {
276 if (lineReader
->IsCanceled())
279 unsigned char c
= fgetc(file
);
280 // TODO: fgetc() blocks, is there a way to make it timeout?
286 status_t ret
= lineReader
->ReadLine(line
);
298 BCommandPipe::ReadLines(FILE* file
)
300 class AllLinesReader
: public LineReader
{
308 virtual bool IsCanceled()
313 virtual status_t
ReadLine(const BString
& line
)
315 int lineLength
= line
.Length();
316 int resultLength
= fResult
.Length();
318 if (fResult
.Length() != lineLength
+ resultLength
)
323 BString
Result() const
332 ReadLines(file
, &lineReader
);
334 return lineReader
.Result();
342 BCommandPipe::operator<<(const char* arg
)
350 BCommandPipe::operator<<(const BString
& arg
)
352 AddArg(arg
.String());
358 BCommandPipe::operator<<(const BCommandPipe
& arg
)
361 const char** argv
= arg
.Argv(argc
);
362 for (int32 i
= 0; i
< argc
; i
++)