diff -Nru bobcat-3.18.01/CLASSES bobcat-3.19.01/CLASSES --- bobcat-3.18.01/CLASSES 2013-11-19 07:51:36.000000000 +0000 +++ bobcat-3.19.01/CLASSES 2013-12-28 10:19:31.000000000 +0000 @@ -64,6 +64,8 @@ pf_iteratorstream pipe primefactors +processenums +processdata process ptriter randbuffer diff -Nru bobcat-3.18.01/INSTALL.im bobcat-3.19.01/INSTALL.im --- bobcat-3.18.01/INSTALL.im 2013-11-19 07:51:36.000000000 +0000 +++ bobcat-3.19.01/INSTALL.im 2013-12-28 10:19:31.000000000 +0000 @@ -26,7 +26,8 @@ // The options "-isystem tmp" must always be used, are set in // icmake/library and should not be altered. -#define PTHREAD "sharedmutex sharedblock sharedmemory sharedsegment" +#define PTHREAD "sharedmutex sharedblock sharedmemory sharedsegment " \ + "process processdata" // Classes requiring -lpthread #define LDFLAGS "-lpthread" diff -Nru bobcat-3.18.01/VERSION bobcat-3.19.01/VERSION --- bobcat-3.18.01/VERSION 2013-11-22 08:13:02.000000000 +0000 +++ bobcat-3.19.01/VERSION 2013-12-30 10:19:00.000000000 +0000 @@ -1,3 +1,3 @@ -VERSION=3.18.01 +VERSION=3.19.01 YEARS=2005-2013 diff -Nru bobcat-3.18.01/changelog bobcat-3.19.01/changelog --- bobcat-3.18.01/changelog 2013-11-22 08:15:46.000000000 +0000 +++ bobcat-3.19.01/changelog 2013-12-30 10:18:36.000000000 +0000 @@ -1,3 +1,20 @@ +bobcat (3.19.01) + + * Fixed Process's d_closedByChild initialization (used by FreeBSD systems). + + -- Frank B. Brokken Mon, 30 Dec 2013 11:17:50 +0100 + +bobcat (3.19.00) + + * Added Signal::remove, removing a previously added signal handling object. + + * Redesigned Process so that it (partially) uses the pimpl idiom. Also added + the eoi manipulator and several new member functions. + + * Updated man-pages for Pipe, Redirector, Process, and Signal, + + -- Frank B. Brokken Sat, 28 Dec 2013 11:16:20 +0100 + bobcat (3.18.01) * Fixed a mismatch between SharedMemory::read's declared and defined return diff -Nru bobcat-3.18.01/debian/changelog bobcat-3.19.01/debian/changelog --- bobcat-3.18.01/debian/changelog 2013-11-26 14:21:35.000000000 +0000 +++ bobcat-3.19.01/debian/changelog 2013-12-31 07:07:33.000000000 +0000 @@ -1,9 +1,22 @@ -bobcat (3.18.01-1ubuntu1) trusty; urgency=low +bobcat (3.19.01-1~ppa1) trusty; urgency=low - * Adjusted library order to link, resolving FTBFS (a leftover symptom - of BTS#608145). + * Rebuild for trusty - -- Daniel T Chen Tue, 26 Nov 2013 08:46:11 -0500 + -- Bhavani Shankar Tue, 31 Dec 2013 12:36:53 +0530 + +bobcat (3.19.01-1) unstable; urgency=low + + * New upstream release fixes a Process data member initialization, required + for FreeBSD systems. + + -- Frank B. Brokken Mon, 30 Dec 2013 11:21:58 +0100 + +bobcat (3.19.00-1) unstable; urgency=low + + * New upstream release reimplements Process partially using pimpl, and + updates several man-pages + + -- Frank B. Brokken Sat, 28 Dec 2013 11:23:31 +0100 bobcat (3.18.01-1) unstable; urgency=low diff -Nru bobcat-3.18.01/debian/control bobcat-3.19.01/debian/control --- bobcat-3.18.01/debian/control 2013-11-26 13:45:50.000000000 +0000 +++ bobcat-3.19.01/debian/control 2013-12-30 10:56:44.000000000 +0000 @@ -1,12 +1,11 @@ Source: bobcat Section: libs Priority: optional -Maintainer: Ubuntu Developers -XSBC-Original-Maintainer: Frank B. Brokken +Maintainer: Frank B. Brokken Uploaders: George Danchev , tony mancill Build-Depends: debhelper (>= 9), libmilter-dev (>= 8.14.3), libx11-dev (>= 2:1.1.5-2), libssl-dev, libreadline-dev, - yodl (>= 3.00.0), g++-4.8, icmake (>= 7.19.00), + yodl (>= 3.03.0), g++-4.8 (>= 4.8.1), icmake (>= 7.21.00), hardening-wrapper Standards-Version: 3.9.5 Vcs-Git: git://anonscm.debian.org/collab-maint/bobcat.git diff -Nru bobcat-3.18.01/debian/patches/0001-libadd-pthread-ftbfs.patch bobcat-3.19.01/debian/patches/0001-libadd-pthread-ftbfs.patch --- bobcat-3.18.01/debian/patches/0001-libadd-pthread-ftbfs.patch 2013-11-26 14:05:17.000000000 +0000 +++ bobcat-3.19.01/debian/patches/0001-libadd-pthread-ftbfs.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -Index: bobcat-3.18.01/icmake/special -=================================================================== ---- bobcat-3.18.01.orig/icmake/special 2013-11-13 05:44:52.000000000 -0500 -+++ bobcat-3.18.01/icmake/special 2013-11-26 09:05:11.055508314 -0500 -@@ -78,7 +78,7 @@ - - if (all || gets() == "y") - { -- g_sharedLibReq += " -lssl -lcrypto"; -+ g_sharedLibReq += " -lssl -lcrypto -lpthread"; - addClasses("SSLCLASSES"); - } - } diff -Nru bobcat-3.18.01/debian/patches/series bobcat-3.19.01/debian/patches/series --- bobcat-3.18.01/debian/patches/series 2013-11-26 14:01:35.000000000 +0000 +++ bobcat-3.19.01/debian/patches/series 2013-12-30 10:56:44.000000000 +0000 @@ -1 +0,0 @@ -0001-libadd-pthread-ftbfs.patch diff -Nru bobcat-3.18.01/debian/rules bobcat-3.19.01/debian/rules --- bobcat-3.18.01/debian/rules 2013-11-23 07:53:09.000000000 +0000 +++ bobcat-3.19.01/debian/rules 2013-12-30 10:56:44.000000000 +0000 @@ -10,7 +10,7 @@ # archive downloaded from https://www.icce.rug.nl/debian/bobcat # (bobcat_x.y.z..tar.gz) -MD5TRUSTED := f7f33b30d8be98a6954ab9efea1f7133 +MD5TRUSTED := 7ed75624a11ad4a6ff9c61678619f175 export DEB_BUILD_HARDENING=1 export LDFLAGS = $(shell dpkg-buildflags --get LDFLAGS) diff -Nru bobcat-3.18.01/documentation/man/include/header.yo bobcat-3.19.01/documentation/man/include/header.yo --- bobcat-3.18.01/documentation/man/include/header.yo 2013-11-19 07:51:36.000000000 +0000 +++ bobcat-3.19.01/documentation/man/include/header.yo 2013-12-28 10:19:31.000000000 +0000 @@ -3,6 +3,10 @@ whenhtml((Manpage: url(ARG1(3bobcat))(ARG1.3.html)))\ ) +DEFINEMACRO(verbinsert)(2)(\ + PIPETHROUGH(yodlverbinsert //ARG1 ARG2)()\ +) + DEFINEMACRO(itb)(1)(it() bf(ARG1):nl()) DEFINEMACRO(itt)(1)(it() tt(ARG1)) DEFINEMACRO(itrange)(2)(tt(CHAR(91)ARG1, ARG2+CHAR(41))) diff -Nru bobcat-3.18.01/documentation/man/pipe.yo bobcat-3.19.01/documentation/man/pipe.yo --- bobcat-3.18.01/documentation/man/pipe.yo 2013-04-25 14:44:30.000000000 +0000 +++ bobcat-3.19.01/documentation/man/pipe.yo 2013-12-26 12:37:09.000000000 +0000 @@ -2,19 +2,37 @@ COMMENT(manpage, section, releasedate, archive, short name) manpage(FBB::Pipe)(3bobcat)(_CurYrs_)(libbobcat-dev__CurVers_-x.tar.gz) - (Error handler) + (System Level Communication Pipe) -manpagename(FBB::Pipe)(Defines a system level pipe) +manpagename(FBB::Pipe)(Defines a system level communication pipe) manpagesynopsis() bf(#include )nl() Linking option: tt(-lbobcat) manpagedescription() - bf(FBB::Pipe) objects may be used to construct a em(pipe). bf(FBB::Pipe) + bf(FBB::Pipe) objects may be used to construct a em(pipe). tt(Pipe) objects offer a simple interface to the reading and writing ends of -pipes. bf(FBB::Pipe) objects are object-wrappers around the bf(pipe)(2) system -call. +pipes. tt(Pipe) objects are object-wrappers around the bf(pipe)(2) system +call. + + A tt(Pipe) which is created just before a program forks can be used to set +up a line of communication between the parent and child process. Information +which is written by the child process to its standard output stream can be +redirected to the writing end of the pipe (using the tt(writtenBy) +member). The information appearing at the reading end of the pipe can then be +extracted using, e.g., an tt(IFdStream) object, initialized with the +tt(Pipe)'s reading file descriptor, or the reading end of the pipe can be +redirected to an existing stream whose file descriptor is known, like tt(cin) +(which uses the tt(STDIN_FILENO) file descriptor). + + When a tt(Pipe) object goes out of scope, no bf(close)(2) operation is +performed on the pipe's file descriptors. After setting up the pipe using the +tt(Pipe's) member functions and passing the tt(Pipe's) file descriptors to +code that uses the tt(Pipe's) descriptors, the tt(Pipe) object could in fact +safely be destroyed. If the pipe should be closed at destruction time, a class +could be derived from bf(Pipe)(3bobcat), whose destructor performs the +required closing-operation. includefile(include/namespace) @@ -24,10 +42,10 @@ manpagesection(CONSTRUCTORS) itemization( itb(Pipe()) - The default bf(Pipe()) constructor constructs a basic pipe, calling + The default tt(Pipe) constructor constructs a basic pipe, calling bf(pipe)(2). - This constructor throws an tt(Exception) exception if the default bf(Pipe) + This constructor throws an tt(Exception) exception if the default tt(Pipe) constructor did not properly complete. The thrown bf(Exception) object's tt(which()) member shows the system's tt(errno) value set by the failing bf(pipe)(2) function. @@ -39,38 +57,54 @@ ) The copy constructor is available. - Note that when the pipe goes out of scope, no bf(close)(2) operation is -performed on the pipe's ends. If the pipe should be closed by the desctructor, -derive a class from bf(Pipe)(3bobcat), whose destructor performs the required -closing-operation. - manpagesection(MEMBER FUNCTIONS) + itemization( itb(int readFd() const) Returns the pipe's file descriptor that is used for reading + itb(void readFrom(int filedescriptor)) Sets up redirection from the internal em(read) filedescriptor to the -given filedescriptor: information is read from the bf(FBB::Pipe) object when -reading from the provided filedescriptor. +given filedescriptor: information written to the write-end of the pipe may be +retrieved by extracting the information from the stream that is associated +with the indicated file descriptor. E.g., after the call +tt(readFrom(STDIN_FILENO)) information inserted into the +write-end of the pipe can be retrieved from tt(cin). + itb(void readFrom(int const *filedescriptors, size_t n)) Sets up redirection from the internal em(read) filedescriptor to the -given filedescriptors: information is read from the bf(FBB::Pipe) object when +given filedescriptors: information is read from the tt(Pipe) object when reading from any of the bf(n) provided filedescriptors (experimental). + itb(int readOnly()) Closes the writing end of the pipe, returns the reading end's file -descriptor. +descriptor. This member can be used, e.g., to construct an tt(IFdStream) +object to extract the information that is inserted into the write-end of the +pipe. + itb(void verify() const) - Obsoleted, will be removed in a future Bobcat release. + Obsoleted, can safely be removed from source files. + itb(int writeFd() const) - Returns the pipe's file descriptor that is used for writing + Returns the pipe's file descriptor that is used for writing. + itb(void writtenBy(int filedescriptor)) Sets up redirection from the internal em(write) filedescriptor to the -given filedescriptor: information is written to the bf(FBB::Pipe) object when -writing to the provided filedescriptor. +given filedescriptor: information is written to the tt(Pipe) object when +writing to the provided filedescriptor. E.g., after the call +tt(writtenBy(STDOUT_FILENO)) information sent to the standard output stream (by +either tt(cout) or by a child process (cf. bf(exec)(3))) is inserted into the +write-end of the pipe. + itb(void writtenBy(int const *filedescriptors, size_t n)) Sets up redirection from the internal em(write) filedescriptor to the -given filedescriptors: information is written to the bf(FBB::Pipe) object -when writing to each of the bf(n) provided filedescriptors. +given filedescriptors: information is inserted into the write-end of the +tt(Pipe) object when writing to each of the bf(n) provided filedescriptors. +E.g., when passing an array of two tt(int) values, respectively equal to +tt(STDOUT_FILENO) and tt(STDERR_FILENO) to this member, all information which +is thereafter sent to the standard output or error streams is inserted into +the write-end of the pipe. + itb(int writeOnly()) Closes the reading end of the pipe, returns the writing end's file descriptor. @@ -78,10 +112,12 @@ manpagesection(PROTECTED ENUMERATION) The bf(RW) protected enumeration has the following elements: + itemization( itb(READ) The index in bf(d_fd[]) (see below) of the element holding the pipe's reading file descriptor; + itb(WRITE) The index in bf(d_fd[]) (see below) of the element holding the pipe's writing file descriptor diff -Nru bobcat-3.18.01/documentation/man/primefactors.yo bobcat-3.19.01/documentation/man/primefactors.yo --- bobcat-3.18.01/documentation/man/primefactors.yo 2013-04-25 14:44:30.000000000 +0000 +++ bobcat-3.19.01/documentation/man/primefactors.yo 2013-12-28 10:19:31.000000000 +0000 @@ -135,7 +135,7 @@ manpagesection(EXAMPLE) - verbinsert(../../primefactors/driver/driver.cc) + verbinclude(../../primefactors/driver/driver.cc) If this program is run with argument 1950 it produces the following output: diff -Nru bobcat-3.18.01/documentation/man/process.yo bobcat-3.19.01/documentation/man/process.yo --- bobcat-3.18.01/documentation/man/process.yo 2013-11-13 10:44:52.000000000 +0000 +++ bobcat-3.19.01/documentation/man/process.yo 2013-12-28 12:32:03.000000000 +0000 @@ -11,61 +11,47 @@ Linking option: tt(-lbobcat) manpagedescription() - The bf(FBB::Process) class offers an elaborate interface to external -programs and/or scripts from a bf(C++) program (so-called + The bf(FBB::Process) class offers an extensive interface to calling +external programs and/or scripts from a bf(C++) program (so-called em(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. +to the standard input, standard output and standard error streams of child +processes. - Objects of the bf(FBB::Process) class use standard process-executing -functions, like bf(sh)(1) and members of the bf(execl)(1) family to execute -the child process, and allow em(shell-scripts) to be executed as well. - -The standard input, output and error streams of executed child processes may -be accessed via their tt(Process) parent objects. Input expected by the child -process may be inserted into the tt(Process) object, output generated by the -child process may be extracted from the tt(Process) object. tt(Process) -objects cannot use these streams to communicate with the child process's -standard streams when the child processes themselves redirect their standard -streams. + Objects of the tt(class Process) use standard process-executing functions, +like members of the bf(execl)(1) family or bf(sh)(1) to execute child +processes. Thus, child processes can be executable programs or +em(shell-scripts). + +The standard input, output and error streams of child processes may +be accessed through their tt(Process) parent objects. Input expected by child +processes may be inserted by tt(Process) objects, and output generated by +child processes may be extracted from tt(Process) objects. When using (output) redirection with the tt(USE_SHELL) path specification (see -below for the path and IOMode specifications) the tt(IGNORE_COUT IOMode) (and -possibly tt(IGNORE_CERR)) will normally be specified as well. See also section -bf(PIPING) below. - -The same tt(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 is terminated first. A child process can also explicitly be -ended (using the tt(stop) member). - -Programs to call as child processes may be specified using tt(Process)'s -constructors. The child processes are not started by tt(Process) -constructors. To start a child process the tt(start) members or the assignment -operator may be used. - -Some child processes continue until their standard input streams are -exhausted. The tt(close) member is provided to close such streams, thus ending -such child processes. - -The class tt(Process) cannot be used to construct em(daemon)s as tt(Process)'s -destructor forcefully terminates its child process. To create daemon processes -the bf(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. In addition unquoted -escape-sequences may be specified: those escape sequences are evaluated and -replaced by their intended characters (e.g., tt(\100) is converted to tt(@)). - -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 tt(Process) -object goes out of scope. tt(Process) makes tt(FBB::Fork)'s tt(waitForChild) -member available, which may be used to prevent a premature termination of a -child process. +below for the path and IOMode specifications), the tt(IGNORE_COUT IOMode) (and +possibly tt(IGNORE_CERR)) should normally be specified (see also this +man-page's bf(PIPING) section). + +tt(Process) objects may repeatedly be used to execute the same or different +child processes. Before the next child process is started, the tt(Process) +object first terminates its currently active child process. Alternatively, a +currently active child process is automatically ended if the tt(Process) +object goes out of scope, if its tt(stop) or tt(eoi) (end-of-information) +member is called, or if the tt(eoi) manipulator is inserted into the +tt(Process) object. + +Programs to be called as child processes may be specified at tt(Process's) +constructor-time or through tt(Process's setCommand) member. tt(Process) +constructors (or tt(Process set)-members) never start child processes. Child +processes are started through tt(start) members or the assignment operator. + +Child processes may receive information at their standard input streams +through information inserted into tt(Process) objects. In these cases the +tt(Process) objects must inform their child processes that they have received +all input. For this the tt(close) or tt(eoi) member or the tt(eoi) manipulator +can be used. After calling the tt(close) member, the tt(waitForChild) member +should be called as well. This is not necessary if either the tt(eoi) member +or the tt(eoi) manipulator is used. If tt(waitForChild) is not called (but information sent to the child which could not be fully processed by the child process in case the child process @@ -73,88 +59,129 @@ operating system issues a tt(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 tt(Process) parent processes: information inserted into +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 contents as-is. In addition unquoted +escape-sequences may be specified: those escape sequences are evaluated and +replaced by their intended characters (e.g., tt(\100) is converted to tt(@)). + +A full command specification may be surrounded by backtics +(tt(`)-characters). These backtick characters are removed by the tt(Process) +object when the command is started. + +Child processes may be allowed a limited amount of time (in seconds) to +complete. By default no time limit is imposed upon child processes. + +By default the standard input, output and error streams of child processes are +accessed through their tt(Process) parent processes: information inserted into the tt(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 tt(Process) object. +can be extracted from its parent tt(Process) object, and information sent by +the child process to its standard error stream may be obtained through +tt(Process's childErrStream) member. + +If the parent and child processes have agreed on some communication process, +then information may alternatingly be sent to and received from the child +process through the tt(Process's ostream) and tt(istream) +facilities. Alternatively, unspecified amounts of information written by child +processes may be processed by separate threads (cf. this manual page's +bf(EXAMPLES) section). includefile(include/namespace) manpagesection(INHERITS FROM) bf(FBB::Fork)(3bobcat) (private), nl() bf(FBB:IOStream)(3bobcat) + bf(FBB:ProcessEnums) + +The tt(struct ProcessEnums) defines enumerations and support functions which +are used by several classes. Its enumerations are documented below; there is +no separate bf(ProcessEnums) man-page. manpagesection(ENUMERATIONS) bf(enum ProcessType):nl() - This enumeration has the following values: + + The bf(enum ProcessType) defines how a child process is started or +located. Its values are specified at constructor-time or through the +tt(setProcessType) member. This enumeration defines the following symbolic +constants: itemization( itb(NO_PATH) - The external program should be called as - specified, without searching the elements in the tt(PATH) environment - variable. + The program specified as child process is started as specified, + without searching the elements of the tt(PATH) environment + variable. itb(USE_PATH) - The tt(PATH) environment variable is - used when locating the external program to be executed. + The elements of the tt(PATH) environment variable are used when + locating the program specified as child process. itb(USE_SHELL) - The external program should be called as - a command (using its tt(-c) option) to bf(/bin/sh). When - (output) redirection is used with the specified command the - tt(IGNORE_COUT IOMode) (and possibly the tt(IGNORE_CERR IOMode) as - well) should be specified. + The program specified as child process is called using tt(/bin/sh + -c). When (output) redirection is used with the specified command + the tt(IGNORE_COUT IOMode) (and possibly also the tt(IGNORE_CERR + IOMode)) should be specified. ) bf(enum IOMode):nl() - The tt(IOMode) specification is used to define which of the standard -streams used by child processes are accessed through the tt(Process) -object. Sensible combinations may be formed using the tt(bit_or) operator. If -no tt(IOMode) is specified, then tt(CIN | COUT | CERR) is used (see -below). This is also used by tt(Process)'s default constructor. -This enumeration defines the following values: + Values of the tt(enum IOMode) are used to define which of the child +process's standard streams can be accessed through the tt(Process) object. Its +symbolic constants may be combined using the tt(bit_or) operator. By default +tt(CIN | COUT | CERR) is used (see below). + + The following symbolic constants are available: itemization( + itb(ALL) + Shortcut for bf(CIN | COUT | CERR). itb(CIN) - Information inserted into the tt(Process) object is forwarded to -its child process. If this is not required then the tt(CIN) specification can -be omitted. + Information inserted into the tt(Process) object is forwarded to + its child process. If this is not required then tt(CIN) should + not be specified. itb(CERR) - Information written by the child process to its standard error -stream is accessible through the tt(cerr) member. If this is not required then -the tt(CERR) specification can be omitted. + Information written by the child process to its standard error + stream is accessible through tt(Process's childErrStream) member. + If this is not required then tt(CERR) should not be specified. itb(COUT) - Information extracted from the tt(Process) object was written by -the child process to its standard output stream. If this is not required then -the tt(COUT) specification can be omitted. + Information written by the child process to its standard output + stream may be directly be extracted from the tt(Process) object, + or from its tt(childOutStream) member. If this is not required + then tt(CERR) should not be specified. itb(DIRECT) - When starting the child process (see below at the member tt(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 tt(IOMode) values (except for tt(STD), see below) an -tt(std::invalid_argument) exception is thrown. + When starting a child process (see below at the member tt(start)) + the current process (i.e., the program defining the tt(Process) + 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 tt(IOMode) (except for + tt(STD), see below) an tt(std::invalid_argument) exception is + thrown. itb(IGNORE_CERR) - Information written by the child process to its standard error -stream is sent to tt(/dev/null). This specification is silently ignored if -either bf(CERR) or bf(MERGE_COUT_CERR) were specified. + Information written by the child process to its standard error + stream is sent to tt(/dev/null). An tt(std::invalid_argument) + exception is thrown if this mode is specified in combination with + bf(DIRECT, CERR) and/or bf(MERGE_COUT_CERR). itb(IGNORE_COUT) - Information written by the child process to its standard output -stream is sent to tt(/dev/null). This specification is silently ignored when -either bf(COUT) or bf(MERGE_COUT_CERR) were specified. + Information written by the child process to its standard output + stream is sent to tt(/dev/null). An tt(std::invalid_argument) + exception is thrown if this mode is specified in combination with + bf(COUT, DIRECT) and/or bf(MERGE_COUT_CERR). + itb(IGNORE_COUT_CERR) + Shortcut for tt(IGNORE_CERR | IGNORE_COUT). itb(MERGE_COUT_CERR) - Information extracted from the tt(Process) object is written by -the child process to its standard output and standard error streams. - itb(STD) - The tt(Process) object will not extract information from or insert -information into the standard streams of its child process. The child process -reads the same standard input stream and writes the same standard output -streams as its parent tt(Process) object. When this mode is specified in -combination with other tt(IOMode) values it is silently ignored. - ) - The tt(IOMode) enumeration also defines the enumeration values bf(IN_PIPE, -OUT_PIPE) and bf(CLOSE_ON_EXEC). These enumeration values are ignored when -specified by users of the class tt(Process) and are for internal use only. - + Information extracted from the tt(Process) object is written by the + child process to its standard output and standard error streams. + An tt(std::invalid_argument) exception is thrown if this mode is + specified in combination with bf(COUT, CERR, DIRECT, IGNORE_COUT) + or tt(IGNORE_CERR). + itb(NONE) + The tt(Process) object does not extract information from or insert + information into the standard streams of its child process. The + child process reads the same standard input stream and writes the + same standard output streams as its parent tt(Process) + object. When this mode is specified in combination with other + tt(IOMode) values it is silently ignored. + ) bf(enum ChildOutput):nl() The tt(ChildOutput) enumeration defines values returned by the @@ -163,86 +190,100 @@ values: itemization( itb(NOTHING_AVAILABLE) - The child process did not (yet) write any -information to its standard streams; + The child process did not (yet) write any information to its + standard streams; itb(CHILD_COUT) - The child process did write -information to its standard output stream which is waiting for extraction. + The child process wrote information to its standard output + stream which is waiting for extraction. itb(CHILD_CERR) - The child process did write -information to its standard error stream which is waiting for extraction. + The child process wrote information to its standard error stream + which is waiting for extraction. ) - The latter two values may be combined using the tt(bit_or) operator -indicating that information on both standard streams is available. - -manpagesection(TYPE) - itemization( - itb(IOMode) - Combinations of values of the bf(enum IOMode) may be used as value of a -variable of this type. In functions expecting an bf(IOMode) argument the empty -set should not normally be specified. To specify multiple tt(IOMode) values -the tt(bit_or) operator should be used. - ) + The latter two values may be combined using the tt(bit_or) operator. The +tt(bit_and) operator,returning a tt(bool) value can be used to test whether +information on a specific output stream is available. manpagesection(PROCESS PARAMETERS) -When running a child process three process parameters may be specified: the -child streams to access from the tt(Process) object (as an bf(IOMode) value); -the way to locate or start the child program (as a bf(ProcessType) value); and -the maximum time (in seconds) the child program is allowed to run.nl() - Unless specified otherwise, all the child's standard streams (standard -input, output and error) are accessible from the tt(Parent) process; the -tt(PATH) environment variable will em(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.nl() - Following the construction of a tt(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 tt(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. +Four process parameters may be specified: the sizes of the stream buffers +which are used when communicating with child processes; to specify which of +the standard streams of child processes can be accessed from the tt(Process) +object combinations of tt(IOMode) values are used; to specify how child +programs are found a tt(ProcessType) value is used; to specify the maximum +time (in seconds) the child program is allowed to run a tt(size_t) values is +used. + +By default, the stream buffers hold 200 bytes; all the child's standard +streams (standard input, output and error) are accessible from the tt(Parent) +process; the tt(PATH) environment variable is em(not) used to locate the child +program; and the child processes will be allowed an unlimited amount of time +to run. + +After constructing a tt(Process) object all default parameters may be +modified. These parameters may either be altered for a single process or a +tt(Process) object's general defaults may be modified. The tt(set*) members +(see below) may be used to change the default process parameters. When +parameters are specified otherwise, they will only be active for the next +process. manpagesection(CONSTRUCTORS) + The command 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 em(back-tick) (tt(`)). The back-ticks will be removed just before the specified program is executed. - A child process is em(not) started automatically following the object -construction. A tt(start) member or the assignment operator (see below) is -used to start the specified child process. + Child processes are em(not) started automatically following tt(Process) +object constructions. A tt(start) member or the assignment operator (see +below) is used to start the specified child process. + + The tt(mode) parameter that is defined for the second through fourth +constructor is defined as a tt(size_t) for backward compatibility reasons. +Internally, this argument is immediately converted to a tt(Process::IOMode) +value, silently ignoring values which do not represent valid tt(IOMode) +values. Multiple tt(IOMode) values may be combined using the bit-or operator. + + After constructing a tt(Process) object its parameters can be changed +using tt(set)-member functions, function call operators or tt(start) members. itemization( itb(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 -tt(Process) object. Standard default values are used for the process -parameters (see section bf(PROCESS PARAMETERS)). - - itb(Process(IOMode mode, std::string const &cmd = "")) - This constructor requires the specification of the object's initial -default bf(IOMode) setting and it can be used to specify the (initial part of -a) command to execute from a tt(Process) object. Standard default values -are used for the remaining two process parameters ((tt(NO_PATH)) and no time -limit imposed on the child process). - - itb(Process(IOMode mode, ProcessType type, std::string const &cmd = "")) - This constructor requires the specification of the object's initial -default bf(IOMode) setting and tt(ProcessType) and it can be used to specify -the (initial part of a) command to execute from a tt(Process) object. By -default no time limit will be imposed upon the child process. + This constructor is used to specify the (initial part of a) command to +execute from a tt(Process) object. Default values are used for the +process parameters (see section bf(PROCESS PARAMETERS)). + + itb(Process(size_t mode, std::string const &cmd = "")) + This constructor requires the specification of the object's +bf(IOMode), and it can be used to specify the (initial part of +a) command to execute from a tt(Process) object. Default values +are used for the remaining process parameters (see section bf(PROCESS +PARAMETERS)). + + itb(Process(size_t mode, ProcessType type, std::string const &cmd = "")) + This constructor requires the specification of the object's +bf(IOMode) and tt(ProcessType), and it can be used to specify the (initial +part of a) command to execute from a tt(Process) object. Default values are +used for the remaining process parameters (see section bf(PROCESS +PARAMETERS)). - itb(Process(IOMode mode, ProcessType type, size_t timeLimit, + itb(Process(size_t mode, ProcessType type, size_t timeLimit, std::string const &cmd = "")) - This constructor requires the specification of the object's initial -default bf(IOMode) setting, tt(ProcessType) and time limit imposed upon child -processes it can be used to specify the (initial part of a) command to execute -from a tt(Process) object. To prevent a time limit from being imposed upon the -child process specify a time limit of 0 (zero). - + This constructor requires the specification of the object's +bf(IOMode), tt(ProcessType), and child process time limit. The (initial part +of a) command to execute from a tt(Process) object may optionally be +specified. The default process parameter is used for the sizes of the +internally used stream buffers (see section bf(PROCESS PARAMETERS)). + + itb(Process(IOMode mode, ProcessType type, size_t timeLimit, size_t + bufferSize, std::string const &cmd = "")) + This constructor requires the specification of the object's +bf(IOMode), tt(ProcessType), child process time limit, and size of the +internally used stream buffers. The (initial part of a) command to execute +from a tt(Process) object may optionally be specified. Note that this +constructor's tt(mode) parameter does not accept a tt(size_t) argument. ) - The class bf(Process) does not offer copy and move constructors. + The class bf(Process) does not offer copy or move constructors. manpagesection(OVERLOADED OPERATORS) @@ -265,53 +306,59 @@ undefined unless tt(IOMode COUT) or tt(MERGE_COUT_CERR) was specified. itb(Process &operator+=(std::string const &)) - This operator adds the provided tt(std::string) object to the command -specification currenly stored in a tt(Process) object. The currently stored -command specification may be redefined using the member tt(setCommand) (see -below). The member tt(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. + This operator adds the provided tt(std::string) object to the currenly +defined command specification of a tt(Process) object. The member +tt(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. itb(int operator=(std::string const &cmd)) The tt(operator=) member defines tt(cmd) as the stored command in -a tt(Process) object. If the command starts and ends with a em(back-tick) -(tt(`)) then the back-ticks are removed, and the resulting contents are -interpreted as a command to execute.nl() - Next it calls tt(stop) (see below) to end any ongoing process followed by -calling tt(start) to execute the newly defined command using the current -default process parameters. It returns tt(stop)'s return value. - - itb(Process &operator()(iomode mode)) - This operator changes the tt(IOMode) of the next child process. It -returns the tt(Process) object allowing constructions like +a tt(Process) object. + + Before starting the child process a possibly active child process is first +stopped by calling tt(stop). It returns tt(stop)'s return value. + + itb(Process &operator()(IOMode mode)) + This operator changes the the tt(Process) object's tt(IOMode) +parameter. A reference to the tt(Process) object is returned, allowing +constructions like verb( - process(COUT) = "/bin/cat"; + process(Process::COUT) = "/bin/cat"; ) to start a new child process with the specified tt(IOMode). - itb(Process &operator()(iomode mode, ProcessType type)) - This operator changes the tt(IOMode) and tt(ProcessType) process -parameters of the next child process. - - itb(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. + itb(Process &operator()(IOMode mode, ProcessType type)) + This operator changes the tt(Process) object's tt(IOMode) and +tt(ProcessType) process parameters. + + itb(Process &operator()(size_t mode, ProcessType type, size_t timeLimit)) + This operator changes the tt(Process) object's mentioned process +parameters, silently converting the tt(size_t mode) to an tt(IOMode) +value. The currently specified default size of the stream buffers is kept +as-is. + + itb(Process &operator()(IOMode mode, ProcessType type, size_t timeLimit, + size_t bufferSize)) + This operator changes all of the tt(Process) object's process +parameters. itb(Process &operator|(Process &lhs, Process &rhs)) - This operator implements em(piping): information sent to the tt(lhs)'s -standard output is passed on to the tt(rhs)'s standard input. The operator -returns tt(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 tt(lhs)'s child process is started, but the -tt(rhs)'s child process isn't. + This operator implements process em(piping): information sent b +tt(lhs) to its standard output becomes the tt(rhs)'s standard input. The +operator returns tt(rhs). + + This operator mimics the piping-operator supported by most command-shell +programs and should not be confused with the binary-or operator. The operator +starts the tt(lhs)'s child process, but the tt(rhs)'s child +process (and thus pipe processing) must explicitly be started. - Since the operator is left-associative and tt(rhs) is returned piping can + Since tt(operator|) is left-associative and tt(rhs) is returned piping can be em(chained), allowing constructions like tt(p1 | p2 | p3), where tt(p1, p2) and tt(p3) are tt(Process) objects. -The following idiom can be used to start the execution of the chain of +The following idiom can be used to start the execution of a chain of processes: tt((p1 | p2 | p3).start()). Alternatively, the following two-step procedure can be used: verb( @@ -321,16 +368,20 @@ If tt(p1) specifies tt(Process::CIN) then this tt(IOMode) is forwared to the final process of the chain of processes. It is not necessary to specify -tt(Process::CIN) for tt(p3). In fact, all tt(IOMode) flags of processes passed -to tt(operator|) are ignored and possibly modified em(except) for -tt(Process::IGNORE_CERR) and tt(Process::CERR) (for all processes), -tt(Process::CIN) (for the first process of the chain) and tt(Process::COUT) -(for the last process of the chain). +tt(Process::CIN) for tt(p3). In fact, most tt(IOMode) flags of processes +passed to tt(operator|) are ignored or modified. Acceptable tt(IOModes) are +tt(Process::IGNORE_CERR) and tt(Process::CERR) (accepted for all processes), +tt(Process::CIN) (accepted for the first process of the chain), and +tt(Process::COUT) (for the last process of the chain). After connecting a +series of processes using tt(operator|) all input and output (except for the +standard error streams) is handled through the last process: if +tt(Process::CIN) is specified for the first process then this mode is +transferred to the last process, so information inserted into the last process +enters the pipe through the first process's standard input. The next 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 tt(Process::CIN) -information must actually be inserted into the final process, tt(p3): +final process: verb( using namespace std; using namespace FBB; @@ -343,26 +394,22 @@ p3.start(); - string line; - while (getline(cin, line) && not line.empty()) - p3 << line << endl; - - p3.close(); - p3.waitForChild(); + p3 << cin.rdbuf() << eoi; ) + Note that when specifying multiple commands using the piping operator +(tt('|')), traditionally tt(USE_SHELL) had to be specified, as the traditional +piping operator is a shell-feature. tt(Process's operator|) handles I/O piping +itself, and thus avoids the additional shell process. ) - - The default overloaded assignment operator is not available. + The default overloaded copy and move assignment operators are not +available. manpagesection(MEMBERS) itemization( itb(bool active()) This member returns tt(true) if the child process is currently running -and tt(false) if not. It is automatically called from the insertion and -extraction operators and from the tt(cerr) member but is available as a public -member as well. It may terminate the child process if the child process has -timed out. +and tt(false) if not. itb(size_t available()) This member returns immediately. Its return value indicates whether @@ -372,96 +419,156 @@ process's standard output stream is available; tt(CHILD_CERR) is returned if information from the child process's standard error stream is available; tt(CHILD_COUT | CHILD_CERR) is returned if information from both the standard -output and standard error streams is available. +output and standard error streams is available. The tt(bit_and) operator, +returning a tt(bool) value, can be used to determine which stream has any +pending information. E.g., + verb( + if (process.available() & Process::CHILD_COUT) + cout << "Process has child standard output available"; + ) + + itb(size_t bufSize() const) + This member returns the default size of the stream buffers that are +used for communication with child processes. If called while a child process +is actually running, then the value returned by this member may differ from +the value that was actually used when starting the child process, as the +default value may be altered by a function call operator just before starting +the child process. itb(std::istream &cerr()) + This member should be avoided. Use tt(childErrStream) instead.nl() + + itb(std::istream &childErrStream()) + If tt(Process::CERR) was specified then this member interfaces +to the child's standard error stream. By extracting the information from +tt(childErrStream) the parent process retrieves the information sent by its +child process to its standard error stream. + + itb(std::istream &childOutStream()) + If tt(Process::COUT) or +tt(Process::MERGE_COUT_CERR) was specified then this member interfaces +to the child's standard output stream. By extracting the information from +tt(childOutStream) the parent process retrieves the information sent by its +child process to its standard output stream. Alternatively, this information +may directly be extracted from the tt(Process) object itself, but this member +does not require the use of a tt(static_cast) to disambiguate the intended +stream buffer in statements like + verb( + cout << process.childOutStream().rdbbuf() + ) + + itb(void close()) + This member closes the child's input stream. In situations where the +child continuously reads information from its standard input stream this +member can be used to inform the child process that input has terminated. This +member should only be used when tt(IOMode CIN) was specified for the currently +running child process; otherwise its behavior is undefined. Alternatively, the +tt(eoi) member or manipulator may be used. + + itb(void eoi()) + This member closes the child's input stream, and then calls +tt(waitForChild) to wait for the child process to end. In situations where the +child continuously reads information from its standard input stream this +member can be used to inform the child process that input has terminated. This +member should only be used when tt(IOMode CIN) was specified for the currently +running child process; otherwise its behavior is undefined. Alternatively, the +tt(close) member or tt(eoi) manipulator may be used. + + itb(std::istream &errStream()) 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 tt(IOMode CERR) was specified for the currently running child process; otherwise its behavior is undefined.nl() - itb(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 -tt(IOMode CIN) was specified for the currently running child process; -otherwise its behavior is undefined. - - itb(iomode ioMode() const) - This member returns the current default tt(IOMode). Note that the -tt(actual) tt(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 tt(operator()) above). + itb(IOMode ioMode() const) + This member returns the default tt(IOMode). If called while a child +process is actually running, then the value returned by this member may differ +from the value that was actually used when starting the child process, as the +default value may be altered by a function call operator just before starting +the child process. itb(ProcessType processType() const) - This member returns the current default tt(ProcessType). Note that the -tt(actual) tt(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 tt(operator()) above). + This member returns the default tt(ProcessType) of child proceses. If +called while a child process is actually running, then the value returned by +this member may differ from the value that was actually used when starting the +child process, as the default value may be altered by a function call operator +just before starting the child process. itb(size_t timeLimit() const) - This member returns the current time limit (in seconds) of child -processes. Note that the tt(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 tt(operator()) above). + This member returns the default time limit (in seconds) of child +processes. A return value of zero indicates that no time limit is enforced. If +called while a child process is actually running, then the value returned by +this member may differ from the value that was actually used when starting the +child process, as the default value may be altered by a function call operator +just before starting the child process. + + itb(void setBufSize(size_t bufSize)) + This member changes the default stream buffer size that is used for +communication with child processes. A zero byte buffer size is silently +changed into one. The new default value will be used when starting the next +child process. itb(void setCommand(std::string const &cmd)) - The tt(setCommand) member (re)defines the (initial part of a) command -specification currently stored in an tt(Process) object. When the program is -eventually started it may start and end with a em(back-tick) (tt(`)). The -back-ticks will be removed just before the specified program is executed.nl() - The tt(setCommand) member will em(not) start the specified command and -tt(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. + The tt(setCommand) member (re)defines the (initial part of a) child +process command specification. + + This member does not actually start the child process, and tt(operator+=) +may be used to append additional text to the command specification. Also, this +member may be used when a child process is currently active: its use does not +affect a currently running child process. itb(void setIOMode(iomode mode)) - This member will change the current default tt(IOMode) process -parameter of child processes. + This member changes the default tt(IOMode). The new default value will +be used when starting the next child process. itb(void setProcessType(ProcessType type)) - This member will change the current default tt(ProcessType) process -parameter of child processes. + This member changes the default tt(ProcessType). The new default value +will be used when starting the next child process. itb(void setTimeLimit(size_t timeLimit)) - This member sets the execution time limit (in seconds) of child -processes. No time limit will be imposed upon child processes if tt(timeLimit -0) is specified. + This member changes the default execution time limit (in seconds). No +time limit will be imposed upon child processes if tt(timeLimit 0) is +specified. The new default value will be used when starting the next child +process. itb(void 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 tt(start) members, -the tt(system) members, function call operator or various -tt(set-)members.nl() - Having specified a command to execute, the first white-space delimited + The currently specified command is started using the tt(Process) +object's process parameters. + + Having specified a command to start, 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 -bf(sh)(1), the tt(USE_SHELL ProcessType) or a tt(system) member -should be used.nl() - 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 tt(Process) object's tt(start) or tt(stop) members are called; when -the object's assignment operator is used; or when the object goes out of -scope. +start. If the program should be called through bf(sh)(1), the tt(USE_SHELL +ProcessType) or a tt(system) member should be used. + + If a child process does not terminate by itself, then it is terminated +when it has run for its alloted time; when the tt(Process) object's tt(start) +or tt(stop) members are called; when the object's assignment operator is used; +or when the object goes out of scope. itb(void start(IOMode mode)) - The currently specified command is executed using the specified -tt(IOMode) rather than the currently specified default but otherwise using the -currently specified default process parameters. The specified tt(IOMode) will -only be used for the process executed by this tt(start) member. - - itb(void start(IOMode mode, Program program)) - The currently specified command is executed using the specified -tt(IOMode) and tt(ProcessType) as well as the currently specified child -process time limit. The specified arguments will only be used for the process -executed by this tt(start) member. - - itb(void 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 tt(start) member. + The currently specified command is started using the specified +tt(IOMode), but otherwise using the currently configured tt(Process) object's +process parameters. The specified tt(IOMode) is only used for the child +process that is started by this member. + + itb(void start(IOMode mode, ProcessType type)) + The currently specified command is started using the specified +tt(IOMode) and tt(ProcessType), but otherwise using the currently configured +tt(Process) object's process parameters. The specified process parameter +values are only used for the child process that is started by this member. + + itb(void start(size_t mode, Program program, size_t timeLimit)) + The currently specified command is started using the specified +tt(IOMode), tt(ProcessType), and time limit (silently converting the tt(size_t +mode) to an tt(IOMode) value), and using the currently configured tt(Process) +object's stream buffer size parameter. The specified process parameter values +are only used for the child process that is started by this member. + + itb(void start(IOMode mode, Program program, size_t timeLimit, size_t + bufferSize)) + The currently specified command is started using the specified process +parameters. The specified parameter values are only used for the child process +that is started by this member. itb(void showMode(char const *lab) const) This member displays the label tt(lab), followed by the current @@ -469,81 +576,84 @@ representation of the currently active tt(IOMode). itb(std::string const &str() const) - This member returns the text of the command currently stored in the -tt(Process) object. It shows the command as it will be executed by -tt(start), tt(system) or the assignment operator. If the command's first -and last characters are back-ticks (tt(`)) then those back-ticks will be -removed when the command is actually executed. + This member returns the contents of the current child process command +specification. It shows the command as it will be (or has been) executed by +tt(start), tt(system) or the assignment operator. itb(void system()) This member executes the currently stored command as a command to -bf(sh)(1) (therefore executing the command as a shell command). When using -tt(system) redirections can be included in the command itself (although this -might render the redirected streams implied by the current bf(IOMode)) +bf(sh)(1). When using tt(system) redirections can be included in the command +itself (this renders the redirected streams implied by the current bf(IOMode)) useless. The currently set process parameters are used when bf(sh)(1) is -executed. Calling tt(system) implies calling tt(start). +executed. itb(void system(IOMode mode)) This member executes the currently stored command as a command to bf(sh)(1) (cf. tt(system) above) using the specified tt(IOMode) rather than -the current default tt(IOMode) setting. The currently specified default time -limit, however, will be used when executing the bf(sh)(1) process. +the current default tt(IOMode) setting. itb(void system(IOMode mode, size_t timeLimit)) This member executes the currently stored command as a command to bf(sh)(1) (cf. tt(system) above) using the specified tt(IOMode) and time -limit values rather than their current default settings. +limit. + + itb(void system(IOMode mode, size_t timeLimit, size_t bufSize)) + This member executes the currently stored command as a command to +bf(sh)(1) (cf. tt(system) above) using the specified tt(IOMode), time +limit, and stream buffer size values. itb(int stop()) This member terminates a currently active child process. The child process is twice sent a tt(SIG_TERM) signal, followed by a tt(SIG_KILL) -signal. This member returnss the exit-value of the child process that was +signal. This member returns the exit-value of the child process that was stopped. Its operation and return value are undefined if called without a -running child process. nl() +running child process. + Following tt(stop) a new command may be called using tt(start, system) or the assignment operator (see earlier). Those members first calls tt(stop). -When the intention is to start another child process, calling tt(stop) can be -skipped. Also, tt(stop) is called when the tt(Process) object goes out of -scope. +When the intention is to start another child process, then there's no need to +call tt(stop) explicitly. Also, tt(stop) is called when the tt(Process) object +goes out of scope. itb(int waitForChild()) This member is inherited from the class tt(FBB::Fork). It waits for a -child process to finish. It is called to prevent premature termination of a +child process to end. It is called to prevent premature termination of a child process before calling tt(stop). It is not always necessary to call tt(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 tt(waitForChild). - ) -manpagesection(USING PIPING IN COMMANDS) - -When specifying multiple commands using the piping operator (tt('|')) -tt(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 tt(Process)'s tt(operator|). - -manpagesection(EXAMPLE) - verbinclude(../../process/driver/driver.cc) - - The next example shows how a tt(Process's) input, output and standard -error streams can be handled. The following program reads from its standard -input and, depending on its command line argument, writes information to its -standard output stream, standard error stream, or both: - - verbinclude(../../process/driver/genall.cc) - -It could be called by the following program, using a tt(Process) object -calling tt(genall) as its child process: +manpagesection(MANIPULATOR) + itemization( + itb(FBB::eoi) + This manipulator may be inserted into a tt(Process) object for which +tt(IOMode CIN) was specified. It closes the child's input stream, and then +calls tt(waitForChild) to wait for the child process to end. In situations +where the child continuously reads information from its standard input stream +this member can be used to inform the child process that input has +terminated. Alternatively, tt(Process) object's tt(close) or tt(eoi) members +may be used. + ) - verbinclude(../../process/driver/callgenall.cc) +manpagesection(EXAMPLES) -The output generated by tt(genall) could also be processed by separate -threads. Here is a program using threads to process tt(genall)'s output: + The first example shows how a program only producing output can be +called. Its child process simply is tt(/bin/ls): + verbinsert(CODE)(../../process/driver/ls.cc) + + The next example shows how a child program can be given a limited amount +of execution time: lines entered at the keyboard are echoed to the standard +output stream for at most 5 seconds: + verbinsert(CODE)(../../process/driver/limit.cc) + + The final example shows how multi threading can be used to access the +child program's standard output and standard error streams through the +tt(Process) object: + verbinsert(CODE)(../../process/driver/all.cc) - verbinclude(../../process/driver/callgenallthreads.cc) + Additional examples are found in the distribution's +tt(bobcat/process/driver) directory. manpagefiles() em(bobcat/process) - defines the class interface diff -Nru bobcat-3.18.01/documentation/man/redirector.yo bobcat-3.19.01/documentation/man/redirector.yo --- bobcat-3.18.01/documentation/man/redirector.yo 2013-04-25 14:44:30.000000000 +0000 +++ bobcat-3.19.01/documentation/man/redirector.yo 2013-12-26 12:37:09.000000000 +0000 @@ -12,24 +12,53 @@ manpagedescription() Objects of the class bf(FBB::Redirector) set up a system level file -redirection, using file descriptors rather than streams. bf(FBB::Redirector) +redirection, using file descriptors rather than streams. tt(Redirector) objects are effectively em(wrappers) around the bf(dup2)(2) system call. System level redirection allows the programmer to send output to, e.g., the standard output stream, which actually appears at another stream (e.g., -the standard error). It is a stronger form of redirection than the standard -one offered by bf(C++), which uses tt(std::streambuf) redirection, and which -is, because of that, bound to the program's scope. System level redirection, -on the other hand, is applied at the system level, allowing the programmer to -redirect standard streams when starting a program. For example, the standard -error is commonly written to the standard output using an invocation like -tt(program 2>&1). - - When constructing bf(FBB::Redirector) objects a file descriptor is -required, and another file descriptor is required when defining the -redirection. Formally, file descriptors are not defined in bf(C++), but they -are available in many types of operating systems. In those systems each `file' -has an associated `file descriptor'. A file descriptor is an bf(int), which is -an index into the program's file allocation table, maintained by the +the standard error). + + + tt(Redirector) objects are used to redirect the output sent to a stream +having file descriptor tt(x) to another stream having file descriptor tt(y), +much like the shell's tt(>) operator redirects the standard output to some +file. + + tt(Redirector) objects can also be used to extract the information from a +stream having file descriptor tt(x) in fact from another stream having file +descriptor tt(y), much like the shell's tt(<) operator is used to read the +information in some file from the standard input. + +Redirection using tt(Redirector) objects represents a stronger form of +redirection than redirection offered by bf(C++) itself, which uses +tt(std::streambuf) redirection, and which is, because of that, bound to the +program's scope. System level redirection, on the other hand, is applied at +the system level, allowing the programmer to redirect standard streams when +starting a program. For example, the standard error is commonly written to the +standard output using an invocation like tt(program 2>&1). + + When constructing tt(Redirector) objects a file descriptor is +required. The file descriptor specified at the constructor is the file +descriptor that is used by the program to read information from or to write +information to. Another file descriptor is required to set up the +redirection: the file descriptor used here is the file descriptor of the +stream that actually holds the information which is extracted from the file +descriptor that was passed to the tt(Redirector)'s constructor; or it is the +file descriptor of the stream receiving the information which is written to +the stream having the file descriptor that was passed to the tt(Redirector)'s +constructor. + + When a tt(Redirector) object goes out of scope, its file descriptor are +left as-is. In particular, note that no bf(close)(2) operation is performed on +the tt(Redirector's) file descriptors. After setting up redirection using the +tt(Redirector's) member functions and passing the tt(Redirector's) file +descriptors to code that uses the tt(Redirector's) descriptors, the +tt(Redirector) object could in fact safely be destroyed. + + Formally, file descriptors are not defined in bf(C++), but they are +available in many types of operating systems. In those systems each `file' has +an associated `file descriptor'. A file descriptor is an bf(int), which is an +index into the program's file allocation table, maintained by the system. Another type of well-known entities which are file descriptors are em(sockets). @@ -45,9 +74,9 @@ ) Notes: itemization( - it() System-level redirection outlives system calls from the bf(execl)(3) -family. - it() Destroying a bf(FBB::Redirector) object does em(not) undo the + it() System-level redirections are kept during system calls of the +bf(exec)(3) family. + it() Destroying a tt(Redirector) object does em(not) undo the redirection set up by that object. ) @@ -70,26 +99,79 @@ itemization( itb(Redirector(int fd)) This constructor expects the file descriptor of the file that will be -used in the program to access (read, write) another file. +used by the program to access (read, write) another file. The file descriptor +that is passed to the constructor is used by the program, and will often be +tt(STDIN, STDOUT), or tt(STDERR), allowing the program to use tt(cin, cout), +or tt(cerr) to extract information from, or insert information into other +streams using its standard input and output streams. ) The copy constructor is available. manpagesection(MEMBER FUNCTIONS) itemization( itb(void swallow(int otherFd) const) - This member function expects the file descriptor of the file that will -be redirected. Redirection means that the descriptor provided to the -constructor will be used when referring to the file descriptor provided to the -bf(swallow()) member (see the example below). If the redirection fails an -bf(FBB::Exception) object is thrown, whose tt(which()) member shows the system's -tt(errno) value set by the failing bf(dup2)(2) function. + This member function expects a file descriptor which should become a +synonym of the constructor's file descriptor. The constructor's file +descriptor is redirected to tt(otherFd). + + After successfully calling tt(swallow) information written to +tt(otherFd) is in fact written to the constructor's file descriptor. E.g., if +the constructor's file descriptor represents a file on disk and tt(otherFd) is +tt(STDOUT_FILENO) then all information sent to the standard output stream is +actually sent to the file on disk: + verb( + information sent to otherFd -> is received at the constructor's Fd + (e.g., otherFd = STDOUT_FILENO) + ) + Conversely, if the constructor's file descriptor represents a file on +disk and tt(otherFd) is tt(STDIN_FILENO) then all information extracted from +the standard input stream is actually read from the file on disk. + verb( + information extracted from otherFd <- is read from the constructor's Fd + (e.g., otherFd = STDIN_FILENO) + ) + + Following tt(swallow) both file descriptors +are open, and refer to the constructor's file descriptor. + + Before setting up the redirection, the original tt(otherFd) is closed +by bf(close)(2). Following tt(swallow) both file descriptors can be used, and +refer to the constructor's file descriptor. If after calling tt(swallow) +bf(close)(2) is called for one of them, then the other one remains open. + + If redirection fails an bf(FBB::Exception) object is thrown, whose +tt(which()) member shows the system's tt(errno) value set by the failing +bf(dup2)(2) function. + itb(void through(int otherFd) const) - This member function also redirects tt(otherFd) to the file descriptor -provided to the constructor, but will also close the constructor's file -descriptor. After calling tt(through) the file referred to by the -constructor's file descriptor can only be accessed from tt(otherFd). The file -originally referred to by tt(otherFd) is not accessible anymore from the -current process. + This member function expects a file descriptor which should become a +synonym of the constructor's file descriptor. The constructor's file +descriptor is redirected to tt(otherFd). The constructor's file descriptor can +no longer be used, as it is closed by bf(close)(2). + + After successfully calling tt(through) information written to +tt(otherFd) is in fact written to the constructor's file descriptor. E.g., if +the constructor's file descriptor represents a file on disk and tt(otherFd) is +tt(STDOUT_FILENO) then all information sent to the standard output stream is +actually sent to the file on disk: + verb( + information sent to otherFd -> is received at the constructor's Fd + (e.g., otherFd = STDOUT_FILENO) + ) + Conversely, if the constructor's file descriptor represents a file on +disk and tt(otherFd) is tt(STDIN_FILENO) then all information extracted from +the standard input stream is actually read from the file on disk. + verb( + information extracted from otherFd <- is read from the constructor's Fd + (e.g., otherFd = STDIN_FILENO) + ) + Before setting up the redirection, the original tt(otherFd) is closed +by bf(close)(2). Following tt(through) only tt(otherFd) can be used, and +it refers to (i.e., reads or writes) the constructor's file descriptor. + + If redirection fails an bf(FBB::Exception) object is thrown, whose +tt(which()) member shows the system's tt(errno) value set by the failing +bf(dup2)(2) function. ) manpagesection(EXAMPLE) diff -Nru bobcat-3.18.01/documentation/man/signal.yo bobcat-3.19.01/documentation/man/signal.yo --- bobcat-3.18.01/documentation/man/signal.yo 2013-04-25 14:44:30.000000000 +0000 +++ bobcat-3.19.01/documentation/man/signal.yo 2013-12-28 10:19:31.000000000 +0000 @@ -57,7 +57,7 @@ The signal is now handled by an object, whose class must define a member verb( - virtual void signalHandler(size_t signum) override; + void signalHandler(size_t signum) override; ) and this function is responsible for handling the received signal. Since it is a member function it may affect its object's local variables and it may @@ -107,7 +107,16 @@ tt(SignalHandler::signalHandler) members are called in the same sequence as their respective tt(Signal::add) calls. If one of the earlier tt(signalHandler) members terminates the program then later - tt(signalHandler) members are not activated anymore. + tt(signalHandler) members are not activated anymore. If + tt(Signal::add) is called by, e.g., an object's constructor, then its + destructor should call tt(Signal::remove) to prevent the object's + signal handler from being called after its destruction. + itb(void remove(size_t signum, SignalHandler &object))nl() + tt(SignalHandler object) for signal tt(signum) is removed from the + tt(Signal) object. It is the responsibility of tt(object) to + deregister itself from tt(Signal) just before tt(object) goes out of + scope. Objects can only deregister themselves if they've previously + registered themselves using tt(add). itb(void ignore(size_t signum))nl() Any previously installed tt(SignalHandler) object is no longer activated on arrival of signal tt(signum). In addition, if possible, diff -Nru bobcat-3.18.01/icmake/clean bobcat-3.19.01/icmake/clean --- bobcat-3.18.01/icmake/clean 2013-11-13 10:44:52.000000000 +0000 +++ bobcat-3.19.01/icmake/clean 2013-12-28 10:19:31.000000000 +0000 @@ -9,7 +9,7 @@ "build-stamp configure-stamp debian/*substvars"; // unless `minimal': - remove2 = "tmp release.yo */oa */os */o"; + remove2 = "tmp release.yo */tmp */oa */os */o"; // in ./documentation: remove3 = "man/man-stamp"; diff -Nru bobcat-3.18.01/icmake/man bobcat-3.19.01/icmake/man --- bobcat-3.18.01/icmake/man 2013-11-13 10:44:52.000000000 +0000 +++ bobcat-3.19.01/icmake/man 2013-12-28 10:19:31.000000000 +0000 @@ -33,9 +33,9 @@ { base = get_base(yodl); - run("yodl2man --no-warnings -r 3 -o ../../tmp/man/man3/" + + run("yodl2man --no-warnings -r 3 -l 3 -o ../../tmp/man/man3/" + base + ".3" LIBRARY " " + yodl); - run("yodl2html --no-warnings -r 3 -o ../../tmp/manhtml/" + + run("yodl2html --no-warnings -r 3 -l 3 -o ../../tmp/manhtml/" + base + ".3.html " + yodl); } } diff -Nru bobcat-3.18.01/process/active.cc bobcat-3.19.01/process/active.cc --- bobcat-3.18.01/process/active.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/active.cc 2013-12-28 10:19:31.000000000 +0000 @@ -2,25 +2,12 @@ bool Process::active() { - if (d_monitor.pid != 0) - { - int retWaiter = waitpid(d_monitor.pid, &d_monitor.ret, WNOHANG); - - if (retWaiter == d_monitor.pid) - { - d_monitor.pid = 0; // process has ended - discontinue(d_child); - } - } - else if (d_child.pid != 0) + if (d_child.pid != 0) { int retChild = waitpid(d_child.pid, &d_child.ret, WNOHANG); if (retChild == d_child.pid) - { d_child.pid = 0; // process has ended - discontinue(d_monitor); - } } return d_child.pid; diff -Nru bobcat-3.18.01/process/bufsize.cc bobcat-3.19.01/process/bufsize.cc --- bobcat-3.18.01/process/bufsize.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/bufsize.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,6 @@ +#include "process.ih" + +size_t Process::bufSize() const +{ + return d_data->d_bufSize; +} diff -Nru bobcat-3.18.01/process/cerr.cc bobcat-3.19.01/process/cerr.cc --- bobcat-3.18.01/process/cerr.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/cerr.cc 2013-12-28 10:19:31.000000000 +0000 @@ -2,7 +2,15 @@ std::istream &Process::cerr() { - active(); - return d_iChildErr; + static bool called = false; + + if (not called) + { + called = true; + std::cerr << "WARN: replace Process::cerr() calls by " + "Process::childErrStream() calls\n"; + } + + return childErrStream(); } diff -Nru bobcat-3.18.01/process/childerrstream.cc bobcat-3.19.01/process/childerrstream.cc --- bobcat-3.18.01/process/childerrstream.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/childerrstream.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,8 @@ +#include "process.ih" + +std::istream &Process::childErrStream() +{ + active(); + return d_iChildErr; +} + diff -Nru bobcat-3.18.01/process/childoutstream.f bobcat-3.19.01/process/childoutstream.f --- bobcat-3.18.01/process/childoutstream.f 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/childoutstream.f 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,4 @@ +inline std::istream &Process::childOutStream() +{ + return static_cast(*this); +} diff -Nru bobcat-3.18.01/process/childprocess.cc bobcat-3.19.01/process/childprocess.cc --- bobcat-3.18.01/process/childprocess.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/childprocess.cc 2013-12-28 10:19:31.000000000 +0000 @@ -26,7 +26,7 @@ } -// std::cerr << "ChildProcess starts as:\n"; +// std::cerr << "ChildOutput starts as:\n"; // for (char const **cp = ec.argv; *cp; ++cp) // std::cerr << " " << *cp << endl; // std::cerr << "======================\n"; diff -Nru bobcat-3.18.01/process/destructor.cc bobcat-3.19.01/process/destructor.cc --- bobcat-3.18.01/process/destructor.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/destructor.cc 2013-12-28 10:19:31.000000000 +0000 @@ -3,5 +3,7 @@ Process::~Process() { stop(); + + delete d_data; // delete additional data } diff -Nru bobcat-3.18.01/process/driver/a.out.cc.SRC bobcat-3.19.01/process/driver/a.out.cc.SRC --- bobcat-3.18.01/process/driver/a.out.cc.SRC 2012-02-08 21:04:36.000000000 +0000 +++ bobcat-3.19.01/process/driver/a.out.cc.SRC 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -#include - -#include -using namespace std; - -int main() -{ - string line; - getline(cin, line); - return 0; -} \ No newline at end of file diff -Nru bobcat-3.18.01/process/driver/all.cc bobcat-3.19.01/process/driver/all.cc --- bobcat-3.18.01/process/driver/all.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/all.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,36 @@ +#include +#include + +#include + +#include "../../processenums/processenums" +#include "../../processdata/processdata.decl" +#include "../process" + +using namespace FBB; +using namespace std; + +//CODE +void collect(ostream *outStream, streambuf *rdbuf) +{ + *outStream << rdbuf << flush; +} + +int main() +{ + string cmd(getcwd(0, 0)); + cmd += "/cincoutcerr"; + + Process all(Process::ALL, cmd); + + all.start(); + + thread outThread(collect, &cout, all.childOutStream().rdbuf()); + thread errThread(collect, &cerr, all.childErrStream().rdbuf()); + + all << cin.rdbuf() << eoi; + + outThread.join(); + errThread.join(); +} +//= diff -Nru bobcat-3.18.01/process/driver/build bobcat-3.19.01/process/driver/build --- bobcat-3.18.01/process/driver/build 2012-02-08 21:04:36.000000000 +0000 +++ bobcat-3.19.01/process/driver/build 2013-12-28 10:19:31.000000000 +0000 @@ -1,23 +1,82 @@ -#!/bin/bash +#!/bin/sh -ln -sf ../process . -ln -sf ../process.ih . +precompile() +{ + cd .. + cd ../signal + icmbuild + + cd ../processdata + icmbuild + + cd ../process + icmbuild + + cd driver +} + +compile() +{ + precompile + + echo compiling $1.cc $2 + + g++ --std=c++11 -o $1 $2 $1.cc \ + -L../tmp -lprocess \ + -L../../processdata/tmp -lprocessdata \ + -L../../signal/tmp -lsignal \ + -lbobcat -s +} + case $1 in - (b) - rm process process.ih - g++ -DBOBCAT --std=c++0x -I../../tmp -o driver driver.cc \ - -lbobcat -L../../tmp/lib -s + (pipe|gpg|sha1sum|limit|ls) + compile $1 ;; - (o) - g++ --std=c++0x -o driver *.cc ../tmp/o/*.o -lbobcat -s + + (sort|thread) + compile $1 -pthread ;; - (c) - g++ --std=c++0x -o driver *.cc -lbobcat -s + + (all) + compile cincoutcerr + compile $1 -pthread + ;; + + (clean) + rm -f pipe gpg sort sha1sum thread limit ls all cincoutcerr + rm -rf ../tmp ../../*/tmp ;; + (*) - echo $0 b links to bobcat built by 'build libraries all' - echo $0 o links to the files in ../tmp/o - echo $0 c links to the files in the current dir only + echo " +Provide the name of the test as first argument. The executable receives the +name of the test. The test-name plus .cc extension is the name of the test +program source file. + +Available tests are: + all - stdin is split over stdout and stderr using multi-threading + gpg - stdin is a PGP encrypted file, stdout is the decrypted file, + stderr shows the result of the signature verification + limit - limits process time to 5 seconds, while copying stdin to stdout + using /bin/cat + ls - show directory contents: no input, only std output + pipe - stdin is passed through 3 /bin/cat programs, and is then + written to stdout + sha1sum - compute the input's sha1sum not using multi-threading + sort - multi threading is used when sorting stdin to stdout, where + sort's output is extracted from the Process object + thread - compute the input's sha1sum using multi-threading + + clean - not a test, but removes the test binaries +" ;; + esac + + + + + + + diff -Nru bobcat-3.18.01/process/driver/callgenall.cc bobcat-3.19.01/process/driver/callgenall.cc --- bobcat-3.18.01/process/driver/callgenall.cc 2013-09-13 13:26:53.000000000 +0000 +++ bobcat-3.19.01/process/driver/callgenall.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ -// Compile as, e.g., -// -// g++ --std=c++11 -o run callgenall.cc -lbobcat -// -// Run as, e.g., -// run './genall 3' < genall.cc - -#include -#include - -using namespace FBB; -using namespace std; - -int main(int argc, char **argv) -{ - if (argc == 1) - { - cout << "provide the path to the program to start as child process\n" - "provide input to that program on cin\n"; - - return 0; - } - - Process genall(argv[1]); - genall.start(); - - genall << cin.rdbuf(); - genall.close(); - - cout << "Standard output:\n" << - genall.rdbuf() << "\n" - "Standard error:\n" << - genall.cerr().rdbuf() << '\n'; - - genall.waitForChild(); -} diff -Nru bobcat-3.18.01/process/driver/callgenallthreads.cc bobcat-3.19.01/process/driver/callgenallthreads.cc --- bobcat-3.18.01/process/driver/callgenallthreads.cc 2013-09-13 14:06:40.000000000 +0000 +++ bobcat-3.19.01/process/driver/callgenallthreads.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -// Compile as, e.g., -// -// g++ --std=c++11 -pthread -o run callgenallthreads.cc -lbobcat -// -// Run as, e.g., -// run './genall 3' < genall.cc - -#include -#include - -#include - -using namespace FBB; -using namespace std; - -void collect(ostream *outStream, istream *inStream) -{ - *outStream << inStream->rdbuf(); -} - -int main(int argc, char **argv) -{ - if (argc == 1) - { - cout << "provide the path to the program to start as child process\n" - "provide input to that program on cin\n"; - - return 0; - } - - Process genall(argv[1]); - - genall.start(); - - thread outThread(collect, &cout, &genall); - thread errThread(collect, &cerr, &genall.cerr()); - - genall << cin.rdbuf(); - genall.close(); - - outThread.join(); - errThread.join(); - - genall.waitForChild(); - -} diff -Nru bobcat-3.18.01/process/driver/cincoutcerr.cc bobcat-3.19.01/process/driver/cincoutcerr.cc --- bobcat-3.18.01/process/driver/cincoutcerr.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/cincoutcerr.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,21 @@ +#include + +using namespace std; + +// Generates output to cout and cerr, and reads cin + +int main() +{ + string line; + + size_t count = 0; + + while (getline(cin, line)) + { + ++count; + if (count % 5 == 0) + cerr << "Cerr line " << count << ": " << line << endl; + else + cout << "Cout line " << count << ": " << line << endl; + } +} diff -Nru bobcat-3.18.01/process/driver/driver.cc bobcat-3.19.01/process/driver/driver.cc --- bobcat-3.18.01/process/driver/driver.cc 2012-02-08 21:04:36.000000000 +0000 +++ bobcat-3.19.01/process/driver/driver.cc 2013-12-28 10:19:31.000000000 +0000 @@ -1,8 +1,8 @@ -#ifdef BOBCAT +//#ifdef BOBCAT #include -#else - #include "process" -#endif +//#else +// #include "process" +//#endif #include #include @@ -41,82 +41,82 @@ 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 +// +// 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 << "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(); +// cout << "? "; +// getline(cin, line); +// process << line << endl; // to /bin/cat +// line.clear(); +// if (!getline(process, line)) // from /bin/cat +// break; +// cout << "Received: " << line << endl; // } - - 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; - } - +// 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) +catch (exception const &err) { - cerr << "EXCEPTION CAUGHT: " << err.why() << endl; + cerr << "CAUGHT EXCEPTION: " << err.what() << endl; return 1; } catch (bool) diff -Nru bobcat-3.18.01/process/driver/genall.cc bobcat-3.19.01/process/driver/genall.cc --- bobcat-3.18.01/process/driver/genall.cc 2013-09-12 11:07:24.000000000 +0000 +++ bobcat-3.19.01/process/driver/genall.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -#include - -using namespace std; - -// Generate output to cout and cerr, and read cin - -int main(int argc, char **argv) -{ - if (argc == 1) - { - cout << "Use argument 1 for only cout, 2 for only cerr, 3 for " - "cout+cerr\n"; - return 0; - } - - int mode = argv[1][0] - '0'; - - string line; - - size_t count = 0; - - while (getline(cin, line)) - { - if (mode & 1) - cout << "Got " << line << endl; - - if (mode & 2 && count++ % 2 == 0) - cerr << "Err line " << count << '\n'; - } -} diff -Nru bobcat-3.18.01/process/driver/gpg.cc bobcat-3.19.01/process/driver/gpg.cc --- bobcat-3.18.01/process/driver/gpg.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/gpg.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,26 @@ +#include "../../processenums/processenums" +#include "../../processdata/processdata.decl" +#include "../process" + +#include + +using namespace std; +using namespace FBB; + +int main() +try +{ + Process gpg(Process::CIN, "/usr/bin/gpg --quiet --batch --decrypt"); + + gpg.start(); + gpg << cin.rdbuf() << eoi; +} +catch (exception const &err) +{ + cerr << err.what() << endl; + return 0; +} +catch (int x) +{ + return 0; +} diff -Nru bobcat-3.18.01/process/driver/limit.cc bobcat-3.19.01/process/driver/limit.cc --- bobcat-3.18.01/process/driver/limit.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/limit.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,42 @@ +#include + +#include "../../processenums/processenums" +#include "../../processdata/processdata.decl" +#include "../process" + +using namespace std; +using namespace FBB; + +//CODE +int main() +{ + Process process(Process::CIN | Process::COUT, "/bin/cat"); + process.setTimeLimit(5); + + process.start(); + + while (true) + { + cout << "? "; + string line; + if (not getline(cin, line)) + return 0; + + process << line << endl; // to /bin/cat + line.clear(); + + if (not getline(process, line)) // from /bin/cat + break; + + cout << "Received: " << line << endl; + } + + cout << "/bin/cat time limit of 5 seconds reached: child process ended\n"; +} +//= + + + + + + diff -Nru bobcat-3.18.01/process/driver/ls.cc bobcat-3.19.01/process/driver/ls.cc --- bobcat-3.18.01/process/driver/ls.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/ls.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,19 @@ +#include + +#include "../../processenums/processenums" +#include "../../processdata/processdata.decl" +#include "../process" + +using namespace std; +using namespace FBB; + +//CODE +int main() +{ + Process process(Process::COUT, "/bin/ls -Fla"); + + process.start(); + cout << process.childOutStream().rdbuf(); +} +//= + diff -Nru bobcat-3.18.01/process/driver/pipe.cc bobcat-3.19.01/process/driver/pipe.cc --- bobcat-3.18.01/process/driver/pipe.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/pipe.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,27 @@ +#include + +#include "../../processenums/processenums" +#include "../../processdata/processdata.decl" +#include "../process" + +using namespace std; +using namespace FBB; + +int main() +{ + // Nota bene: by default IOMode equals Process::ALL + + Process p1(Process::CIN, "/bin/cat"); + Process p2(Process::STD, "/bin/cat"); + Process p3(Process::STD, "/bin/cat"); + + (p1 | p2 | p3).start(); + + p3 << cin.rdbuf() << eoi; +} + + + + + + diff -Nru bobcat-3.18.01/process/driver/sha1sum.cc bobcat-3.19.01/process/driver/sha1sum.cc --- bobcat-3.18.01/process/driver/sha1sum.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/sha1sum.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,32 @@ +#include +#include + +#include "../../processenums/processenums" +#include "../../processdata/processdata.decl" +#include "../process" + +using namespace std; +using namespace FBB; + +int main() +try +{ + Process sha1sum(Process::CIN | Process::COUT, "/usr/bin/sha1sum"); + + sha1sum.start(); + + sha1sum << cin.rdbuf() << eoi; + + string line; + while (getline(sha1sum, line)) + cout << line << '\n'; +} +catch (exception const &err) +{ + cerr << err.what() << endl; + return 0; +} +catch (int x) +{ + return 0; +} diff -Nru bobcat-3.18.01/process/driver/sort.cc bobcat-3.19.01/process/driver/sort.cc --- bobcat-3.18.01/process/driver/sort.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/sort.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,37 @@ +#include +#include + +#include "../../processenums/processenums" +#include "../../processdata/processdata.decl" +#include "../process" + +using namespace std; +using namespace FBB; + +void collect(streambuf *buf) +{ + cout << buf; +} + +int main() +try +{ + Process sort(Process::CIN | Process::COUT, "/usr/bin/sort"); + + sort.start(); + + thread out(collect, sort.childOutStream().rdbuf()); + + sort << cin.rdbuf() << eoi; + + out.join(); +} +catch (exception const &err) +{ + cerr << err.what() << endl; + return 0; +} +catch (int x) +{ + return 0; +} diff -Nru bobcat-3.18.01/process/driver/spawn/childprocess.cc bobcat-3.19.01/process/driver/spawn/childprocess.cc --- bobcat-3.18.01/process/driver/spawn/childprocess.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/spawn/childprocess.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,14 @@ +#include "spawn.ih" + +void Spawn::childProcess() +{ + + vector cmd(String::split(static_cast(0), + d_command)); + + char const **args = String::argv(cmd); + + execv(args[0], const_cast(args)); + + throw 0; // this should not be reached, but if so main properly ends. +} diff -Nru bobcat-3.18.01/process/driver/spawn/childredirections.cc bobcat-3.19.01/process/driver/spawn/childredirections.cc --- bobcat-3.18.01/process/driver/spawn/childredirections.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/spawn/childredirections.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,9 @@ +#include "spawn.ih" + +void Spawn::childRedirections() +{ + d_insertPipe.readFrom(STDIN_FILENO); +// d_extractPipe.writtenBy(STDOUT_FILENO); +// d_errPipe.writtenBy(STDERR_FILENO); +} + diff -Nru bobcat-3.18.01/process/driver/spawn/end.cc bobcat-3.19.01/process/driver/spawn/end.cc --- bobcat-3.18.01/process/driver/spawn/end.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/spawn/end.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,10 @@ +#include "spawn.ih" + +void Spawn::end() +{ + flush(); + + ::close(d_insertPipe.writeFd()); + + waitForChild(); +} diff -Nru bobcat-3.18.01/process/driver/spawn/main.cc bobcat-3.19.01/process/driver/spawn/main.cc --- bobcat-3.18.01/process/driver/spawn/main.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/spawn/main.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,22 @@ +#include "spawn.h" + +using namespace std; + +int main(int argc, char **argv) +try +{ + Spawn spawn(argv[1]); + + ifstream in(argv[2]); + + spawn.fork(); + + spawn << in.rdbuf(); + + spawn.end(); + +} +catch (int x) +{ + return 0; +} diff -Nru bobcat-3.18.01/process/driver/spawn/parentprocess.cc bobcat-3.19.01/process/driver/spawn/parentprocess.cc --- bobcat-3.18.01/process/driver/spawn/parentprocess.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/spawn/parentprocess.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,8 @@ +#include "spawn.ih" + +void Spawn::parentProcess() +{ + d_insertPipe.writeOnly(); + + +} diff -Nru bobcat-3.18.01/process/driver/spawn/spawn.h bobcat-3.19.01/process/driver/spawn/spawn.h --- bobcat-3.18.01/process/driver/spawn/spawn.h 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/spawn/spawn.h 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,44 @@ +#ifndef INCLUDED_SPAWN_ +#define INCLUDED_SPAWN_ + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +class Spawn: public FBB::Fork, public std::ostream// , public std::istream +{ + FBB::Pipe d_insertPipe; +// FBB::Pipe d_extractPipe; +// FBB::Pipe d_errPipe; + + FBB::OFdStreambuf d_insertBuffer; +// FBB::IFdStreambuf d_extractBuffer; +// FBB::IFdStream d_errStream; + + std::string d_command; + + public: + Spawn(std::string const &command); + + void end(); + + private: + void childProcess() override; + void parentProcess() override; + void childRedirections() override; +}; + +#endif + + + + + diff -Nru bobcat-3.18.01/process/driver/spawn/spawn.ih bobcat-3.19.01/process/driver/spawn/spawn.ih --- bobcat-3.18.01/process/driver/spawn/spawn.ih 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/spawn/spawn.ih 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,14 @@ +#include "spawn.h" + +#include + +#include +#include +#include +#include + +#include + +using namespace std; +using namespace FBB; + diff -Nru bobcat-3.18.01/process/driver/spawn/spawn1.cc bobcat-3.19.01/process/driver/spawn/spawn1.cc --- bobcat-3.18.01/process/driver/spawn/spawn1.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/spawn/spawn1.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,20 @@ +#include "spawn.ih" + +// 1: program[0] +// 2: command +// 3: cin-name +// 4: cout-name +// 5: cerr-name + +Spawn::Spawn(std::string const &command) +: + d_command(command), + d_insertBuffer(d_insertPipe.writeFd(), 10000) + +// d_extractBuffer(d_extractPipe.readOnly()), +// d_errStream(d_errPipe.readOnly()) +{ + rdbuf(&d_insertBuffer); +// rdbuf(&d_extractBuffer); +} + diff -Nru bobcat-3.18.01/process/driver/thread.cc bobcat-3.19.01/process/driver/thread.cc --- bobcat-3.18.01/process/driver/thread.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/driver/thread.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,36 @@ +//#include +#include "../process" + +#include +#include + +using namespace std; +using namespace FBB; + +void collect(streambuf *buf) +{ + cout << buf; +} + +int main() +try +{ + Process sha1sum(Process::CIN | Process::COUT, "/usr/bin/sha1sum"); + + sha1sum.start(); + + thread out(collect, sha1sum.childOutStream().rdbuf()); + + sha1sum << cin.rdbuf() << eoi; + + out.join(); +} +catch (exception const &err) +{ + cerr << err.what() << endl; + return 0; +} +catch (int x) +{ + return 0; +} diff -Nru bobcat-3.18.01/process/eoi.f bobcat-3.19.01/process/eoi.f --- bobcat-3.18.01/process/eoi.f 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/eoi.f 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,6 @@ + +inline std::ostream &eoi(std::ostream &str) +{ + return str; +} + diff -Nru bobcat-3.18.01/process/eoi2.f bobcat-3.19.01/process/eoi2.f --- bobcat-3.18.01/process/eoi2.f 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/eoi2.f 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,6 @@ + +inline void Process::eoi() +{ + *this << FBB::eoi; +} + diff -Nru bobcat-3.18.01/process/forking.cc bobcat-3.19.01/process/forking.cc --- bobcat-3.18.01/process/forking.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/forking.cc 2013-12-28 10:19:31.000000000 +0000 @@ -1,42 +1,11 @@ #include "process.ih" -#include - void Process::forking() { + newPipes(); + if (d_mode == IOMode::DIRECT) childProcess(); fork(); - - // this is the parent, following parentRedirections() - - d_child.pid = pid(); - - if (d_timeLimit == 0) // no wait, set monitor.pid to 0: no - { // time monitoring - d_monitor.pid = 0; - return; - } - - d_monitor.pid = ::fork(); - - if (d_monitor.pid < 0) // monitor process fails - { - d_monitor.pid = 0; - stop(); - throw Exception() << "Process " << d_command << - ": can't start the timeout monitor"; - } - else if (d_monitor.pid == 0) // actual monitoring process - { - // close open pipes inherited from the - // parent process - closeWriteFd(d_oChildInPipe); - closeReadFd(d_iChildOutPipe); - closeReadFd(d_iChildErrPipe); - - sleep(d_timeLimit); // end the child after 'timeLimit' - exit(0); - } } diff -Nru bobcat-3.18.01/process/initialize.cc bobcat-3.19.01/process/initialize.cc --- bobcat-3.18.01/process/initialize.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/initialize.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -#include "process.ih" - -void Process::initialize(size_t timeLimit, iomode mode, - ProcessType processType) -{ - -#ifdef BOBCAT_DIY_CLOEXEC_ - d_closedByChild = 0; -#endif - - d_active = false; - - d_setTimeLimit = d_timeLimit = timeLimit; - d_setProcessType = d_processType = processType; - d_setMode = sanitizeIOMode(mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC)); - - open(d_iChildOut, d_oChildIn); -} diff -Nru bobcat-3.18.01/process/iomode.f bobcat-3.19.01/process/iomode.f --- bobcat-3.18.01/process/iomode.f 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/iomode.f 2013-12-28 10:19:31.000000000 +0000 @@ -1,4 +1,4 @@ -inline Process::iomode Process::ioMode() const +inline Process::IOMode Process::ioMode() const { return d_mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC); } diff -Nru bobcat-3.18.01/process/limiter.cc bobcat-3.19.01/process/limiter.cc --- bobcat-3.18.01/process/limiter.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/limiter.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,33 @@ +#include "process.ih" + +void Process::limiter(Process *process) +{ + size_t &timeLimit = process->d_timeLimit; + + if (timeLimit == 0) // no timelimit: thread immediately + return; // ends + + unique_lock lock(process->d_data->d_mutex); // get the lock + + volatile ChildAction &action = process->d_data->d_action; + + action = TIME_LIMIT; + + // when the child process ends, signalHandler is called, which + // sets d_action to CHILD_ENDED, and notifies this function: + // the loop ends with CHILD_ENDED. Otherwise, the time limit is + // reached and the wait_for ends with d_action == TIME_LIMIT + while (action != CHILD_ENDED) + { + // When the time limit is reached + // the loop breaks, and d_action is + // TIME_LIMIT. + if (process->d_data->d_condition.wait_for( + lock, chrono::seconds(timeLimit)) == cv_status::timeout) + break; + } + + if (action == TIME_LIMIT) + process->discontinue(process->d_child); +} + diff -Nru bobcat-3.18.01/process/operatorassign.cc bobcat-3.19.01/process/operatorassign.cc --- bobcat-3.18.01/process/operatorassign.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/operatorassign.cc 2013-12-28 10:19:31.000000000 +0000 @@ -6,6 +6,6 @@ setCommand(command); - start(d_mode, d_processType, d_timeLimit); + start(d_mode, d_processType, d_timeLimit, bufSize()); return ret; } diff -Nru bobcat-3.18.01/process/operatorfun.cc bobcat-3.19.01/process/operatorfun.cc --- bobcat-3.18.01/process/operatorfun.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/operatorfun.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,10 +0,0 @@ -#include "process.ih" - -Process &Process::operator()(iomode mode, ProcessType type, size_t timeLimit) -{ - d_timeLimit = timeLimit; - d_processType = type; - sanitizeIOMode(mode); - - return *this; -} diff -Nru bobcat-3.18.01/process/operatorfun1.cc bobcat-3.19.01/process/operatorfun1.cc --- bobcat-3.18.01/process/operatorfun1.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/operatorfun1.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,6 @@ +#include "process.ih" + +Process &Process::operator()(size_t mode, ProcessType type, size_t timeLimit) +{ + return operator()(iomode(mode), type, timeLimit, bufSize()); +} diff -Nru bobcat-3.18.01/process/operatorfun2.cc bobcat-3.19.01/process/operatorfun2.cc --- bobcat-3.18.01/process/operatorfun2.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/operatorfun2.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,12 @@ +#include "process.ih" + +Process &Process::operator()(IOMode mode, ProcessType type, size_t timeLimit, + size_t bufSize) +{ + d_data->d_bufSize = bufSize; + d_timeLimit = timeLimit; + d_processType = type; + sanitizeIOMode(mode); + + return *this; +} diff -Nru bobcat-3.18.01/process/operatorinsert.cc bobcat-3.19.01/process/operatorinsert.cc --- bobcat-3.18.01/process/operatorinsert.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/operatorinsert.cc 2013-12-28 10:19:31.000000000 +0000 @@ -3,7 +3,17 @@ Process &Process::operator<<(std::ostream &(*pf)(std::ostream &)) { if (active()) - dynamic_cast(*this) << pf; + { + + if (pf != FBB::eoi) + static_cast(*this) << pf; + else + { + close(); + waitForChild(); + } + } + return *this; } diff -Nru bobcat-3.18.01/process/operatorpipe.cc bobcat-3.19.01/process/operatorpipe.cc --- bobcat-3.18.01/process/operatorpipe.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/operatorpipe.cc 2013-12-28 10:19:31.000000000 +0000 @@ -24,7 +24,9 @@ ) lhs.d_setMode |= Process::CLOSE_ON_EXEC; - lhs.d_setMode |= Process::OUT_PIPE; // This is the output end of the pipe + // This is the output end of the pipe + lhs.d_setMode |= Process::PIPES_OK | Process::OUT_PIPE; + rhs.d_setMode |= Process::PIPES_OK; lhs.start(); // forking() does the real work @@ -49,7 +51,7 @@ } // this is the input end of the pipe - rhs.d_setMode |= Process::IN_PIPE | Process::CIN; + rhs.d_setMode |= Process::CIN | Process::IN_PIPE; rhs.d_mode |= Process::CIN; return rhs; // to start do, e.g., (p1|p2).start() diff -Nru bobcat-3.18.01/process/opfun1.f bobcat-3.19.01/process/opfun1.f --- bobcat-3.18.01/process/opfun1.f 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/opfun1.f 2013-12-28 10:19:31.000000000 +0000 @@ -1,5 +1,4 @@ -inline Process &Process::operator()(iomode mode) +inline Process &Process::operator()(IOMode mode) { - return operator()(mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC), - d_setProcessType, d_setTimeLimit); + return operator()(mode, d_setProcessType, d_setTimeLimit); } diff -Nru bobcat-3.18.01/process/opfun2.f bobcat-3.19.01/process/opfun2.f --- bobcat-3.18.01/process/opfun2.f 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/opfun2.f 2013-12-28 10:19:31.000000000 +0000 @@ -1,4 +1,4 @@ -inline Process &Process::operator()(iomode mode, ProcessType type) +inline Process &Process::operator()(IOMode mode, ProcessType type) { return operator()(mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC), type, d_setTimeLimit); diff -Nru bobcat-3.18.01/process/parentprocess.cc bobcat-3.19.01/process/parentprocess.cc --- bobcat-3.18.01/process/parentprocess.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/parentprocess.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,7 @@ +#include "process.ih" + +void Process::parentProcess() // overrides +{ + d_child.pid = pid(); +} + diff -Nru bobcat-3.18.01/process/parentprocess.f bobcat-3.19.01/process/parentprocess.f --- bobcat-3.18.01/process/parentprocess.f 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/parentprocess.f 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -inline void Process::parentProcess() -{} diff -Nru bobcat-3.18.01/process/process bobcat-3.19.01/process/process --- bobcat-3.18.01/process/process 2013-11-13 10:45:02.000000000 +0000 +++ bobcat-3.19.01/process/process 2013-12-30 10:13:10.000000000 +0000 @@ -12,6 +12,7 @@ #include #include #include +#include #if defined(__FreeBSD_kernel__) || defined(__FreeBSD__) #ifndef BOBCAT_DIY_CLOEXEC_ @@ -22,7 +23,9 @@ namespace FBB { -struct Process: private Fork, public IOStream +struct ProcessData; + +struct Process: private Fork, public IOStream, public ProcessEnums { friend Process &operator|(Process &lhs, Process &rhs); @@ -35,11 +38,11 @@ private: bool d_active; - size_t d_mode; + IOMode d_mode; size_t d_timeLimit; // seconds allowed to child-process ProcessType d_processType; - size_t d_setMode; // these values are set by the + IOMode d_setMode; // these values are set by the size_t d_setTimeLimit; // set members and used as ProcessType d_setProcessType; // defaults unless overridden by // actual values @@ -65,64 +68,43 @@ { int ret; pid_t pid; - + RetPid(); // 1.f }; RetPid d_child; - RetPid d_monitor; + + ProcessData *d_data; + char d_notUsed[sizeof(RetPid) - sizeof(ProcessData *)]; #ifdef BOBCAT_DIY_CLOEXEC_ - int d_closedByChild; // DIY CLOSE_ON_EXEC + int d_closedByChild = 0; // DIY CLOSE_ON_EXEC #endif public: - enum IOMode - { - STD = 0, - - CIN = 1 << 0, - COUT = 1 << 1, - CERR = 1 << 2, - - IGNORE_COUT = 1 << 3, - IGNORE_CERR = 1 << 4, - - MERGE_COUT_CERR = 1 << 5, - - DIRECT = 1 << 8, - - // flags below are Internal Use Only and cannot be set by - // users - - IN_PIPE = 1 << 10, - OUT_PIPE = 1 << 11, - - CLOSE_ON_EXEC = 1 << 12, - }; - typedef size_t iomode; - - enum ChildOutput - { - NOTHING_AVAILABLE = 0, - CHILD_COUT = 1 << 0, - CHILD_CERR = 1 << 1, - }; - explicit Process(std::string const &command = ""); // 1 - explicit Process(iomode mode, std::string const &command = ""); // 2 - Process(iomode mode, ProcessType type, // 3 + + explicit Process(size_t iomode, std::string const &command = ""); // 2 + Process(size_t mode, ProcessType type, // 3 std::string const &command = ""); - Process(iomode mode, ProcessType type, size_t timeLimit, // 4 + Process(size_t mode, ProcessType type, size_t timeLimit, // 4 std::string const &command = ""); + Process(IOMode mode, ProcessType type, size_t timeLimit, // 5 + size_t bufSize, std::string const &command = ""); + + Process(Process const &other) = delete; - virtual ~Process(); // stop()s any ongoing process + ~Process() override; // stop()s any ongoing process - iomode ioMode() const; // returns default IOMode .f + Process &operator=(Process const &other) = delete; + + size_t bufSize() const; // returns current buffer size + IOMode ioMode() const; // returns default IOMode .f ProcessType processType() const; // returns default ProcessType .f size_t timeLimit() const; // returns default time limit .f - void setIOMode(iomode mode); // change IOMode .f + void setBufSize(size_t bufSize); + void setIOMode(IOMode mode); // change IOMode .f void setProcessType(ProcessType type); // .f @@ -131,30 +113,31 @@ // 0 means: no time monitor void setCommand(std::string const &command); // sets cmd, .f - // eats backticks Process &operator+=(std::string const &text); // opaddis.f // adds to the command void start(); // 1.f - void start(iomode mode); // 2.f - void start(iomode mode, ProcessType type); // 3.f + void start(IOMode mode); // 2.f + void start(IOMode mode, ProcessType type); // 3.f + + void start(size_t mode, ProcessType type, size_t timeLimit); // 1 + void start(IOMode mode, ProcessType type, // 2 + size_t timeLimit, size_t bufSize); - void start(iomode mode, ProcessType type, size_t timeLimit); void system(); // calls /bin/sh -c cmd; 1.f // shell redirs OK - void system(iomode mode); // 2.f - void system(iomode mode, size_t timeLimit); // 3.1 - + void system(IOMode mode); // 2.f + void system(IOMode mode, size_t timeLimit); // 3.f + void system(IOMode mode, size_t timeLimit, size_t bufSize); // 4.f + int operator=(std::string const &cmd); // sets and starts a command std::string const &str() const; // current command .f - int stop(); // terminate a running childprocess - template Process &operator<<(Type const &value); // opinsert.f @@ -163,43 +146,55 @@ template Process &operator>>(Type &value); // opextract.f - bool active(); - - Process &operator()(iomode mode); // opfun1.f - Process &operator()(iomode mode, ProcessType type); // opfun2.f - Process &operator()(iomode mode, ProcessType type, size_t timeLimit); + int stop(); // terminate a running childprocess void close(); // closes input to the child + void eoi(); // closes input and waits for + // the child to end + using Fork::waitForChild; + + bool active(); - std::istream &cerr(); // READ cerr from the child + Process &operator()(IOMode mode); // opfun1.f + Process &operator()(IOMode mode, ProcessType type); // opfun2.f + + // operatorfun1.cc + Process &operator()(size_t mode, ProcessType type, size_t timeLimit); + + Process &operator()(IOMode mode, ProcessType type, // operatorfun2.cc + size_t timeLimit, size_t bufSize); + + std::istream &childErrStream(); // READ cerr from the child + std::istream &cerr(); // same, but deprecated + + std::istream &childOutStream(); // .f + // READ cout from the child + // (also: direct through + // extraction) size_t available(); // returns ChildOutput bit_or // (cf. manpage) void showMode(char const *lab) const; - using Fork::waitForChild; - private: - Process(Process const &other) = delete; - Process &operator=(Process const &other) = delete; - virtual void childProcess(); - virtual void childRedirections(); - virtual void parentProcess(); // .f - virtual void parentRedirections(); + void childProcess() override; + void childRedirections() override; + void parentProcess() override; + void parentRedirections() override; void newPipe(Pipe &pipe); pid_t discontinue(RetPid &proc); - size_t whichStream(); + ChildOutput whichStream(); void close(int fd); void closeWriteFd(Pipe &pipe); void closeReadFd(Pipe &pipe); + void rmBackticks(); void forking(); - void initialize(size_t timeLimit, iomode mode, - ProcessType processType); - iomode sanitizeIOMode(iomode mode); + + IOMode sanitizeIOMode(IOMode mode); void newPipes(); void closeChildInputOnExec(); @@ -207,8 +202,13 @@ typedef std::string::const_iterator ConstIter; struct ExecContext; ExecContext analyzeCommand(); + + static void limiter(Process *process); }; +#include "childoutstream.f" +#include "eoi.f" +#include "eoi2.f" #include "iomode.f" #include "opaddis.f" #include "opextract.f" @@ -227,6 +227,7 @@ #include "system1.f" #include "system2.f" #include "system3.f" +#include "system4.f" #include "timelimit.f" diff -Nru bobcat-3.18.01/process/process.ih bobcat-3.19.01/process/process.ih --- bobcat-3.18.01/process/process.ih 2013-11-13 10:45:02.000000000 +0000 +++ bobcat-3.19.01/process/process.ih 2013-12-28 10:19:31.000000000 +0000 @@ -14,16 +14,28 @@ #include #include +#include "../processdata/processdata.decl" + using namespace std; using namespace FBB; - struct Process::ExecContext { size_t argc; // must eventually be at least 1 char const **argv; // 0-terminated array of pointers to the // arguments }; - + #include "retpid1.f" -#include "parentprocess.f" + + + + + + + + + + + + diff -Nru bobcat-3.18.01/process/process1.cc bobcat-3.19.01/process/process1.cc --- bobcat-3.18.01/process/process1.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/process1.cc 2013-12-28 10:19:31.000000000 +0000 @@ -2,11 +2,5 @@ Process::Process(std::string const &command) : - d_command(command), - - d_oChildIn(0), - d_iChildOut(0), - d_iChildErr(0) -{ - initialize(0, CIN | COUT | CERR, NO_PATH); -} + Process(ALL, NO_PATH, 0, 200, command) +{} diff -Nru bobcat-3.18.01/process/process2.cc bobcat-3.19.01/process/process2.cc --- bobcat-3.18.01/process/process2.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/process2.cc 2013-12-28 10:19:31.000000000 +0000 @@ -1,12 +1,6 @@ #include "process.ih" -Process::Process(iomode mode, std::string const &command) +Process::Process(size_t mode, std::string const &command) : - d_command(command), - - d_oChildIn(0), - d_iChildOut(0), - d_iChildErr(0) -{ - initialize(0, mode, NO_PATH); -} + Process(iomode(mode), NO_PATH, 0, 200, command) +{} diff -Nru bobcat-3.18.01/process/process3.cc bobcat-3.19.01/process/process3.cc --- bobcat-3.18.01/process/process3.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/process3.cc 2013-12-28 10:19:31.000000000 +0000 @@ -1,12 +1,6 @@ #include "process.ih" -Process::Process(iomode mode, ProcessType type, std::string const &command) +Process::Process(size_t mode, ProcessType type, std::string const &command) : - d_command(command), - - d_oChildIn(0), - d_iChildOut(0), - d_iChildErr(0) -{ - initialize(0, mode, type); -} + Process(iomode(mode), type, 0, 200, command) +{} diff -Nru bobcat-3.18.01/process/process4.cc bobcat-3.19.01/process/process4.cc --- bobcat-3.18.01/process/process4.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/process4.cc 2013-12-28 10:19:31.000000000 +0000 @@ -1,13 +1,7 @@ #include "process.ih" -Process::Process(iomode mode, ProcessType processType, size_t timeLimit, +Process::Process(size_t mode, ProcessType processType, size_t timeLimit, string const &command) : - d_command(command), - - d_oChildIn(0), - d_iChildOut(0), - d_iChildErr(0) -{ - initialize(timeLimit, mode, processType); -} + Process(iomode(mode), processType, timeLimit, 200, command) +{} diff -Nru bobcat-3.18.01/process/process5.cc bobcat-3.19.01/process/process5.cc --- bobcat-3.18.01/process/process5.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/process5.cc 2013-12-30 10:10:46.000000000 +0000 @@ -0,0 +1,27 @@ +#include "process.ih" + +Process::Process(IOMode mode, ProcessType processType, + size_t timeLimit, size_t bufSize, string const &command) +: + d_active(false), + d_timeLimit(timeLimit), + d_processType(processType), + + d_setTimeLimit(timeLimit), + d_setProcessType(processType), + + d_command(command), + + d_oChildIn(0), // initialize the streams with 0-buffers + d_iChildOut(0), + d_iChildErr(0), + + d_data(new ProcessData(bufSize)) +{ + d_setMode = sanitizeIOMode(mode); + + // connect the input and output streams to Process + open(d_iChildOut, d_oChildIn); +} + + diff -Nru bobcat-3.18.01/process/rmbackticks.cc bobcat-3.19.01/process/rmbackticks.cc --- bobcat-3.18.01/process/rmbackticks.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/rmbackticks.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,11 @@ +#include "process.ih" + +void Process::rmBackticks() +{ + if (d_command.front() == '`' && d_command.back() == '`') // rm backticks + { + d_command.resize(d_command.length() - 1); // rm last backtick + d_command.erase(0, 1); // rm front backtick + } + +} diff -Nru bobcat-3.18.01/process/sanitizeiomode.cc bobcat-3.19.01/process/sanitizeiomode.cc --- bobcat-3.18.01/process/sanitizeiomode.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/sanitizeiomode.cc 2013-12-28 10:19:31.000000000 +0000 @@ -1,21 +1,31 @@ #include "process.ih" -Process::iomode Process::sanitizeIOMode(iomode mode) +Process::IOMode Process::sanitizeIOMode(IOMode mode) { + if ( + not (mode & PIPES_OK) + && + (mode & (IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC)) + ) + throw invalid_argument("IOModes IN_PIPE, OUT_PIPE and CLOSE_ON_EXIT " + "may not be specified"); + if ((mode & DIRECT) && (mode & ~DIRECT)) throw invalid_argument("IOModes cannot be combined with DIRECT"); - d_mode = mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC); - - if (d_mode & COUT) // overrules IGNORE_COUT - d_mode &= ~(IGNORE_COUT); - - if (d_mode & CERR) // overrules IGNORE_CERR - d_mode &= ~IGNORE_CERR; + if ((mode & IGNORE_CERR) && (mode & (CERR | MERGE_COUT_CERR))) + throw invalid_argument( + "IOMode IGNORE_CERR cannot be used with modes " + "CERR or MERGE_COUT_CERR"); + + if ((mode & IGNORE_COUT) && (mode & (COUT | MERGE_COUT_CERR))) + throw invalid_argument( + "IOMode IGNORE_COUT cannot be used with modes " + "COUT or MERGE_COUT_CERR"); + + if ((mode & MERGE_COUT_CERR) && (mode & (CERR | COUT))) + throw invalid_argument( + "IOMode MERGE_COUT_CERR cannot be used with modes COUT or CERR"); - if (d_mode & MERGE_COUT_CERR) // overrules either COUT or CERR - d_mode &= ~(COUT | CERR); - - return d_mode; + return d_mode = mode; } - diff -Nru bobcat-3.18.01/process/setbufsize.cc bobcat-3.19.01/process/setbufsize.cc --- bobcat-3.18.01/process/setbufsize.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/setbufsize.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,6 @@ +#include "process.ih" + +void Process::setBufSize(size_t bufSize) +{ + d_data->d_bufSize = bufSize == 0 ? 1 : bufSize; +} diff -Nru bobcat-3.18.01/process/setiomode.f bobcat-3.19.01/process/setiomode.f --- bobcat-3.18.01/process/setiomode.f 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/setiomode.f 2013-12-28 10:19:31.000000000 +0000 @@ -1,4 +1,4 @@ -inline void Process::setIOMode(iomode mode) +inline void Process::setIOMode(IOMode mode) { - d_setMode = sanitizeIOMode(mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC)); + d_setMode = sanitizeIOMode(mode); } diff -Nru bobcat-3.18.01/process/showmode.cc bobcat-3.19.01/process/showmode.cc --- bobcat-3.18.01/process/showmode.cc 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/showmode.cc 2013-12-28 10:19:31.000000000 +0000 @@ -4,8 +4,8 @@ { std::cerr << lab << ' ' << getpid() << ' ' << d_child.pid << " IOMode: "; - if (d_mode & STD) - std::cerr << "STD "; + if (d_mode == NONE) + std::cerr << "NONE "; if (d_mode & CIN) std::cerr << "CIN "; if (d_mode & COUT) @@ -31,3 +31,11 @@ std::cerr << '\n'; } + + + + + + + + diff -Nru bobcat-3.18.01/process/start.cc bobcat-3.19.01/process/start.cc --- bobcat-3.18.01/process/start.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/start.cc 1970-01-01 00:00:00.000000000 +0000 @@ -1,23 +0,0 @@ -#include "process.ih" - -void Process::start(iomode mode, ProcessType type, size_t timeLimit) -{ - if (d_active) - stop(); - - d_active = true; - d_timeLimit = timeLimit; - d_processType = type; - - sanitizeIOMode(mode); - newPipes(); - - if (d_command[0] == '`' && *d_command.rbegin() == '`') // rm backticks - d_command = d_command.substr(1, d_command.length() - 2); - - forking(); - - d_mode = d_setMode; // revert to the default process - d_processType = d_setProcessType; // parameters for a next run - d_timeLimit = d_setTimeLimit; -} diff -Nru bobcat-3.18.01/process/start1.cc bobcat-3.19.01/process/start1.cc --- bobcat-3.18.01/process/start1.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/start1.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,6 @@ +#include "process.ih" + +void Process::start(size_t mode, ProcessType type, size_t timeLimit) +{ + start(iomode(mode), type, timeLimit, bufSize()); +} diff -Nru bobcat-3.18.01/process/start1.f bobcat-3.19.01/process/start1.f --- bobcat-3.18.01/process/start1.f 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/start1.f 2013-12-28 10:19:31.000000000 +0000 @@ -1,4 +1,4 @@ inline void Process::start() -{ +{ start(d_setMode, d_setProcessType, d_setTimeLimit); } diff -Nru bobcat-3.18.01/process/start2.cc bobcat-3.19.01/process/start2.cc --- bobcat-3.18.01/process/start2.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/start2.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,34 @@ +#include "process.ih" + +void Process::start(IOMode mode, ProcessType type, size_t timeLimit, + size_t bufferSize) +{ + if (d_active) + stop(); + + size_t savedBufSize = bufSize(); + setBufSize(bufferSize); + + d_active = true; + d_timeLimit = timeLimit; + d_processType = type; + + rmBackticks(); // rm backticks from d_command + + sanitizeIOMode(mode); + // not yet using the time limit + // thread + d_data->d_limit = thread(limiter, this); + forking(); + + setBufSize(savedBufSize); + d_mode = d_setMode; // revert to the default process + d_processType = d_setProcessType; // parameters for a next run + d_timeLimit = d_setTimeLimit; +} + + + + + + diff -Nru bobcat-3.18.01/process/start2.f bobcat-3.19.01/process/start2.f --- bobcat-3.18.01/process/start2.f 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/start2.f 2013-12-28 10:19:31.000000000 +0000 @@ -1,4 +1,4 @@ -inline void Process::start(iomode mode) +inline void Process::start(IOMode mode) { start(mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC), d_setProcessType, d_setTimeLimit); diff -Nru bobcat-3.18.01/process/start3.f bobcat-3.19.01/process/start3.f --- bobcat-3.18.01/process/start3.f 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/start3.f 2013-12-28 10:19:31.000000000 +0000 @@ -1,4 +1,4 @@ -inline void Process::start(iomode mode, ProcessType type) +inline void Process::start(IOMode mode, ProcessType type) { start(mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC), type, d_setTimeLimit); } diff -Nru bobcat-3.18.01/process/stop.cc bobcat-3.19.01/process/stop.cc --- bobcat-3.18.01/process/stop.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/stop.cc 2013-12-28 10:19:31.000000000 +0000 @@ -5,8 +5,6 @@ if (!d_active) return -1; -// d_command.clear(); - d_oChildIn.flush(); d_oChildInbuf.open(-1); @@ -18,7 +16,8 @@ closeReadFd(d_iChildErrPipe); discontinue(d_child); - discontinue(d_monitor); + + d_data->d_limit.join(); d_active = false; diff -Nru bobcat-3.18.01/process/system1.f bobcat-3.19.01/process/system1.f --- bobcat-3.18.01/process/system1.f 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/system1.f 2013-12-28 10:19:31.000000000 +0000 @@ -1,4 +1,4 @@ inline void Process::system() { - start(d_mode, USE_SHELL, d_timeLimit); + start(d_mode, USE_SHELL, d_timeLimit, bufSize()); } diff -Nru bobcat-3.18.01/process/system2.f bobcat-3.19.01/process/system2.f --- bobcat-3.18.01/process/system2.f 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/system2.f 2013-12-28 10:19:31.000000000 +0000 @@ -1,5 +1,4 @@ -inline void Process::system(iomode mode) +inline void Process::system(IOMode mode) { - start(mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC), - USE_SHELL, d_timeLimit); + start(mode, USE_SHELL, d_timeLimit, bufSize()); } diff -Nru bobcat-3.18.01/process/system3.f bobcat-3.19.01/process/system3.f --- bobcat-3.18.01/process/system3.f 2013-11-13 10:44:53.000000000 +0000 +++ bobcat-3.19.01/process/system3.f 2013-12-28 10:19:31.000000000 +0000 @@ -1,4 +1,4 @@ -inline void Process::system(iomode mode, size_t timeLimit) +inline void Process::system(IOMode mode, size_t timeLimit) { - start(mode & ~(IN_PIPE | OUT_PIPE | CLOSE_ON_EXEC), USE_SHELL, timeLimit); + start(mode, USE_SHELL, timeLimit, bufSize()); } diff -Nru bobcat-3.18.01/process/system4.f bobcat-3.19.01/process/system4.f --- bobcat-3.18.01/process/system4.f 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/process/system4.f 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,4 @@ +inline void Process::system(IOMode mode, size_t timeLimit, size_t bufSize) +{ + start(mode, USE_SHELL, timeLimit, bufSize); +} diff -Nru bobcat-3.18.01/process/whichstream.cc bobcat-3.19.01/process/whichstream.cc --- bobcat-3.18.01/process/whichstream.cc 2013-10-02 10:36:00.000000000 +0000 +++ bobcat-3.19.01/process/whichstream.cc 2013-12-28 10:19:31.000000000 +0000 @@ -1,6 +1,6 @@ #include "process.ih" -size_t Process::whichStream() +Process::ChildOutput Process::whichStream() { d_selector.wait(); diff -Nru bobcat-3.18.01/processdata/destructor.cc bobcat-3.19.01/processdata/destructor.cc --- bobcat-3.18.01/processdata/destructor.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/processdata/destructor.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,6 @@ +#include "processdata.ih" + +ProcessData::~ProcessData() +{ + Signal::instance().remove(SIGCHLD, *this); +} diff -Nru bobcat-3.18.01/processdata/processdata.decl bobcat-3.19.01/processdata/processdata.decl --- bobcat-3.18.01/processdata/processdata.decl 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/processdata/processdata.decl 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,32 @@ +#ifndef INCLUDED_PROCESSDATA_DECL_ +#define INCLUDED_PROCESSDATA_DECL_ + +#include +#include +#include + +#include "../signal/signal" + +#include "../processenums/processenums" + +namespace FBB +{ + +struct ProcessData: private ProcessEnums, public SignalHandler +{ + std::thread d_limit; + volatile ChildAction d_action = CHILD_ENDED; + std::mutex d_mutex; + std::condition_variable d_condition; + size_t d_bufSize; + + ProcessData(size_t bufSize); + ~ProcessData() override; + + private: + void signalHandler(size_t signum) override; +}; + +} // FBB + +#endif diff -Nru bobcat-3.18.01/processdata/processdata.ih bobcat-3.19.01/processdata/processdata.ih --- bobcat-3.18.01/processdata/processdata.ih 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/processdata/processdata.ih 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,19 @@ +#include "processdata.decl" + +//#include // TMP + +//#include +//#include +//#include +// +//#include +//#include +// +//#include "../exception/exception" +//#include "../redirector/redirector" + +using namespace std; +using namespace FBB; + +// #include "retpid1.f" + diff -Nru bobcat-3.18.01/processdata/processdata1.cc bobcat-3.19.01/processdata/processdata1.cc --- bobcat-3.18.01/processdata/processdata1.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/processdata/processdata1.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,9 @@ +#include "processdata.ih" + +ProcessData::ProcessData(size_t bufSize) +: + d_bufSize(bufSize == 0 ? 1 : bufSize) +{ + Signal::instance().add(SIGCHLD, *this); +} + diff -Nru bobcat-3.18.01/processdata/signalhandler.cc bobcat-3.19.01/processdata/signalhandler.cc --- bobcat-3.18.01/processdata/signalhandler.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/processdata/signalhandler.cc 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,10 @@ +#include "processdata.ih" + +void ProcessData::signalHandler(size_t signal) +{ + if (d_action == TIME_LIMIT) + { + d_action = CHILD_ENDED; + d_condition.notify_one(); + } +} diff -Nru bobcat-3.18.01/processenums/processenums bobcat-3.19.01/processenums/processenums --- bobcat-3.18.01/processenums/processenums 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/processenums/processenums 2013-12-28 10:19:31.000000000 +0000 @@ -0,0 +1,130 @@ +#ifndef INCLUDED_BOBCAT_PROCESSENUMS_ +#define INCLUDED_BOBCAT_PROCESSENUMS_ + + +namespace FBB +{ + +struct ProcessEnums +{ + enum ChildOutput + { + NOTHING_AVAILABLE = 0, + CHILD_COUT = 1 << 0, + CHILD_CERR = 1 << 1, + }; + + enum IOMode: size_t + { + NONE = 0, // no piping/redirection + STD = NONE, // for backward compatibility reasons + + CIN = 1 << 0, + COUT = 1 << 1, + CERR = 1 << 2, + ALL = CIN | COUT | CERR, + + IGNORE_COUT = 1 << 3, + IGNORE_CERR = 1 << 4, + IGNORE_COUT_CERR = IGNORE_COUT | IGNORE_CERR, + + MERGE_COUT_CERR = 1 << 5, + + DIRECT = 1 << 8, + }; + + protected: + static IOMode iomode(size_t mode); + + enum IOModeExt + { + ALL_IOMODES = (1 << 9) - 1, + + IN_PIPE = 1 << 10, + OUT_PIPE = 1 << 11, + + CLOSE_ON_EXEC = 1 << 12, + PIPES_OK = 1 << 13 + }; + friend IOMode operator|(IOMode lhs, IOModeExt rhs); + friend IOMode operator|(IOModeExt lhs, IOModeExt rhs); + friend IOMode &operator|=(IOMode &lhs, IOModeExt rhs); + + enum ChildAction + { + TIME_LIMIT, + CHILD_ENDED + }; +}; + +inline ProcessEnums::ChildOutput operator|(ProcessEnums::ChildOutput lhs, + ProcessEnums::ChildOutput rhs) +{ + return static_cast( + static_cast(lhs) | static_cast(rhs)); +} + +inline bool operator&(ProcessEnums::ChildOutput lhs, + ProcessEnums::ChildOutput rhs) +{ + return static_cast(lhs) & static_cast(rhs); +} + +inline ProcessEnums::IOMode ProcessEnums::iomode(size_t mode) +{ + return static_cast(mode & ALL_IOMODES); +} + + +inline ProcessEnums::IOMode operator|(ProcessEnums::IOMode lhs, + ProcessEnums::IOMode rhs) +{ + return static_cast( + static_cast(lhs) | static_cast(rhs)); +} + + +inline ProcessEnums::IOMode operator|(ProcessEnums::IOMode lhs, + ProcessEnums::IOModeExt rhs) +{ + return static_cast( + static_cast(lhs) | static_cast(rhs)); +} + + +inline ProcessEnums::IOMode operator|(ProcessEnums::IOModeExt lhs, + ProcessEnums::IOModeExt rhs) +{ + return static_cast( + static_cast(lhs) | static_cast(rhs)); +} + +inline ProcessEnums::IOMode operator&(ProcessEnums::IOMode lhs, + ProcessEnums::IOMode rhs) +{ + return static_cast( + static_cast(lhs) & static_cast(rhs)); +} + +inline ProcessEnums::IOMode operator~(ProcessEnums::IOMode mode) +{ + return static_cast(~static_cast(mode)); +} + +inline ProcessEnums::IOMode &operator|=(ProcessEnums::IOMode &lhs, + ProcessEnums::IOMode rhs) +{ + reinterpret_cast(lhs) |= static_cast(rhs); + return lhs; +} + +inline ProcessEnums::IOMode &operator|=(ProcessEnums::IOMode &lhs, + ProcessEnums::IOModeExt rhs) +{ + reinterpret_cast(lhs) |= static_cast(rhs); + return lhs; +} + +} // FBB +#endif + diff -Nru bobcat-3.18.01/signal/remove.cc bobcat-3.19.01/signal/remove.cc --- bobcat-3.18.01/signal/remove.cc 1970-01-01 00:00:00.000000000 +0000 +++ bobcat-3.19.01/signal/remove.cc 2013-12-26 12:38:46.000000000 +0000 @@ -0,0 +1,21 @@ +#include "signal.ih" + +void Signal::remove(size_t signum, SignalHandler &object) +{ + verify(signum, "Signal::remove"); + + if (d_signals.size() <= signum) + throw Exception(1) << "no signal handlers for signal " << signum << + " were installed"; + + auto iter = + find(d_signals[signum].begin(), d_signals[signum].end(), &object); + + if (iter == d_signals[signum].end()) + throw Exception(1) << "object " << &object << + " did not register a handler for signal " << signum; + + d_signals[signum].erase(iter); + + signal(signum, handler); +} diff -Nru bobcat-3.18.01/signal/signal bobcat-3.19.01/signal/signal --- bobcat-3.18.01/signal/signal 2013-10-02 10:35:59.000000000 +0000 +++ bobcat-3.19.01/signal/signal 2013-12-26 12:39:10.000000000 +0000 @@ -22,6 +22,11 @@ typedef std::vector SignalHandlerVector; std::vector d_signals; + // d_signals is a vector of vectors of pointers to SignalHandlers + // the row dimension refers to the signal number + // each row holds a SignalHandler object handling that kind of signal + + static Signal *s_signal; public: @@ -31,6 +36,8 @@ Signal &operator=(Signal const &) = delete; void add(size_t signum, SignalHandler &object); + void remove(size_t signum, SignalHandler &object); + void ignore(size_t signum); void reset(size_t signum); diff -Nru bobcat-3.18.01/signal/signal.ih bobcat-3.19.01/signal/signal.ih --- bobcat-3.18.01/signal/signal.ih 2013-10-02 10:35:59.000000000 +0000 +++ bobcat-3.19.01/signal/signal.ih 2013-12-26 12:38:46.000000000 +0000 @@ -1,5 +1,9 @@ #include "signal" +//#include // TMP + +#include + #include using namespace std;