aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2017-12-01 08:46:15 +0200
committerSergey Poznyakoff <gray@gnu.org>2017-12-01 08:47:56 +0200
commit048800a78f64808116bb9b943837062a67f586ae (patch)
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.
-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
--- /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
@@ -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,
diff --git a/runcap.c b/runcap.c
index 26654f8..6790dc4 100644
--- a/runcap.c
+++ b/runcap.c
@@ -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;

Return to:

Send suggestions and report system problems to the System administrator.