FBB::Proc - Runs external programs
#include <bobcat/proc>
Linking option: -lbobcat
The FBB::Proc offers an alternative to the
FBB::Process class. FBB::Proc offers an extensive interface to
calling external programs and/or scripts from a C++ program
(so-called child-processes). The class offers an easy to use,
stream-based interface to communicate with the standard input, output and
error streams of child processes.
Objects of the class Proc use standard process-executing
functions, like members of the execl(2) family or sh(1) to
execute child processes. Thus, child processes can be executable programs or
shell-scripts.
The standard input, output and error streams of child processes
may be accessed through their Proc parent objects. Input expected by
child processes can be inserted into Proc objects. standard output
and standard error generated by child processes are inserted into and
further handled by std::ostream objects, by default std::cout
and std::cerr.
When using (output) redirection when executing child processes
using the USE_SHELL path specification (see below for the path and
IOMode specifications), the IGNORE_COUT IOMode (and possibly
IGNORE_CERR) should normally be specified (cf. section
ENUMERATIONS for a description of the IOMode enumeration).
Proc objects may repeatedly be used to execute the same or
different child processes. Before the next child process is started, the
Proc object ensures that its currently active child process ends.
Alternatively, a currently active child process ends if the Proc
object goes out of scope, if the allotted execution time of the child
process has passed, if a new process is started using Proc’s
assignment operator, or if its stop member is called. Otherwise child
processes continue until completion when calling finish or, if the
child process reads its standard input stream, when the eoi
manipulator is inserted into the Proc object.
Programs called as child processes may be specified when
constructing a Proc object or by using Proc’s
setCommand member. Proc constructors (or Proc’s
setCommand-member) don’t start child processes. To start child
processes the start members or the assignment operator must be
used.
Child processes may receive information at their standard input
streams through information inserted into Proc objects. In those
cases Proc objects must inform their child processes that they have
received all input. For this the eoi manipulator can be inserted into
Proc objects, or Proc’s finish member can be
called.
If information sent to the child is not fully be processedd by the
child process then the operating system issues a Broken pipe message,
indicating that information in a pipe was lost, ending the program. The
Proc class’s member pipeSignal can be used to suppress
the Broken pipe message.
Arguments passed to child processes may be surrounded by double or
single quotes. Arguments surrounded by double quotes have their double
quotes removed, while interpreting any escape-sequences that may have been
used within. Arguments surrounded by single quotes have their single quotes
removed, while accepting their content as-is. In addition unquoted
escape-sequences may be specified: those escape sequences are evaluated and
replaced by their intended characters (e.g., \100 is converted to
@).
A full command specification may also be surrounded by backtics
(`-characters). These backtick characters are removed by the
Proc object when the command starts.
Child processes may be allotted a limited amount of time (in
seconds) to complete. By default no time limit is imposed upon child
processes. If a time limit is specified then the child process, if still
running after the specified number of seconds, is ended by sending it a
SIGTERM signal, followed by a SIGKILL signal (cf.
signal(7)).
By default the standard input, output and error streams of child
processes are handled by their Proc parent processes: information
inserted into the Proc object is forwarded to the child
process’s standard input stream, information sent by the child
process to its standard output and error streams are either forwarded to the
corresponding streams of the parent process, or they can be processed by
streams, configured by the Proc object.
Multiple Proc processes can be combined using the pipe
operator (i.e., the | operator). When used, the standard output stream of
the left-hand side (lhs) Proc object is used as the standard input
stream of the right-hand side (rhs) Proc object. Since the
Proc objects start their own child processes, this effectively boils
down to the output of the lhs’s child process being used as the input
of the rhs’s child process. The leftmost Proc object may also
read its input (using the pipe operator) from an istream object or
from a file whose name (path) is specified as the most lhs argument of a
pipe expression. Likewise, the rightmost Proc object may pipe its
standard output to an existing ostream object or to a file whose name
(path) is specified as the most rhs argument of a pipe expression.
Proc objects use Pipe objects (cf.
pipe(3bobcat)) for communication with their child processes. To
ensure that these pipes are properly closed the members waitForChild,
stop or the eoi manipulator should be used. Once a Proc
object ceases to exist pipes to its child process are also closed.
FBB
All constructors, members, operators and manipulators, mentioned in this
man-page, are defined in the namespace FBB.
FBB::Fork(3bobcat) (private),
std::ostream
The following enumerations are defined by the Proc
class:
enum ProcType:
The enum ProcType defines how a child proc is started or
located. Its values are specified at constructor-time or through the
setProcType member. This enumeration defines the following symbolic
constants:
- o
- NO_PATH:
The program specified as child proc is started as specified, without
searching the elements of the PATH environment variable.
- o
- USE_PATH:
The elements of the PATH environment variable are used when locating
the program specified as child proc.
- o
- USE_SHELL:
The program specified as child proc is called using /bin/sh
-c. When (output) redirection is used with the specified command
the IGNORE_COUT IOMode (and possibly also the IGNORE_CERR
IOMode) should be specified.
enum IOMode:
Values of the enum IOMode are used to define which of the
child proc’s standard streams can be accessed through the Proc
object. Its symbolic constants may be combined using the bit_or
operator. By default CIN | COUT | CERR is used (see below).
IOMode arguments may be combined using bit-or
operators.
The following symbolic constants are available:
- o
- ALL:
Shortcut for CIN | COUT | CERR.
- o
- CIN:
Information inserted into the Proc object is forwarded to its child
proc. If this is not required then CIN should not be
specified.
- o
- CERR:
Information written by the child process to its standard error stream is
made available as Proc’s standard error stream. If this is
not required then CERR should not be specified.
- o
- COUT:
Information written by the child process to its standard output stream is
made available as Proc’s standard output stream. If this is
not required then CERR should not be specified.
- o
- IGNORE_CERR:
Information written by the child proc to its standard error stream is
ignored (i.e., not made available). An std::invalid_argument
exception is thrown if this mode is specified in combination with CERR,
MERGE_COUT_CERR, and/or REPLACE.
- o
- IGNORE_COUT:
Information written by the child proc to its standard output stream is
ignored. An std::invalid_argument exception is thrown if this mode
is specified in combination with COUT, MERGE_COUT_CERR
and/or REPLACE.
- o
- IGNORE_COUT_CERR:
Shortcut for IGNORE_CERR | IGNORE_COUT.
- o
- MERGE_COUT_CERR:
Information written by the child process to its standard output and standard
error streams is made available at the Proc object’s
standard output stream. An std::invalid_argument exception is
thrown if this mode is specified in combination with COUT, CERR,
IGNORE_COUT, IGNORE_CERR or REPLACE.
- o
- NONE:
The Proc object does not insert information into the standard input
streams of its child process and information written by the child process
to its standard output or error streams is not forwarded to the
Proc object. Instead, the child process processes its standard
streams by itself. When this mode is specified in combination with other
IOMode values it is silently ignored.
- o
- REPLACE:
When starting a child proc (see below at the member start) the
current process (i.e., the program defining the Proc object) is
replaced by the child process, inheriting the current process’s
standard input and output streams. If this mode is specified in
combination with any other IOMode (except for NONE, see
below) an std::invalid_argument exception is thrown.
Note that child processes are not started automatically
following the construction of t(Proc) objects. A start member or the
assignment operator (see below) is used to start child processes.
Once a Proc object has been constructed its parameters can
be changed using set-member functions or start members.
- o
- explicit Proc(std::string const &command = "",
IOMode mode = ALL, ProcType type = NO_PATH, size_t bufSize =
200, size_t timeLimit = 0, bool pipeSignal = true):
The parameter bufSize defines the size of the streambuf
buffers used by the Proc object. The timeLimit specifies the
maximum execution time of a child process in seconds; when timeLimit ==
0 no execution time limit is used. When pipeSignal == true
incomplete processing of information sent to or read from the child
process results in a Broken pipe exception, terminating the
program. When specifying false the Broken pipe exception is
suppressed, and the input and/or output streams do not have to be
completely processed (see also pipeSignal’s description).
Copy and move constructors (and assignment operators) are not
available.
- o
- Proc &operator<<(Type value):
This operator inserts value into the child’s standard input
stream. I.e., the child proc reads value from its standard input. A
value of any type that can be inserted into an ostream can be
inserted into a Proc object. Nothing happens if the member is used
when the child proc has terminated. Manipulators like std::endl are
also supported. The behavior of this operator is undefined when IOMode
CIN has not been specified.
- o
- Proc &operator+=(std::string const &):
This operator adds the provided std::string object to the currently
defined command specification of a Proc object. The member
operator+= does not add a separating blank space between the
currently stored command specification and the text to append. It merely
adds its right-hand side string to the command stored so far. It does not
affect a currently running child process.
- o
- int operator=(std::string const &cmd):
The operator= member defines cmd as the stored command in a
Proc object, and thereupon starts `cmd’ as its child
process.
- Before starting the child process a possibly active child process is first
stopped by calling stop. It returns stop’s return
value. Immediately after calling stop the new command (cmd)
is started. If ending and restarting another command should be separate
actions then use finish or stop followed by
setCommand, followed by calling an appropriate overloaded version
of the member start.
- o
- Return operator|(Proc &lhs, Proc &rhs):
This operator implements piping. Information sent by lhs to
its standard output is used as the standard input of the
rhs’s child process. The Return value is rhs
if the expression is followed by another pipe-operator or it is
void.
- o
- Return operator|(std::istream &in, Proc &proc):
This operator implements piping. Information read from in is
read by proc’s child process. The Return value is
proc if the expression is followed by another pipe-operator or it
is void.
- o
- Return operator|(std::string const &fname, Proc &proc):
This operator implements piping. information in the file whose file
(path) name is fname is read by proc’s child process.
The Return value is proc if the expression is followed by
another pipe-operator or it is void.
- o
- void operator|(Proc &proc, std::ostream &out):
This operator implements piping. Information sent by
proc’s child process to its standard output stream is
written to out.
- o
- void operator|(Proc &proc, std::string &fname):
This operator implements piping. Information sent by
proc’s child process to its standard output stream is
written to the file whose file (path) name is fname.
The pipe (|) operator mimics the pipe-operator supported by most
command-shell programs and should not be confused with the bit-or
operator. The pipe operator allows constructions like
p1 | p2 | p3 // piping 3 Proc objects
cin | p1 | p2 | cout // p1 reads cin, p2 writes cout
inName | p1 | outName // inName: file name of the file
// read by p1, outName: file name
// of the file written by p1
When using the pipe operator Proc objects reading input
automatically specify their CIN modes, while Proc objects
writing their standard output automatically specify their COUT modes.
Following the pipe-expression the IOMode specifications which were
specified before the pipe-expression are restored.
- o
- bool active():
If the child proc is currently running true is returned and and
false if not.
- o
- void cerrMode(char const *lab) const:
The label lab, followed by the a textual representation of the
currently configured IOMode is inserted into std::cerr.
- o
- void cerrPipes(char const *lab) const:
The text Proc, followed by the Proc’s id, followed by
label lab, followed by the currently active read and write file
descriptors of the pipes currently used by the Proc object are
inserted into std::cerr.
- o
- std::string const &cmd() const:
The currently specified child-process starting command is returned.
- o
- int exitStatus() const:
The last child-process’s exit-status is returned. If a child process
is currently running or if no child process has yet been started -1 is
returned.
- o
- int finish():
Waits until a currently active child process has ended and returns its exit
status. If the child process isn’t currently running -1 is
returned.
- o
- IOMode ioMode() const:
The IOMode currently used by the Proc object is returned.
- o
- std::string mode() const:
The IOMode currently used by the Proc object is returned as a
text-string.
- o
- int pid() const:
The child process’s process-id is returned. The returned value is
undefined if no child process has yet been started. If the child process
has already completed the last child process’s id is returned.
- o
- void pipeSignal(bool on):
When incompletely forwarding information to a child process or incompletely
reading information from a child process a Broken pipe may
result, ending the currently running program. To avoid this,
pipeSignal(false) can be called. To reactivate recognizing broken
pipes pipeSignal(true) can be called. After using
pipeSignal(false) failing insertions into a Proc object
result in its member good returning false, and its members
bad and fail returning true.
- o
- size_t procIdx() const:
Every constructed Proc object receives its own construction-order
index. The first Proc object constructed in a program gets index
value 0.
- o
- ProcType procType() const:
The ProcType used when starting child processes is returned.
- o
- void setBufSize(size_t bufSize):
The stream buffer size in bytes used by streams communicating with child
processes is set to bufSize. A zero byte buffer size is silently
changed into one.
- o
- void setCommand(std::string const &cmd):
The (initial part of a) child process command specification is set to
cmd. After calling this member operator+= can be used to
append additional text to the command specification.
- o
- void setIOMode(IOMode mode):
The IOMode used when calling child processes is set to mode.
Note that pipe-expressions may modify the mode of Proc
objects while the pipe-expression is executed. For details see the end of
the OVERLOADED OPERATORS section.
- o
- void setProcType(ProcType type):
The ProcType used when starting child processes is set to
type.
- o
- void setTimeLimit(size_t timeLimit):
The execution time limit of child processes is set to timeLimit (in
seconds). No time limit is used when timeLimit 0 is specified. The
time limit set by setTimeLimit is used when starting the next child
process. When calling setTimeLimit then pipeSignal(timeLimit ==
0) is automatically called. If that’s not intended, then
explicitly call pipeSignal after calling setTimeLimit.
- o
- void start(size_t timeLimit, IOMode mode = ALL, ProcType type =
NO_PATH, size_t bufSize = 200):
The currently specified command is started using the specified timeLimit,
IOMode, ProcType and bufSize arguments. The start
members do not alter the currently configured default values of their
arguments.
- If a child process is still active when start is called it first
calls stop to end the currently running child process
- o
- void start(IOMode mode, ProcType type = NO_PATH, size_t bufSize
= 200):
Same as the previous start member, but using the currently configured
timeLimit and requiring the specification of the IOMode to
use.
- o
- void start():
Same as the first start member, but using the currently configured
timeLimit, IOMode, ProcType and bufSize values.
- o
- int stop():
A currently active child process is ended by calling Fork::endChild
(see also fork(3bobcat)).
- o
- void system(size_t timeLimit, IOMode mode = ALL, size_t bufSize
= 200):
The currently stored command is executed as a command of sh(1), using
the specified process-arguments.
- o
- void system(IOMode mode = ALL, size_t bufSize = 200):
Same as the previous system command, but using the default
timeLimit specification.
- o
- size_t timeLimit() const:
The currently configured execution time limit of Proc’s child
process is returned. The return value zero indicates that no time limit is
used.
- o
- void useErr(std::ostream &out):
The standard error output produced by the child process is sent to
out. If the Proc object had specified IGNORE_CERR
then that IOMode is unset, and the CERR mode is set.
- o
- void useErr(std::string const &fname):
Same as the previous member, but the child’s standard error output is
written to the file (path) fname.
- o
- void useMerge(std::ostream &out):
The standard output and standard error output produced by the child process
is sent to out. If the Proc object had specified CERR,
COUT, IGNORE_CERR, or IGNORE_COUT then those IOModes are
unset, and the MERGE_COUT_CERR mode is set.
- o
- void useMerge(std::string const &fname):
Same as the previous member, but the child’s standard output and
standard error output is written to the file (path) fname.
- o
- void useOut(std::ostream &out):
The standard output produced by the child process is sent to out. If
the Proc object had specified IGNORE_COUT then that
IOMode is unset, and the COUT mode is set.
- o
- void useOut(std::string const &fname):
Same as the previous member, but the child’s standard output is
written to the file (path) fname.
- o
- int waitForChild():
This member calls the identically named member from the class
FBB::Fork, waiting for a child process to end. When calling
finish or using pipe-expressions waitForChild is
automatically called.
All examples should start with:
#include <iostream>
#include <bobcat/proc>
using namespace std;
using namespace FBB;
The first example illustrates how a program only producing output
can be called. Its child proc simply is /bin/ls:
int main()
{
Proc proc("/bin/ls -Fla", Proc::COUT);
proc.start();
}
The next example illustrates a child program that’s given a
limited amount of execution time: lines entered at the keyboard are echoed
to the standard output stream for at most 5 seconds:
int main()
{
Proc proc("/bin/cat", Proc::CIN | Proc::COUT);
proc.setTimeLimit(5);
proc.start();
while (true)
{
cout << "? ";
string line;
if (not getline(cin, line))
return 0;
proc << line << endl; // to /bin/cat
if (not proc.good())
{
cout << "child time limit exceeded\n";
break;
}
}
cout << "/bin/cat time limit of 5 seconds reached: child proc ended\n";
}
Piping is illustrated next: information at the program’s
standard input is piped to a second Proc object, writing its standard
output to the program’s standard output stream:
int main()
{
Proc proc1{ "/bin/cat" };
Proc proc2{ "/bin/cat" };
cin | proc1 | proc2; // By default piping to cout. To do that
// explicitly use ’... | proc2 | cout’
}
bobcat/proc - defines the class interface
bobcat(7), execle(3), fork(3bobcat),
process(3bobcat), ostream(3fork), sh(1)
- o
- https://fbb-git.gitlab.io/bobcat/: gitlab project page;
- o
- bobcat_6.04.00-x.dsc: detached signature;
- o
- bobcat_6.04.00-x.tar.gz: source archive;
- o
- bobcat_6.04.00-x_i386.changes: change log;
- o
- libbobcat1_6.04.00-x_*.deb: debian package containing the
libraries;
- o
- libbobcat1-dev_6.04.00-x_*.deb: debian package containing the
libraries, headers and manual pages;
Bobcat is an acronym of `Brokken’s Own Base Classes And
Templates’.
This is free software, distributed under the terms of the GNU
General Public License (GPL).
Frank B. Brokken (f.b.brokken@rug.nl).