diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-08-14 17:24:50 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-08-14 17:24:50 +0300 |
commit | 5b7e047dfdb34d0fdc3720e14dd08a7693948b2f (patch) | |
tree | 5a1100f05f72a2168bf1d66b14acf7f0b475da3c | |
parent | 1309ae35b1ff7ed26a3ccc2fcdc6bd13bb494cee (diff) | |
download | runcap-5b7e047dfdb34d0fdc3720e14dd08a7693948b2f.tar.gz runcap-5b7e047dfdb34d0fdc3720e14dd08a7693948b2f.tar.bz2 |
Update READMEv1.1
-rw-r--r-- | README | 256 |
1 files changed, 241 insertions, 15 deletions
@@ -1,36 +1,204 @@ | |||
1 | #+TITLE: runcap | ||
2 | |||
3 | * Overview | 1 | * Overview |
4 | 2 | ||
5 | The function *runcap* runs an external command, and waits for its | 3 | The function *runcap* runs an external command, and waits for its |
6 | termination, optionally capturing its standard output and standard | 4 | termination, optionally capturing its standard output and standard |
7 | error streams, and piping data to its standard input. | 5 | error streams, and piping data to its standard input. |
8 | 6 | ||
9 | * Building as a standalone library | 7 | Upon return from the function, the caller can obtain the termination |
8 | status of the program and access the captured output data. | ||
9 | |||
10 | * Usage | ||
11 | |||
12 | The function *runcap* is defined as follows: | ||
13 | |||
14 | #+BEGIN_SRC C | ||
15 | int runcap(struct runcap *rc, int flags); | ||
16 | #+END_SRC | ||
17 | |||
18 | The =rc= argument points to the structure that controls the execution | ||
19 | of the program. It contains the input and output members. The only | ||
20 | member of this structure that must be initialized on input is | ||
21 | =rc_argv=, which points to the array of pointers to | ||
22 | null-terminated strings that represent the command name and the | ||
23 | argument list to that program. Initialization of the rest of input | ||
24 | members is optional. For each input member, there is a corresponding | ||
25 | flag in =flags= which must be set, if the member is initialized. For | ||
26 | example, if the =rc_timeout= member is set (indicating maximum time | ||
27 | the program execution is allowed to take), then the =RCF_TIMEOUT= flag | ||
28 | must be set. | ||
29 | |||
30 | Upon return, the function returns the execution status of the | ||
31 | program, and initializes the output members of =rc= to hold the | ||
32 | standard output and standard error streams captured from the command. | ||
33 | Special functions are provided to read these streams. | ||
34 | |||
35 | For a detailed description of *runcap* and accompanying functions, | ||
36 | please see the [[http://man.gnu.org.ua/manpage/?3+runcap][runcap]](3) manual. In this chapter we will illustrate | ||
37 | the usage of the *runcap* library by examples. | ||
38 | |||
39 | The example below defines the function *runcom* with the following | ||
40 | prototype: | ||
41 | |||
42 | #+BEGIN_SRC C | ||
43 | int runcom(char *cmd, char *in, char **out, char **err); | ||
44 | #+END_SRC | ||
45 | |||
46 | The function runs the command line given in the ~cmd~ argument | ||
47 | using =/bin/sh= and returns the data it printed on its standard output | ||
48 | and 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 | |||
52 | The function returns program exit status on success, -1 if the program | ||
53 | terminated on signal and -2 on error. This example implements only | ||
54 | rudimentary error handling, in order to minimize the amount of | ||
55 | irrelevant code. | ||
56 | |||
57 | #+BEGIN_SRC C | ||
58 | int 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 | ||
11 | The following steps will build the project as a standalone installable | 156 | To clone the project from the repository, run |
12 | library: | 157 | |
158 | #+BEGIN_SRC shell-script | ||
159 | git clone git://git.gnu.org.ua/runcap.git | ||
160 | #+END_SRC | ||
161 | |||
162 | * Building | ||
163 | |||
164 | The project can be used either a standalone library, or as a shared | ||
165 | or static convenience library embedded in another project. If you | ||
166 | cloned the project from the git repository, you will need to | ||
167 | bootstrap it first. To do so, change to the =runcap= directory and | ||
168 | run | ||
169 | #+BEGIN_SRC shell-script | ||
170 | autoreconf -I. -f -i -s | ||
171 | #+END_SRC | ||
172 | |||
173 | Use the =RUNCAP_BUILD= environment variable to indicate the type of | ||
174 | the 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 | |||
180 | Once bootstrapped, the project can be built with the usual sequence | ||
181 | of commands: | ||
13 | 182 | ||
14 | 1. Configure the package | 183 | 1. Configure the package |
15 | #+BEGIN_SRC shell-script | 184 | #+BEGIN_SRC shell-script |
16 | ./configure | 185 | ./configure |
17 | #+END_SRC | 186 | #+END_SRC |
18 | 2. Build the project. | 187 | 2. Build it |
19 | #+BEGIN_SRC shell-script | 188 | #+BEGIN_SRC shell-script |
20 | make | 189 | make |
21 | #+END_SRC | 190 | #+END_SRC |
22 | 3. Install the files (normally run as root). | 191 | 3. 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 | ||
33 | To incorporate *runcap* as a submodule to your project, follow these | 201 | To incorporate *runcap* to your project as a submodule, follow these |
34 | steps: | 202 | steps: |
35 | 203 | ||
36 | 1. Change to your project's toplevel directory. | 204 | 1. 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 |
52 | 5. Edit your *configure.ac* | 220 | 5. 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 |
56 | 6. | 224 | 6. 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 |