A C++ IOStream interface to POSIX Process I/O. |
![]() |
The library is a work in progress. It is intended to provide a C++
re-implementation of the POSIX.2 functions popen(3)
and
pclose(3)
, using IOStreams to read from and write to the
opened process.
The advantages over the standard popen()
function are:
printf()
/scanf()
functions in standard C.popen()
vary
between systems. Some systems use bidirectional pipes, allowing reading
and writing on the same stream, but this is not supported everywhere.
Because PStreams doesn't use popen()
but re-implements it
at a lower level, bidirectional I/O is available on all systems.stderr
. Input PStreams can read
from the process' stderr
as well as stdout
.popen()
the PStreams classes can open a process
specified by a filename and a vector of arguments, similar to the
execv()
function.The library is available under the GNU Lesser General Public License
To help improve PStreams see the SourceForge project page.
Version 0.42
Working ipstream
and opstream
classes for
ISO C++-compliant compilers. The classes are fully functional and the
public interfaces should be stable for all except the pstreambuf
class, which may be extended to add new features.
The stream buffer class, pstreambuf
, doesn't use
popen()
. It uses up to three
pipes shared with the associated process, giving access to any combination
of the process' stdin
, stdout
and stderr
streams. I/O operations on these pipes are buffered to avoid making a
system call for every character written or read.
Another class, rpstream
(Restricted PStream) is similar to
pstream
except that the child process' stdout
and stderr
cannot be read directly from an
rpstream
. To read from the process you must call either
rpstream::out()
or rpstream::err()
to obtain a
reference to an istream
that reads from the process'
corresponding output stream. This class is not as well tested as the others
(i.e. it's hardly tested at all).
No code-conversion is performed on multi-byte character streams.
It should be possible to use the PStreams classes templatized with character
types other than char
(e.g. basic_pstream<int>
)
but note that characters are transfered in a bytewise manner, so it is the
programmer's responsibility to interpret the resulting character strings.
Since the classes are intended to be used to read/write data between
processes, which will usually share an internal character representation,
rather than to/from files, this behaviour should be sufficient.
Please refer to the doxygen-generated documentation, accessible through the links at the top of the page.
Using the PStreams classes is similar to using a std::fstream
,
except that a shell command is given rather than a filename:
// print names of all header files in current directory
redi::ipstream in("ls ./*.h");
std::string str;
while (in >> str) {
std::cout << str << std::endl;
}
The command argument is a pointer to a null-terminated string containing a shell command line. This command is passed to /bin/sh using the -c flag; Alias and wildcard interpretation, if any, is performed by the shell.
Alternatively, the process can be started with a vector of arguments:
// remove some files, capturing any error messages
std::vector<std::string> argv;
std::vector<std::string> errors;
argv.push_back("rm");
argv.push_back("-rf");
argv.push_back("./foo.txt");
argv.push_back("./bar.html");
argv.push_back("./fnord/");
redi::ipstream in("rm", argv, pstreambuf::pstderr);
std::string errmsg;
while (std::getline(in, errmsg)) {
errors.push_back(errmsg);
}
If this form of initialisation is used and the file argument doesn't
contain a slash then the actions of the shell
will be duplicated in searching for an executable in PATH
.
The shell will not interpret the other arguments, so wildcard expansion will
not take place if this interface is used.
If an rpstream
was used in the example above it would be
necessary to replace the while condition like so:
while (std::getline(in.err(), errmsg)) {
errors.push_back(errmsg);
}
This form can also be used with the unrestricted pstream
and ipstream
classes, but it is not strictly necessary.
The latest version of PStreams can be found at http://pstreams.sf.net