aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-08-14 17:24:50 +0300
committerSergey Poznyakoff <gray@gnu.org>2019-08-14 17:24:50 +0300
commit5b7e047dfdb34d0fdc3720e14dd08a7693948b2f (patch)
tree5a1100f05f72a2168bf1d66b14acf7f0b475da3c
parent1309ae35b1ff7ed26a3ccc2fcdc6bd13bb494cee (diff)
downloadruncap-5b7e047dfdb34d0fdc3720e14dd08a7693948b2f.tar.gz
runcap-5b7e047dfdb34d0fdc3720e14dd08a7693948b2f.tar.bz2
Update READMEv1.1
-rw-r--r--README256
1 files changed, 241 insertions, 15 deletions
diff --git a/README b/README
index f94219f..2ccdb24 100644
--- a/README
+++ b/README
@@ -1,36 +1,204 @@
1#+TITLE: runcap
2
3* Overview 1* Overview
4 2
5The function *runcap* runs an external command, and waits for its 3The function *runcap* runs an external command, and waits for its
6termination, optionally capturing its standard output and standard 4termination, optionally capturing its standard output and standard
7error streams, and piping data to its standard input. 5error streams, and piping data to its standard input.
8 6
9* Building as a standalone library 7Upon return from the function, the caller can obtain the termination
8status of the program and access the captured output data.
9
10* Usage
11
12The function *runcap* is defined as follows:
13
14#+BEGIN_SRC C
15int runcap(struct runcap *rc, int flags);
16#+END_SRC
17
18The =rc= argument points to the structure that controls the execution
19of the program. It contains the input and output members. The only
20member of this structure that must be initialized on input is
21=rc_argv=, which points to the array of pointers to
22null-terminated strings that represent the command name and the
23argument list to that program. Initialization of the rest of input
24members is optional. For each input member, there is a corresponding
25flag in =flags= which must be set, if the member is initialized. For
26example, if the =rc_timeout= member is set (indicating maximum time
27the program execution is allowed to take), then the =RCF_TIMEOUT= flag
28must be set.
29
30Upon return, the function returns the execution status of the
31program, and initializes the output members of =rc= to hold the
32standard output and standard error streams captured from the command.
33Special functions are provided to read these streams.
34
35For a detailed description of *runcap* and accompanying functions,
36please see the [[http://man.gnu.org.ua/manpage/?3+runcap][runcap]](3) manual. In this chapter we will illustrate
37the usage of the *runcap* library by examples.
38
39The example below defines the function *runcom* with the following
40prototype:
41
42#+BEGIN_SRC C
43int runcom(char *cmd, char *in, char **out, char **err);
44#+END_SRC
45
46The function runs the command line given in the ~cmd~ argument
47using =/bin/sh= and returns the data it printed on its standard output
48and error streams in the memory locations pointed to by the arguments
49~out~ and ~err~, correspondingly. If any of these arguments is
50=NULL=, capturing of the corresponding stream will be disabled.
51
52The function returns program exit status on success, -1 if the program
53terminated on signal and -2 on error. This example implements only
54rudimentary error handling, in order to minimize the amount of
55irrelevant code.
56
57#+BEGIN_SRC C
58int runcom(char *cmd, char *in, char **out, char **err)
59{
60 int status;
61 char *p;
62 char c;
63 char *argv[] = { "/bin/sh", "-c", cmd, NULL };
64 struct runcap rc;
65 int rcflags = RCF_TIMEOUT;
66
67 /* Declare the command line to be run. The rc_argv filed is the
68 * only field that must be initialized on input.
69 */
70 rc.rc_argv = argv;
71
72 /* Set maximum execution timeout. The presense of this setting is
73 * indicated by the RCF_TIMEOUT flag in rcflags.
74 */
75 rc.rc_timeout = 10;
76
77 /* If the input string is supplied, initialize the input stream and
78 * raise the RCF_STDIN flag to indicate that it has been initialized.
79 */
80 if (in) {
81 rc.rc_cap[RUNCAP_STDIN].sc_base = in;
82 rc.rc_cap[RUNCAP_STDIN].sc_size = strlen(in);
83 rc.rc_cap[RUNCAP_STDIN].sc_fd = -1;
84 rcflags |= RCF_STDIN;
85 }
86
87 /* If out argument is NULL, disable capturing program's stdout. To
88 * disable capturing a stream, it suffices to initialize its sc_size
89 * field to zero and raise the corresponding RCF_*_SIZE bit in flags.
90 */
91 if (!out) {
92 rc.rc_cap[RUNCAP_STDOUT].sc_size = 0;
93 rcflags |= RCF_STDOUT_SIZE;
94 }
95
96 /* Same for the stderr: */
97 if (!err) {
98 rc.rc_cap[RUNCAP_STDERR].sc_size = 0;
99 rcflags |= RCF_STDERR_SIZE;
100 }
101
102 /* Run the command. The runcap function returns 0 on success. On
103 * error, it returns -1 and sets the errno variable. Its value is
104 * also duplicated in the rc_errno member of struct runcap.
105 */
106 if (runcap(&rc, rcflags)) {
107 perror("runcap");
108 return -2;
109 }
110
111 /* Upon return, the sc_leng member of the capturing structure for
112 * stdout and stderr contains total amount of bytes in the corresponding
113 * stream. The stream can be read using the runcap_getc and
114 * runcap_getline functions.
115 */
116 if (rc.rc_cap[RUNCAP_STDOUT].sc_leng) {
117 p = malloc(rc.rc_cap[RUNCAP_STDOUT].sc_leng + 1);
118 assert(p != NULL);
119 *out = p;
120 while (runcap_getc(&rc, RUNCAP_STDOUT, &c))
121 *p++ = c;
122 *p = 0;
123 } else
124 *out = NULL;
125
126 if (rc.rc_cap[RUNCAP_STDERR].sc_leng) {
127 p = malloc(rc.rc_cap[RUNCAP_STDERR].sc_leng + 1);
128 assert(p != NULL);
129 *err = p;
130 while (runcap_getc(&rc, RUNCAP_STDERR, &c))
131 *p++ = c;
132 *p = 0;
133 } else
134 *err = NULL;
135
136 /* Analyze the exit status of the command */
137 if (WIFEXITED(rc.rc_status)) {
138 status = WEXITSTATUS(rc.rc_status);
139 } else {
140 status = -1;
141
142 if (WIFSIGNALED(rc.rc_status)) {
143 fprintf(stderr, "%s terminated on signal %d\n",
144 argv[0], WTERMSIG(rc.rc_status));
145 } else {
146 fprintf(stderr, "%s terminated with unrecognized status: %d\n",
147 argv[0], rc.rc_status);
148 }
149 }
150 return status;
151}
152#+END_SRC
153
154* Downloading
10 155
11The following steps will build the project as a standalone installable 156To clone the project from the repository, run
12library: 157
158#+BEGIN_SRC shell-script
159git clone git://git.gnu.org.ua/runcap.git
160#+END_SRC
161
162* Building
163
164The project can be used either a standalone library, or as a shared
165or static convenience library embedded in another project. If you
166cloned the project from the git repository, you will need to
167bootstrap it first. To do so, change to the =runcap= directory and
168run
169#+BEGIN_SRC shell-script
170 autoreconf -I. -f -i -s
171#+END_SRC
172
173Use the =RUNCAP_BUILD= environment variable to indicate the type of
174the build you need. Allowed values are:
175
176- install :: Build standalone installable library (default).
177- shared :: Build shared convenience library.
178- static :: Build static convenience library.
179
180Once bootstrapped, the project can be built with the usual sequence
181of commands:
13 182
141. Configure the package 1831. Configure the package
15 #+BEGIN_SRC shell-script 184 #+BEGIN_SRC shell-script
16 ./configure 185 ./configure
17 #+END_SRC 186 #+END_SRC
182. Build the project. 1872. Build it
19 #+BEGIN_SRC shell-script 188 #+BEGIN_SRC shell-script
20 make 189 make
21 #+END_SRC 190 #+END_SRC
223. Install the files (normally run as root). 1913. If building installable library, install it (normally run as root).
23 #+BEGIN_SRC shell-script 192 #+BEGIN_SRC shell-script
24 make install 193 make install
25 #+END_SRC 194 #+END_SRC
26
27 This will install the files *libruncap.so* and *libruncap.a* to the 195 This will install the files *libruncap.so* and *libruncap.a* to the
28 system library directory, and the header file *runcap.h* to the 196 system library directory, and the header file *runcap.h* to the
29 system include directory. 197 system include directory.
30 198
31* Incorporating as a submodule 199* Incorporating as a submodule
32 200
33To incorporate *runcap* as a submodule to your project, follow these 201To incorporate *runcap* to your project as a submodule, follow these
34steps: 202steps:
35 203
361. Change to your project's toplevel directory. 2041. Change to your project's toplevel directory.
@@ -49,20 +217,78 @@ steps:
49 217
50 SUBDIRS = runcap 218 SUBDIRS = runcap
51 #+END_SRC 219 #+END_SRC
525. Edit your *configure.ac* 2205. Edit your *configure.ac*. Add the following line:
53 #+BEGIN_SRC automake 221 #+BEGIN_SRC autoconf
54 RUNCAP_SETUP 222 RUNCAP_SETUP
55 #+END_SRC 223 #+END_SRC
566. 2246. Add the following to the *Makefile.am* file which builds the target
225 that uses on the *runcap* library:
57 #+BEGIN_SRC make 226 #+BEGIN_SRC make
58 AM_CPPFLAGS = @RUNCAP_INC@ 227 AM_CPPFLAGS = @RUNCAP_INC@
59 AM_LDADD = @RUNCAP_LDADD@ 228 LDADD = @RUNCAP_LDADD@
60 #+END_SRC 229 #+END_SRC