diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2017-12-01 08:46:15 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2017-12-01 08:47:56 +0200 |
commit | 048800a78f64808116bb9b943837062a67f586ae (patch) | |
tree | ec97848673a9ebfe6cb5fe8c7ef4e96d943db004 | |
parent | 0145de1db25c3840346b9cd9ea44e571812e5516 (diff) | |
download | runcap-048800a78f64808116bb9b943837062a67f586ae.tar.gz runcap-048800a78f64808116bb9b943837062a67f586ae.tar.bz2 |
Bugfixes
* runcap.3: Update docs.
* runcap.c (stream_capture_get,stream_capture_put)
(runcap_loop): Handle EINTR.
* README: New file.
-rw-r--r-- | README | 68 | ||||
-rw-r--r-- | runcap.3 | 23 | ||||
-rw-r--r-- | runcap.c | 12 |
3 files changed, 90 insertions, 13 deletions
@@ -0,0 +1,68 @@ +#+TITLE: runcap + +* Overview + +The function *runcap* runs an external command, and waits for its +termination, optionally capturing its standard output and standard +error streams, and piping data to its standard input. + +* Building as a standalone library + +The following steps will build the project as a standalone installable +library: + +1. Configure the package + #+BEGIN_SRC shell-script + ./configure + #+END_SRC +2. Build the project. + #+BEGIN_SRC shell-script + make + #+END_SRC +3. Install the files (normally run as root). + #+BEGIN_SRC shell-script + make install + #+END_SRC + + This will install the files *libruncap.so* and *libruncap.a* to the + system library directory, and the header file *runcap.h* to the + system include directory. + +* Incorporating as a submodule + +To incorporate *runcap* as a submodule to your project, follow these +steps: + +1. Change to your project's toplevel directory. +2. Clone the project. + #+BEGIN_SRC shell-script + git submodule add git://git.gnu.org.ua/runcap.git + git submodule init + #+END_SRC +3. Add it to *git* index: + #+BEGIN_SRC shell-script + git add runcap + #+END_SRC +4. Add it to your toplevel *Makefile.am*. + #+BEGIN_SRC make + ACLOCAL_AMFLAGS = -I grecs/am + + SUBDIRS = runcap + #+END_SRC +5. Edit your *configure.ac* + #+BEGIN_SRC automake + RUNCAP_SETUP + #+END_SRC +6. + #+BEGIN_SRC make + AM_CPPFLAGS = @RUNCAP_INC@ + AM_LDADD = @RUNCAP_LDADD@ + #+END_SRC + + +# Local Variables: +# mode: org +# paragraph-separate: "[ ^L]*$" +# version-control: never +# End: + @@ -10,13 +10,13 @@ .\" but WITHOUT ANY WARRANTY; without even the implied warranty of .\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public License .\" along with runcap. If not, see <http://www.gnu.org/licenses/>. -.TH RUNCAP 2 "August 19, 2017" "RUNCAP" "User Commands" +.TH RUNCAP 2 "August 22, 2017" "RUNCAP" "User Commands" .SH NAME runcap \- run external process and capture its stdout and stderr .SH SYNOPSIS .nf .B #include <runcap.h> .sp @@ -75,18 +75,18 @@ struct runcap int rc_status; /* [\fIOUT\fR] Termination status */ int rc_errno; /* [\fIOUT\fR] System error code */ }; .fi .in .PP -The members that may be initialized on input are marked with +Members that may be initialized on input are marked with [\fIIN\fR], those that are set upon return from \fBruncap()\fR are marked with [\fIOUT\fR]. .PP The caller is responsible for initializing the \fBrc_argv\fR member -with a pointer to the command line arguments array. The other +with a pointer to the command line arguments array. Other input fields are: .TP .B rc_program Actual pathname of the program to be executed. If initialized, the \fBRCF_PROGRAM\fR bit must be set in \fIflags\fR. Otherwise, the value of \fBrc_argv[0]\fR is assumed. @@ -137,26 +137,27 @@ struct stream_capture The caller may initialize the following members in \fBrc_cap[RUNCAP_STDOUT]\fR and \fBrc_cap[RUNCAP_STDERR]\fR: .TP .B sc_size Size of the buffer (\fBsize_t\fR). If set, the \fBRCF_STDOUT_SIZE\fR (for \fBRUNCAP_STDOUT\fR) or \fBRCF_STDERR_SIZE\fR (for -\fBRUNCAP_STDERR\fR) bit must be set in \fIflags\fR. The default -buffer size is 4096 bytes. If the amount of input data exceeds the -buffer size, the data are saved in the disk file, therefore setting a -larger buffer can improve performance. Setting \fBsc_size\fR to 0 -disables capturing. +\fBRUNCAP_STDERR\fR) bit must be set in \fIflags\fR. If the amount of +input data exceeds the buffer size, the data are saved in the disk +file, therefore setting a larger buffer can improve performance. +Setting \fBsc_size\fR to 0 disables capturing. + +Default buffer size is 4096 bytes. .TP .B sc_linemon A pointer to the line monitor function. If set, the \fBRCF_STDOUT_LINEMON\fR (for \fBRUNCAP_STDOUT\fR), or \fBRCF_STDERR_LINEMON\fR (for \fBRUNCAP_STDERR\fR) bit must be set in \fIflags\fR. .sp The line monitor function allows the caller to monitor the arrival of -the new data in the corresponding stream. Its signature is: +the new data in the corresponding stream. It is declared as follows: .sp .BI "void linemon(const char *" line ", size_t " size ", void *" data ) .sp where \fIline\fR is the line that has been read, \fIsize\fR is its length, and \fIdata\fR is an opaque pointer to application-specific data, supplied in the \fBsc_monarg\fR member. @@ -205,13 +206,13 @@ Upon return, the following fields are initialized: Termination status, as returned by .BR wait (2). .TP .B rc_errno Value of errno, if terminated on error. .PP -Upon successful return, the following fields are initialized: +The following fields are defined upon successful return: .TP .B rc_cap[RUNCAP_STDOUT].sc_leng Total length of captured stdout. .TP .B rc_cap[RUNCAP_STDOUT].sc_nlines Number of lines in the captured stdout. @@ -224,13 +225,13 @@ Number of lines in the captured stderr. .PP The actual data can be retrieved using the \fBruncap_getc\fR, and \fBruncap_getline\fR functions, described below. .SH Examining output Upon return from \fBruncap\fR the following functions can be used to retrieve the captured data from the \fBstruct runcap\fR object pointed -to by its \fIrc\fR argument. The stream to retrieve the data from is +to by its \fIrc\fR argument. The stream to retrieve data from is identified by the \fIstream\fR argument, whose valid values are \fBRUNCAP_STDOUT\fR (or \fB1\fR) or \fBRUNCAP_STDERR\fR (or \fB2\fR). .PP The function \fBruncap_getc\fR reads the next character from the captured stream and returns it as an unsigned char cast to an int. It returns 0 on end of stream, and -1 on error. In the latter case, @@ -134,14 +134,17 @@ stream_capture_get(struct stream_capture *cap, int *feof) if (cap->sc_level == cap->sc_size) { if (stream_capture_flush(cap)) return -1; } rc = read(cap->sc_fd, cap->sc_base + cap->sc_level, cap->sc_size - cap->sc_level); - if (rc == -1) + if (rc == -1) { + if (errno == EINTR) + return 0; return -1; + } if (rc == 0) { *feof = 1; return 0; } else *feof = 0; @@ -167,14 +170,17 @@ stream_capture_get(struct stream_capture *cap, int *feof) static int stream_capture_put(struct stream_capture *cap, int *feof) { if (cap->sc_cur < cap->sc_level) { int n = write(cap->sc_fd, &cap->sc_base[cap->sc_cur], 1); - if (n == -1) + if (n == -1) { + if (errno == EINTR) + return 0; return -1; + } if (n == 0) { errno = ENOSPC; return -1; } cap->sc_cur++; } @@ -326,12 +332,14 @@ runcap_loop(struct runcap *rc) pid_t pid; if (nfd == 0 && rc->rc_timeout == 0) flags = 0; pid = waitpid(rc->rc_pid, &rc->rc_status, flags); if (pid == -1) { + if (errno == EINTR) + continue; rc->rc_errno = errno; kill(rc->rc_pid, SIGKILL); break; } if (pid == rc->rc_pid) rc->rc_pid = (pid_t) -1; |