summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2017-12-01 06:46:15 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2017-12-01 06:47:56 (GMT)
commit048800a78f64808116bb9b943837062a67f586ae (patch) (side-by-side diff)
treeec97848673a9ebfe6cb5fe8c7ef4e96d943db004
parent0145de1db25c3840346b9cd9ea44e571812e5516 (diff)
downloadruncap-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.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--README68
-rw-r--r--runcap.323
-rw-r--r--runcap.c12
3 files changed, 90 insertions, 13 deletions
diff --git a/README b/README
new file mode 100644
index 0000000..91f5b16
--- a/dev/null
+++ b/README
@@ -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:
+
diff --git a/runcap.3 b/runcap.3
index 0a5a89c..4a425d6 100644
--- a/runcap.3
+++ b/runcap.3
@@ -13,7 +13,7 @@
.\"
.\" 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
@@ -78,12 +78,12 @@ struct runcap
.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
@@ -140,11 +140,12 @@ The caller may initialize the following members in
.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
@@ -153,7 +154,7 @@ A pointer to the line monitor function. If set, the
\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
@@ -208,7 +209,7 @@ Termination status, as returned by
.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.
@@ -227,7 +228,7 @@ The actual data can be retrieved using the \fBruncap_getc\fR, and
.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
diff --git a/runcap.c b/runcap.c
index 26654f8..6790dc4 100644
--- a/runcap.c
+++ b/runcap.c
@@ -137,8 +137,11 @@ stream_capture_get(struct stream_capture *cap, int *feof)
}
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;
@@ -170,8 +173,11 @@ 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;
@@ -329,6 +335,8 @@ runcap_loop(struct runcap *rc)
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;

Return to:

Send suggestions and report system problems to the System administrator.