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 @@
1#+TITLE: runcap
2
3* Overview
4
5The function *runcap* runs an external command, and waits for its
6termination, optionally capturing its standard output and standard
7error streams, and piping data to its standard input.
8
9* Building as a standalone library
10
11The following steps will build the project as a standalone installable
12library:
13
141. Configure the package
15 #+BEGIN_SRC shell-script
16 ./configure
17 #+END_SRC
182. Build the project.
19 #+BEGIN_SRC shell-script
20 make
21 #+END_SRC
223. Install the files (normally run as root).
23 #+BEGIN_SRC shell-script
24 make install
25 #+END_SRC
26
27 This will install the files *libruncap.so* and *libruncap.a* to the
28 system library directory, and the header file *runcap.h* to the
29 system include directory.
30
31* Incorporating as a submodule
32
33To incorporate *runcap* as a submodule to your project, follow these
34steps:
35
361. Change to your project's toplevel directory.
372. Clone the project.
38 #+BEGIN_SRC shell-script
39 git submodule add git://git.gnu.org.ua/runcap.git
40 git submodule init
41 #+END_SRC
423. Add it to *git* index:
43 #+BEGIN_SRC shell-script
44 git add runcap
45 #+END_SRC
464. Add it to your toplevel *Makefile.am*.
47 #+BEGIN_SRC make
48 ACLOCAL_AMFLAGS = -I grecs/am
49
50 SUBDIRS = runcap
51 #+END_SRC
525. Edit your *configure.ac*
53 #+BEGIN_SRC automake
54 RUNCAP_SETUP
55 #+END_SRC
566.
57 #+BEGIN_SRC make
58 AM_CPPFLAGS = @RUNCAP_INC@
59 AM_LDADD = @RUNCAP_LDADD@
60 #+END_SRC
61
62
63# Local Variables:
64# mode: org
65# paragraph-separate: "[ ^L]*$"
66# version-control: never
67# End:
68
diff --git a/runcap.3 b/runcap.3
index 0a5a89c..4a425d6 100644
--- a/runcap.3
+++ b/runcap.3
@@ -10,13 +10,13 @@
10.\" but WITHOUT ANY WARRANTY; without even the implied warranty of 10.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
11.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12.\" GNU General Public License for more details. 12.\" GNU General Public License for more details.
13.\" 13.\"
14.\" You should have received a copy of the GNU General Public License 14.\" You should have received a copy of the GNU General Public License
15.\" along with runcap. If not, see <http://www.gnu.org/licenses/>. 15.\" along with runcap. If not, see <http://www.gnu.org/licenses/>.
16.TH RUNCAP 2 "August 19, 2017" "RUNCAP" "User Commands" 16.TH RUNCAP 2 "August 22, 2017" "RUNCAP" "User Commands"
17.SH NAME 17.SH NAME
18runcap \- run external process and capture its stdout and stderr 18runcap \- run external process and capture its stdout and stderr
19.SH SYNOPSIS 19.SH SYNOPSIS
20.nf 20.nf
21.B #include <runcap.h> 21.B #include <runcap.h>
22.sp 22.sp
@@ -75,18 +75,18 @@ struct runcap
75 int rc_status; /* [\fIOUT\fR] Termination status */ 75 int rc_status; /* [\fIOUT\fR] Termination status */
76 int rc_errno; /* [\fIOUT\fR] System error code */ 76 int rc_errno; /* [\fIOUT\fR] System error code */
77}; 77};
78.fi 78.fi
79.in 79.in
80.PP 80.PP
81The members that may be initialized on input are marked with 81Members that may be initialized on input are marked with
82[\fIIN\fR], those that are set upon return from \fBruncap()\fR are 82[\fIIN\fR], those that are set upon return from \fBruncap()\fR are
83marked with [\fIOUT\fR]. 83marked with [\fIOUT\fR].
84.PP 84.PP
85The caller is responsible for initializing the \fBrc_argv\fR member 85The caller is responsible for initializing the \fBrc_argv\fR member
86with a pointer to the command line arguments array. The other 86with a pointer to the command line arguments array. Other
87input fields are: 87input fields are:
88.TP 88.TP
89.B rc_program 89.B rc_program
90Actual pathname of the program to be executed. If initialized, the 90Actual pathname of the program to be executed. If initialized, the
91\fBRCF_PROGRAM\fR bit must be set in \fIflags\fR. Otherwise, the 91\fBRCF_PROGRAM\fR bit must be set in \fIflags\fR. Otherwise, the
92value of \fBrc_argv[0]\fR is assumed. 92value of \fBrc_argv[0]\fR is assumed.
@@ -137,26 +137,27 @@ struct stream_capture
137The caller may initialize the following members in 137The caller may initialize the following members in
138\fBrc_cap[RUNCAP_STDOUT]\fR and \fBrc_cap[RUNCAP_STDERR]\fR: 138\fBrc_cap[RUNCAP_STDOUT]\fR and \fBrc_cap[RUNCAP_STDERR]\fR:
139.TP 139.TP
140.B sc_size 140.B sc_size
141Size of the buffer (\fBsize_t\fR). If set, the \fBRCF_STDOUT_SIZE\fR 141Size of the buffer (\fBsize_t\fR). If set, the \fBRCF_STDOUT_SIZE\fR
142(for \fBRUNCAP_STDOUT\fR) or \fBRCF_STDERR_SIZE\fR (for 142(for \fBRUNCAP_STDOUT\fR) or \fBRCF_STDERR_SIZE\fR (for
143\fBRUNCAP_STDERR\fR) bit must be set in \fIflags\fR. The default 143\fBRUNCAP_STDERR\fR) bit must be set in \fIflags\fR. If the amount of
144buffer size is 4096 bytes. If the amount of input data exceeds the 144input data exceeds the buffer size, the data are saved in the disk
145buffer size, the data are saved in the disk file, therefore setting a 145file, therefore setting a larger buffer can improve performance.
146larger buffer can improve performance. Setting \fBsc_size\fR to 0 146Setting \fBsc_size\fR to 0 disables capturing.
147disables capturing. 147
148Default buffer size is 4096 bytes.
148.TP 149.TP
149.B sc_linemon 150.B sc_linemon
150A pointer to the line monitor function. If set, the 151A pointer to the line monitor function. If set, the
151\fBRCF_STDOUT_LINEMON\fR (for \fBRUNCAP_STDOUT\fR), or 152\fBRCF_STDOUT_LINEMON\fR (for \fBRUNCAP_STDOUT\fR), or
152\fBRCF_STDERR_LINEMON\fR (for \fBRUNCAP_STDERR\fR) bit must be set in 153\fBRCF_STDERR_LINEMON\fR (for \fBRUNCAP_STDERR\fR) bit must be set in
153\fIflags\fR. 154\fIflags\fR.
154.sp 155.sp
155The line monitor function allows the caller to monitor the arrival of 156The line monitor function allows the caller to monitor the arrival of
156the new data in the corresponding stream. Its signature is: 157the new data in the corresponding stream. It is declared as follows:
157.sp 158.sp
158.BI "void linemon(const char *" line ", size_t " size ", void *" data ) 159.BI "void linemon(const char *" line ", size_t " size ", void *" data )
159.sp 160.sp
160where \fIline\fR is the line that has been read, \fIsize\fR is its 161where \fIline\fR is the line that has been read, \fIsize\fR is its
161length, and \fIdata\fR is an opaque pointer to application-specific 162length, and \fIdata\fR is an opaque pointer to application-specific
162data, supplied in the \fBsc_monarg\fR member. 163data, supplied in the \fBsc_monarg\fR member.
@@ -205,13 +206,13 @@ Upon return, the following fields are initialized:
205Termination status, as returned by 206Termination status, as returned by
206.BR wait (2). 207.BR wait (2).
207.TP 208.TP
208.B rc_errno 209.B rc_errno
209Value of errno, if terminated on error. 210Value of errno, if terminated on error.
210.PP 211.PP
211Upon successful return, the following fields are initialized: 212The following fields are defined upon successful return:
212.TP 213.TP
213.B rc_cap[RUNCAP_STDOUT].sc_leng 214.B rc_cap[RUNCAP_STDOUT].sc_leng
214Total length of captured stdout. 215Total length of captured stdout.
215.TP 216.TP
216.B rc_cap[RUNCAP_STDOUT].sc_nlines 217.B rc_cap[RUNCAP_STDOUT].sc_nlines
217Number of lines in the captured stdout. 218Number of lines in the captured stdout.
@@ -224,13 +225,13 @@ Number of lines in the captured stderr.
224.PP 225.PP
225The actual data can be retrieved using the \fBruncap_getc\fR, and 226The actual data can be retrieved using the \fBruncap_getc\fR, and
226\fBruncap_getline\fR functions, described below. 227\fBruncap_getline\fR functions, described below.
227.SH Examining output 228.SH Examining output
228Upon return from \fBruncap\fR the following functions can be used to 229Upon return from \fBruncap\fR the following functions can be used to
229retrieve the captured data from the \fBstruct runcap\fR object pointed 230retrieve the captured data from the \fBstruct runcap\fR object pointed
230to by its \fIrc\fR argument. The stream to retrieve the data from is 231to by its \fIrc\fR argument. The stream to retrieve data from is
231identified by the \fIstream\fR argument, whose valid values are 232identified by the \fIstream\fR argument, whose valid values are
232\fBRUNCAP_STDOUT\fR (or \fB1\fR) or \fBRUNCAP_STDERR\fR (or \fB2\fR). 233\fBRUNCAP_STDOUT\fR (or \fB1\fR) or \fBRUNCAP_STDERR\fR (or \fB2\fR).
233.PP 234.PP
234The function \fBruncap_getc\fR reads the next character from the 235The function \fBruncap_getc\fR reads the next character from the
235captured stream and returns it as an unsigned char cast to an int. 236captured stream and returns it as an unsigned char cast to an int.
236It returns 0 on end of stream, and -1 on error. In the latter case, 237It 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)
134 if (cap->sc_level == cap->sc_size) { 134 if (cap->sc_level == cap->sc_size) {
135 if (stream_capture_flush(cap)) 135 if (stream_capture_flush(cap))
136 return -1; 136 return -1;
137 } 137 }
138 138
139 rc = read(cap->sc_fd, cap->sc_base + cap->sc_level, cap->sc_size - cap->sc_level); 139 rc = read(cap->sc_fd, cap->sc_base + cap->sc_level, cap->sc_size - cap->sc_level);
140 if (rc == -1) 140 if (rc == -1) {
141 if (errno == EINTR)
142 return 0;
141 return -1; 143 return -1;
144 }
142 if (rc == 0) { 145 if (rc == 0) {
143 *feof = 1; 146 *feof = 1;
144 return 0; 147 return 0;
145 } else 148 } else
146 *feof = 0; 149 *feof = 0;
147 150
@@ -167,14 +170,17 @@ stream_capture_get(struct stream_capture *cap, int *feof)
167 170
168static int 171static int
169stream_capture_put(struct stream_capture *cap, int *feof) 172stream_capture_put(struct stream_capture *cap, int *feof)
170{ 173{
171 if (cap->sc_cur < cap->sc_level) { 174 if (cap->sc_cur < cap->sc_level) {
172 int n = write(cap->sc_fd, &cap->sc_base[cap->sc_cur], 1); 175 int n = write(cap->sc_fd, &cap->sc_base[cap->sc_cur], 1);
173 if (n == -1) 176 if (n == -1) {
177 if (errno == EINTR)