NAME¶
FBB::Process - Runs external programs
SYNOPSIS¶
#include <bobcat/process>
Linking option:
-lbobcat
DESCRIPTION¶
The
FBB::Process class offers an elaborate interface to external programs
and/or scripts from a
C++ program (so-called
child-processes).
The class offers an easy to use, stream-based interface to the child
process’s standard input, standard output and standard error streams.
Objects of the
FBB::Process class use standard process-executing
functions, like
sh(1) and members of the
execl(1) family to
execute the child process, and allow
shell-scripts to be executed as
well.
The standard input, output and error streams of executed child processes may be
accessed via their
Process parent objects. Input expected by the child
process may be inserted into the
Process object, output generated by
the child process may be extracted from the
Process object.
Process objects cannot use these streams to communicate with the child
process’s standard streams when the child processes themselves redirect
their standard streams.
When using (output) redirection with the
USE_SHELL path specification
(see below for the path and IOMode specifications) the
IGNORE_COUT
IOMode (and possibly
IGNORE_CERR) will normally be specified as
well. See also section
PIPING below.
The same
Process object may be used repeatedly to execute the same or
different child processes in sequence. If a previously started child process
is still active it will first be terminated. It is also possible (using the
stop member) to end a child process explicitly.
Programs to call as child processes may be specified using
Process’s constructors. The child processes are not started by
Process constructors. To start a child process the
start members
or the assignment operator may be used.
Some child processes continue until their standard input streams are exhausted.
The
close member is provided to close such streams, thus ending such
child processes.
The class
Process cannot be used to construct
daemons as
Process’s destructor forcefully terminates its child process. To
create daemon processes the
Fork(3bobcat) class can be used.
Command line arguments passed to child processes may be surrounded by double or
single quotes. Arguments surrounded by double quotes will have their double
quotes removed, interpreting any escape-sequences that may have been used
within. Arguments surrounded by single quotes will have their single quotes
removed, accepting their contents unmodified.
Child processes may be allowed a limited amount of time (in seconds) to
complete. Alternatively, child processes may have no time limit imposed upon
then. A child process is forcefully terminated when its parent
Process
object goes out of scope.
Process makes
FBB::Fork’s
waitForChild member available, which may be used to prevent a premature
termination of a child process.
If
waitForChild is not called but information sent to the child which
could not be fully processed by the child process because the child process
terminated as a result of the
Process object going out of scope, then
the operating system issues a
Broken pipe message, indicating that
information in a pipe was lost.
By default the standard input and output streams of child processes are accessed
from their
Process parent processes: information inserted into the
Process object is forwarded to the child process’s standard input
stream, information sent by the child process to its standard output stream
can be extracted from its parent
Process object.
NAMESPACE¶
FBB
All constructors, members, operators and manipulators, mentioned in this
man-page, are defined in the namespace
FBB.
INHERITS FROM¶
FBB::Fork(3bobcat) (private),
FBB:IOStream(3bobcat)
ENUMERATIONS¶
enum ProcessType:
This enumeration has the following values:
- o
- NO_PATH:
This value indicates that the external program should be called as
specified, without searching the elements in the PATH environment
variable.
- o
- USE_PATH:
This value indicates that the PATH environment variable should be
used to locate the external program to be executed.
- o
- USE_SHELL:
This value indicates that the external program should be called as a command
(using its -c option) to /bin/sh. When (output) redirection
is used with the specified command the IGNORE_COUT IOMode (and
possibly the IGNORE_CERR IOMode as well) should be specified.
enum IOMode:
The
IOMode specification is used to define which of the standard streams
used by child processes are accessed through the
Process object.
Sensible combinations may be formed using the
bit_or operator. If no
IOMode is specified, then
CIN | COUT | CERR is used (see below).
This is also used by
Process’s default constructor.
This enumeration defines the following values:
- o
- CIN:
Information inserted into the Process object is forwarded to its
child process. If this is not required then the CIN specification
can be omitted (but note IGNORE_ALL below).
- o
- CERR:
Information written by the child process to its standard error stream is
accessible through the cerr member. If this is not required then
the CERR specification can be omitted (but note IGNORE_ALL
below).
- o
- COUT:
Information extracted from the Process object was written by the
child process to its standard output stream. If this is not required then
the COUT specification can be omitted (but note IGNORE_ALL
below).
- o
- DIRECT:
When starting the child process (see below at the member start) the
current process is replaced by the child process, inheriting the current
process’s standard input and output streams. When this mode is
specified in combination with other IOMode values (except for
STD, see below) an std::invalid_argument exception is
thrown.
- o
- IGNORE_CERR:
Information written by the child process to its standard error stream is
sent to /dev/null. This specification is silently ignored if either
CERR or MERGE_COUT_CERR were specified.
- o
- IGNORE_COUT:
Information written by the child process to its standard output stream is
sent to /dev/null. This specification is silently ignored when
either COUT or MERGE_COUT_CERR were specified.
- o
- MERGE_COUT_CERR:
Information extracted from the Process object is written by the child
process to its standard output and standard error streams.
- o
- STD:
The Process object will not extract information from or insert
information into the standard streams of its child process. The child
process read from the same standard input stream and write to the same
standard output streams as used by its parent Process object. When
this mode is specified in combination with other IOMode values it
is silently ignored. The IOMode enumeration also defines the
enumeration values IN_PIPE, OUT_PIPE and
CLOSE_ON_EXEC. These enumeration values are ignored when specified
by users of the class Process and are for internal use only.
enum ChildOutput:
The
ChildOutput enumeration defines values returned by the
available member (see below) indicating to which standard stream the
child process has written information. This enumeration defines the following
values:
- o
- NOTHING_AVAILABLE:
This value indicates that the child process did not (yet) write any
information to its standard streams;
- o
- CHILD_COUT:
This value indicates that the child process did write information to its
standard output stream which is waiting for extraction.
- o
- CHILD_CERR:
This value indicates that the child process did write information to its
standard error stream which is waiting for extraction. The latter two
values may be combined using the bit_or operator indicating that
information on both standard streams is available.
TYPE¶
- o
- IOMode:
Combinations of values of the enum IOMode may be used as value of a
variable of this type. In functions expecting an IOMode argument
the empty set should not normally be specified. To specify multiple
IOMode values the bit_or operator should be used.
PROCESS PARAMETERS¶
When running a child process three process parameters may be specified: the
child streams to access from the
Process object (as an
IOMode
value); the way to locate or start the child program (as a
ProcessType
value); and the maximum time (in seconds) the child program is allowed to run.
Unless specified otherwise, all the child’s standard streams (standard
input, output and error) are accessible from the
Parent process; the
PATH environment variable will
not be used to locate the child
program to be executed (often resulting in the requirement to provide an
absolute path to the intended program) and the child processes will be allowed
unlimited time to run.
Following the construction of a
Process object all default parameter
values may be modified. Process parameters may be altered for a single process
or the general defaults may be modified. The
setXXX members (see below)
may be used to change the default process parameters. When process parameters
are specified otherwise they will be active for the next process only.
CONSTRUCTORS¶
The command that may be provided to the following constructors may be the
(initial part of the) specification of an external program to run. When the
program is eventually started it may start and end with a
back-tick (
`). The back-ticks will be removed just before the specified program is
executed.
A child process is
not started automatically following the object
construction. A
start member or the assignment operator (see below) can
be used to start the specified child process.
- o
- Process(std::string const &cmd = ""):
This constructor can also be used as default constructor. It can be used to
specify the (initial part of a) command to execute from a Process
object. Standard default values are used for the process parameters (see
section PROCESS PARAMETERS).
- o
- Process(IOMode mode, std::string const &cmd =
""):
This constructor requires the specification of the object’s initial
default IOMode setting and it can be used to specify the (initial
part of a) command to execute from a Process object. Standard
default values are used for the remaining two process parameters ((
NO_PATH) and no time limit imposed on the child process).
- o
- Process(IOMode mode, ProcessType type, std::string const
&cmd = ""):
This constructor requires the specification of the object’s initial
default IOMode setting and ProcessType and it can be used to
specify the (initial part of a) command to execute from a Process
object. By default no time limit will be imposed upon the child
process.
- o
- Process(IOMode mode, ProcessType type, size_t
timeLimit, std::string const &cmd = ""):
This constructor requires the specification of the object’s initial
default IOMode setting, ProcessType and time limit imposed
upon child processes it can be used to specify the (initial part of a)
command to execute from a Process object. To prevent a time limit
from being imposed upon the child process specify a time limit of 0
(zero).
- The class Process does not offer copy and move
constructors.
OVERLOADED OPERATORS¶
- o
- Process &operator<<(Type value):
This operator inserts value into the child’s standard input
stream. I.e., the child process reads value from its standard
input. A value of any type that can be inserted into an ostream can
be inserted into a Process object. Nothing happens if the member is
used when the child process has terminated. The behavior of this operator
is undefined unless IOMode CIN was specified.
- o
- Process &operator>>(Type value):
This operator extracts value from the child’s standard output
stream and optionally (if IOMode MERGE_COUT_CERR was specified)
from the child’s error stream. I.e., value may be extracted
from Process objects. A value of any type that can be extracted
from an istream can be extracted from a Process object.
Nothing happens if the member is used when the child process has
terminated. The behavior of this operator is undefined unless IOMode
COUT or MERGE_COUT_CERR was specified.
- o
- Process &operator+=(std::string const &):
This operator adds the provided std::string object to the command
specification currenly stored in a Process object. The currently
stored command specification may be redefined using the member
setCommand (see below). 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
Process object. If the command starts and ends with a
back-tick ( `) then the back-ticks are removed, and the
resulting contents are interpreted as a command to execute.
Next it will call stop (see below) to end any ongoing process
followed by calling start to execute the newly defined command
using the current default process parameters. It returns
stop’s return value.
- o
- Process &operator()(iomode mode):
This operator changes the IOMode of the next child process. It
returns the Process object allowing constructions like
process(COUT) = "/bin/cat";
to start a new child process with the specified IOMode.
- o
- Process &operator()(iomode mode, ProcessType
type):
This operator changes the IOMode and ProcessType process
parameters of the next child process.
- o
- Process &operator()(iomode mode, ProcessType type,
size_t timeLimit):
This operator changes all three process parameters of the next child
process. Time limit 0 prevents a time limit from being imposed upon the
next child process.
- o
- Process &operator|(Process &lhs, Process
&rhs):
This operator implements piping: information sent to the
lhs’s standard output is passed on to the rhs’s
standard input. The operator returns rhs. This operator mimics the
piping-operator supported by most command-shell programs and should not be
confused with the binary-or operator. Before returning, the
lhs’s child process is started, but the rhs’s
child process isn’t.
- Since the operator is left-associative and rhs is
returned piping can be chained, allowing constructions like p1 |
p2 | p3, where p1, p2 and p3 are Process
objects.
- The following idiom can be used to start the execution of
the chain of processes: (p1 | p2 | p3).start(). Alternatively, the
following two-step procedure can be used:
p1 | p2 | p3;
p3.start();
- If p1 specifies Process::CIN then this
IOMode is forwared to the final process of the chain of processes.
It is not necessary to specify Process::CIN for p3. In fact,
all IOMode flags of processes passed to operator| are
ignored and possibly modified except for
Process::IGNORE_CERR and Process::CERR (for all processes),
Process::CIN (for the first process of the chain) and
Process::COUT (for the last process of the chain).
- The following example illustrates how input can be inserted
into the first process from a main process and sent to the standard output
stream by the final process. Note that, due to the forwarding of
Process::CIN information must actually be inserted into the final
process, p3:
using namespace std;
using namespace FBB;
Process p1(Process::CIN, "/bin/cat");
Process p2("/bin/cat");
Process p3(Process::STD, "/bin/cat");
p1 | p2 | p3;
p3.start();
string line;
while (getline(cin, line) && not line.empty())
p3 << line << endl;
p3.close();
p3.waitForChild();
The default overloaded assignment operator is not available.
MEMBERS¶
- o
- bool active():
This member returns true if the child process is currently running
and false if not. It is automatically called from the insertion and
extraction operators and from the cerr member but is available as a
public member as well. It may terminate the child process if the child
process has timed out.
- o
- size_t available():
This member returns immediately. Its return value indicates whether any
information can be obtained from the child process as value(s) from the
enum ChildOutput. NOTHING_AVAILABLE is returned if no
information is ready for extraction. CHILD_COUT is returned if
information from the child process’s standard output stream is
available; CHILD_CERR is returned if information from the child
process’s standard error stream is available; CHILD_COUT |
CHILD_CERR is returned if information from both the standard output
and standard error streams is available.
- o
- std::istream &cerr():
This member may be used to extract information written by the child process
to its standard error stream. This member should only be used when
IOMode CERR was specified for the currently running child process;
otherwise its behavior is undefined.
- o
- void close():
This member may be called from the parent process to close the child’s
input stream. In situations where the child continuously reads information
from its standard input stream this member must be used to inform the
child process that input has terminated. This member should only be used
when IOMode CIN was specified for the currently running child
process; otherwise its behavior is undefined.
- o
- iomode ioMode() const:
This member returns the current default IOMode. Note that the
actual IOMode that will be used may be different from the
default value as the actual value may have been altered using a function
call operator (see operator() above).
- o
- ProcessType processType() const:
This member returns the current default ProcessType. Note that the
actual ProcessType that will be used may be different from
the default value as the actual value may have been altered using a
function call operator (see operator() above).
- o
- size_t timeLimit() const:
This member returns the current default child process time limit. Note that
the actual time limit that will be used may be different from the
default value as the actual value may have been altered using a function
call operator (see operator() above).
- o
- void setCommand(std::string const &cmd):
The setCommand member (re)defines the (initial part of a) command
specification currently stored in an Process object. When the
program is eventually started it may start and end with a back-tick
( `). The back-ticks will be removed just before the specified
program is executed.
The setCommand member will not start the specified command and
operator+= may be used to append the command specification before
the command is eventually executed. Also, this member does not affect a
currently running child process.
- o
- void setIOMode(iomode mode):
This member will change the current default IOMode process parameter
of child processes.
- o
- void setProcessType(ProcessType type):
This member will change the current default ProcessType process
parameter of child processes.
- o
- void setTimeLimit(size_t timeLimit):
This member will change the current default time limit process parameter of
child processes. No time limit will be imposed upon child processes if
timeLimit 0 is specified.
- o
- int start():
The currently specified command is executed using the currently active
process parameters. These process parameters may be modified (either as
new defaults or for the next process only) using overloaded start
members, the system members, function call operator or various
set-members.
Having specified a command to execute, the first white-space delimited
element of the specified command is used as the name of the program to
execute. If the program should be called as a command to be executed by
sh(1), the USE_SHELL ProcessType or a system member
should be used.
If a child process does not terminate by itself (within its allotted amount
of time) it is terminated when it has run for its alloted time; when the
Process object’s start or stop members are
called; when the object’s assignment operator is used; or when the
object goes out of scope.
- o
- int start(IOMode mode):
The currently specified command is executed using the specified
IOMode rather than the currently specified default but otherwise
using the currently specified default process parameters. The specified
IOMode will only be used for the process executed by this
start member.
- o
- int start(IOMode mode, Program program):
The currently specified command is executed using the specified
IOMode and ProcessType as well as the currently specified
child process time limit. The specified arguments will only be used for
the process executed by this start member.
- o
- int start(IOMode mode, Program program, size_t
timeLimit):
The currently specified command is executed using the specified arguments
for the process parameters. The specified arguments will only be used for
the process executed by this start member.
- o
- std::string const &str() const:
This member returns the text of the command currently stored in the
Process object. It shows the command as it will be executed by
start, system or the assignment operator. If the
command’s first and last characters are back-ticks ( `) then
those back-ticks will be removed when the command is actually
executed.
- o
- void system():
This member executes the currently stored command as a command to
sh(1) (therefore executing the command as a shell command). When
using system redirections can be included in the command itself
(although this might render the redirected streams implied by the current
IOMode) useless. The currently set process parameters are used when
sh(1) is executed. Calling system implies calling
start.
- o
- void system(IOMode mode):
This member executes the currently stored command as a command to
sh(1) (cf. system above) using the specified IOMode
rather than the current default IOMode setting. The currently
specified default time limit, however, will be used when executing the
sh(1) process.
- o
- void system(IOMode mode, size_t timeLimit):
This member executes the currently stored command as a command to
sh(1) (cf. system above) using the specified IOMode
and time limit values rather than their current default settings.
- o
- int stop():
This member terminates a currently active child process. The child process
is twice sent a SIG_TERM signal, followed by a SIG_KILL
signal. This member’s return value is the exit-value of the child
process that was stopped. It is underfined if it was called without a
running child process.
Following stop a new command may be called using start,
system or the assignment operator (see earlier). Those members will
first call stop so when the intention is to start another child
process calling stop can be skipped. Also, stop is called
when the Process object goes out of scope.
- o
- int waitForChild():
This member is inherited from the class FBB::Fork and will wait for a
child process to finish. It can be used to prevent premature termination
of a child process before calling stop. It is not always required
to use waitForChild. E.g., when a process writes to its standard
output stream and all output has been read then the child process can be
stopped without calling waitForChild.
USING PIPING IN COMMANDS¶
When specifying multiple commands using the piping operator (
’|’)
USE_SHELL must be specified as piping using the
piping operator is a shell-feature.
The additional shell process may be avoided by explicitly setting up the
stdin-stdout piping using
Process’s
operator|.
EXAMPLE¶
#ifdef BOBCAT
#include <bobcat/process>
#else
#include "process"
#endif
#include <string>
#include <iostream>
#include <climits>
using namespace std;
using namespace FBB;
void prompt(char const *task)
{
cout << "Press Enter to start " << task << endl;
cin.ignore(INT_MAX, ’\n’);
}
int main(int argc, char **argv)
try
{
cout << "Size of Process: " << sizeof(Process) << endl;
string line;
// Nota bene: without IOMode you get CIN, COUT and CERR
Process p1(Process::CIN, "/bin/cat");
Process p2(Process::STD, "/bin/cat");
Process p3(Process::STD, "/bin/cat");
prompt("sending lines (until empty) to cat | cat | cat");
(p1 | p2 | p3).start();
while (getline(cin, line) && not line.empty())
{
cout << "Entering " << line << endl;
p3 << line << endl;
}
p3.close();
p3.waitForChild();
Process process(Process::CIN | Process::COUT,
"/usr/bin/sha1sum");
prompt("sha1sum");
process.start();
process << "Hello world\n"; // input to sha1sum
process.close();
process >> line; // retrieve the value
cout << line << endl;
process.stop();
prompt("cat, ignoring its output");
process.setCommand("/bin/cat");
process.setIOMode(Process::CIN | Process::IGNORE_COUT);
process.start();
process << "Hello world\n"; // input to sha1sum
process.close();
line.clear();
if (process >> line) // retrieve the value
cout << ">>>" << line << "<<<" << endl;
process.stop();
// if (argc > 1) // sending an e-mail
// {
// cout << "Sending mail to " << argv[1] << endl;
// prompt("/usr/bin/mail");
// process.setCommand("/usr/bin/mail -s ’from Process’ ");
// process += argv[1];
// process.start(Process::CIN);
// process << "This mail was sent by the process drive\n";
// process << "It consists of multiple lines of text\n";
// process.close();
// process.waitForChild();
// }
prompt("5 seconds IO to /bin/cat");
process.setIOMode(Process::CIN | Process::COUT);
process.setTimeLimit(5); // change time limit
process = "/bin/cat";
while (process.active())
{
cout << "? ";
getline(cin, line);
process << line << endl; // to /bin/cat
line.clear();
if (!getline(process, line)) // from /bin/cat
break;
cout << "Received: " << line << endl;
}
cout << "/bin/cat forcefully terminated\n";
process.setTimeLimit(0);
cout << "3 times running /bin/ls\n";
for (size_t trial = 0; trial < 3; ++trial)
{
prompt("ls");
process(Process::COUT) = "/bin/ls";
cerr << process.str() << endl;
size_t count = 0;
while (getline(process, line))
cout << ++count << ": " << line << endl;
}
}
catch (Errno const &err)
{
cerr << "EXCEPTION CAUGHT: " << err.why() << endl;
return 1;
}
catch (bool)
{
return 0;
}
catch (...)
{
cerr << "Unrecognized exception in main()\n";
return 0;
}
FILES¶
bobcat/process - defines the class interface
SEE ALSO¶
bobcat(7),
execle(3),
fork(3bobcat),
iostream(3fork),
sh(1)
BUGS¶
With the release of Bobcat 1.21.1 the class
Process was completely
rewritten. The new implementation, however, should not affect existing
programs other than that
Process will no longer impose a limited
time-to-live upon child processes. The interface was enlarged, but this should
not affect existing programs. The internal organization of the
Process
class
has changed though, requiring recompilation of sources defining
Process class type objects and linking dynamically to the
Bobcat
library.
With the release of Bobcat 2.11.0 another major modification of
Process
was realized. Although
Process’s internal organization was again
modified this does not affect exeisting programs using
Process objects.
No recompilation of existing sources using
Process is required.
DISTRIBUTION FILES¶
- o
- bobcat_3.01.00-x.dsc: detached signature;
- o
- bobcat_3.01.00-x.tar.gz: source archive;
- o
- bobcat_3.01.00-x_i386.changes: change log;
- o
- libbobcat1_3.01.00-x_*.deb: debian package holding
the libraries;
- o
- libbobcat1-dev_3.01.00-x_*.deb: debian package
holding the libraries, headers and manual pages;
- o
- http://sourceforge.net/projects/bobcat: public
archive location;
BOBCAT¶
Bobcat is an acronym of `Brokken’s Own Base Classes And Templates’.
COPYRIGHT¶
This is free software, distributed under the terms of the GNU General Public
License (GPL).
AUTHOR¶
Frank B. Brokken (
f.b.brokken@rug.nl).