File 0008-library-add-_adcli_call_external_program.patch of Package adcli (Revision ce46d0e7322eb68daa00b5c190e5847d)
Currently displaying revision ce46d0e7322eb68daa00b5c190e5847d , Show latest
xxxxxxxxxx
1
From e70607d0842e27b5e3c71ab52345886ab0ddc838 Mon Sep 17 00:00:00 2001
2
From: Sumit Bose <sbose@redhat.com>
3
Date: Tue, 30 Jan 2018 14:39:17 +0100
4
Subject: [PATCH 08/25] library: add _adcli_call_external_program()
5
6
Allow adcli to call an external program given by an absolute path name
7
and an array of options. stdin and stdout can be used if needed.
8
9
https://bugs.freedesktop.org/show_bug.cgi?id=100118
10
https://gitlab.freedesktop.org/realmd/adcli/issues/6
11
12
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
13
---
14
configure.ac | 28 +++++++
15
library/adprivate.h | 6 ++
16
library/adutil.c | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++
17
3 files changed, 245 insertions(+)
18
19
diff --git a/configure.ac b/configure.ac
20
index 221d8ae..fe86638 100644
21
--- a/configure.ac
22
+++ b/configure.ac
23
24
AC_SUBST(GCOV)
25
AC_SUBST(GENHTML)
26
27
+AC_PATH_PROG(BIN_CAT, cat, no)
28
+if test "$BIN_CAT" = "no" ; then
29
+ AC_MSG_ERROR([cat is not available])
30
+else
31
+ AC_DEFINE_UNQUOTED(BIN_CAT, "$BIN_CAT", [path to cat, used in unit test])
32
+fi
33
+
34
+AC_PATH_PROG(BIN_TAC, tac, no)
35
+if test "$BIN_TAC" = "no" ; then
36
+ AC_MSG_ERROR([tac is not available])
37
+else
38
+ AC_DEFINE_UNQUOTED(BIN_TAC, "$BIN_TAC", [path to tac, used in unit test])
39
+fi
40
+
41
+AC_PATH_PROG(BIN_REV, rev, no)
42
+if test "$BIN_REV" = "no" ; then
43
+ AC_MSG_ERROR([rev is not available])
44
+else
45
+ AC_DEFINE_UNQUOTED(BIN_REV, "$BIN_REV", [path to rev, used in unit test])
46
+fi
47
+
48
+AC_PATH_PROG(BIN_ECHO, echo, no)
49
+if test "$BIN_ECHO" = "no" ; then
50
+ AC_MSG_ERROR([echo is not available])
51
+else
52
+ AC_DEFINE_UNQUOTED(BIN_ECHO, "$BIN_ECHO", [path to echo, used in unit test])
53
+fi
54
+
55
# ---------------------------------------------------------------------
56
57
ADCLI_LT_RELEASE=$ADCLI_CURRENT:$ADCLI_REVISION:$ADCLI_AGE
58
diff --git a/library/adprivate.h b/library/adprivate.h
59
index e99f9fc..7257c93 100644
60
--- a/library/adprivate.h
61
+++ b/library/adprivate.h
62
63
64
bool _adcli_check_nt_time_string_lifetime (const char *nt_time_string, unsigned int lifetime);
65
66
+adcli_result _adcli_call_external_program (const char *binary,
67
+ char * const *argv,
68
+ const char *stdin_data,
69
+ uint8_t **stdout_data,
70
+ size_t *stdout_data_len);
71
+
72
#endif /* ADPRIVATE_H_ */
73
diff --git a/library/adutil.c b/library/adutil.c
74
index a057763..14df42e 100644
75
--- a/library/adutil.c
76
+++ b/library/adutil.c
77
78
#include <unistd.h>
79
#include <stdint.h>
80
#include <time.h>
81
+#include <sys/wait.h>
82
83
static adcli_message_func message_func = NULL;
84
static char last_error[2048] = { 0, };
85
86
return false;
87
}
88
89
+adcli_result
90
+_adcli_call_external_program (const char *binary, char * const *argv,
91
+ const char *stdin_data,
92
+ uint8_t **stdout_data, size_t *stdout_data_len)
93
+{
94
+ int ret;
95
+ int pipefd_to_child[2] = { -1, -1};
96
+ int pipefd_from_child[2] = { -1, -1};
97
+ pid_t child_pid = 0;
98
+ int err;
99
+ size_t len;
100
+ ssize_t rlen;
101
+ pid_t wret;
102
+ int status;
103
+ uint8_t read_buf[4096];
104
+ uint8_t *out;
105
+
106
+ errno = 0;
107
+ ret = access (binary, X_OK);
108
+ if (ret != 0) {
109
+ err = errno;
110
+ _adcli_err ("Cannot run [%s]: [%d][%s].", binary, err,
111
+ strerror (err));
112
+ ret = ADCLI_ERR_FAIL;
113
+ goto done;
114
+ }
115
+
116
+ ret = pipe (pipefd_from_child);
117
+ if (ret == -1) {
118
+ err = errno;
119
+ _adcli_err ("pipe failed [%d][%s].", err, strerror (err));
120
+ ret = ADCLI_ERR_FAIL;
121
+ goto done;
122
+ }
123
+
124
+ ret = pipe (pipefd_to_child);
125
+ if (ret == -1) {
126
+ err = errno;
127
+ _adcli_err ("pipe failed [%d][%s].", err, strerror (err));
128
+ ret = ADCLI_ERR_FAIL;
129
+ goto done;
130
+ }
131
+
132
+ child_pid = fork ();
133
+
134
+ if (child_pid == 0) { /* child */
135
+ close (pipefd_to_child[1]);
136
+ ret = dup2 (pipefd_to_child[0], STDIN_FILENO);
137
+ if (ret == -1) {
138
+ err = errno;
139
+ _adcli_err ("dup2 failed [%d][%s].", err,
140
+ strerror (err));
141
+ exit (EXIT_FAILURE);
142
+ }
143
+
144
+ close (pipefd_from_child[0]);
145
+ ret = dup2 (pipefd_from_child[1], STDOUT_FILENO);
146
+ if (ret == -1) {
147
+ err = errno;
148
+ _adcli_err ("dup2 failed [%d][%s].", err,
149
+ strerror (err));
150
+ exit (EXIT_FAILURE);
151
+ }
152
+
153
+ execv (binary, argv);
154
+ _adcli_err ("Failed to run %s.", binary);
155
+ ret = ADCLI_ERR_FAIL;
156
+ goto done;
157
+ } else if (child_pid > 0) { /* parent */
158
+
159
+ if (stdin_data != NULL) {
160
+ len = strlen (stdin_data);
161
+ ret = write (pipefd_to_child[1], stdin_data, len);
162
+ if (ret != len) {
163
+ _adcli_err ("Failed to send computer account password "
164
+ "to net command.");
165
+ ret = ADCLI_ERR_FAIL;
166
+ goto done;
167
+ }
168
+ }
169
+
170
+ close (pipefd_to_child[0]);
171
+ pipefd_to_child[0] = -1;
172
+ close (pipefd_to_child[1]);
173
+ pipefd_to_child[0] = -1;
174
+
175
+ if (stdout_data != NULL || stdout_data_len != NULL) {
176
+ rlen = read (pipefd_from_child[0], read_buf, sizeof (read_buf));
177
+ if (rlen < 0) {
178
+ ret = errno;
179
+ _adcli_err ("Failed to read from child [%d][%s].\n",
180
+ ret, strerror (ret));
181
+ ret = ADCLI_ERR_FAIL;
182
+ goto done;
183
+ }
184
+
185
+ out = malloc (sizeof(uint8_t) * rlen);
186
+ if (out == NULL) {
187
+ _adcli_err ("Failed to allocate memory "
188
+ "for child output.");
189
+ ret = ADCLI_ERR_FAIL;
190
+ goto done;
191
+ } else {
192
+ memcpy (out, read_buf, rlen);
193
+ }
194
+
195
+ if (stdout_data != NULL) {
196
+ *stdout_data = out;
197
+ } else {
198
+ free (out);
199
+ }
200
+
201
+ if (stdout_data_len != NULL) {
202
+ *stdout_data_len = rlen;
203
+ }
204
+ }
205
+
206
+ } else {
207
+ _adcli_err ("Cannot run net command.");
208
+ ret = ADCLI_ERR_FAIL;
209
+ goto done;
210
+ }
211
+
212
+ ret = ADCLI_SUCCESS;
213
+
214
+done:
215
+ if (pipefd_from_child[0] != -1) {
216
+ close (pipefd_from_child[0]);
217
+ }
218
+ if (pipefd_from_child[1] != -1) {
219
+ close (pipefd_from_child[1]);
220
+ }
221
+ if (pipefd_to_child[0] != -1) {
222
+ close (pipefd_to_child[0]);
223
+ }
224
+ if (pipefd_to_child[1] != -1) {
225
+ close (pipefd_to_child[1]);
226
+ }
227
+
228
+ if (child_pid > 0) {
229
+ wret = waitpid (child_pid, &status, 0);
230
+ if (wret == -1) {
231
+ _adcli_err ("No sure what happend to net command.");
232
+ } else {
233
+ if (WIFEXITED (status)) {
234
+ _adcli_err ("net command failed with %d.",
235
+ WEXITSTATUS (status));
236
+ }
237
+ }
238
+ }
239
+
240
+ return ret;
241
+}
242
+
243
+
244
#ifdef UTIL_TESTS
245
246
#include "test.h"
247
248
free (str);
249
}
250
251
+static void
252
+test_call_external_program (void)
253
+{
254
+ adcli_result res;
255
+ char *argv[] = { NULL, NULL, NULL };
256
+ uint8_t *stdout_data;
257
+ size_t stdout_data_len;
258
+
259
+ argv[0] = "/does/not/exists";
260
+ res = _adcli_call_external_program (argv[0], argv, NULL, NULL, NULL);
261
+ assert (res == ADCLI_ERR_FAIL);
262
+
263
+#ifdef BIN_CAT
264
+ argv[0] = BIN_CAT;
265
+ res = _adcli_call_external_program (argv[0], argv, "Hello",
266
+ &stdout_data, &stdout_data_len);
267
+ assert (res == ADCLI_SUCCESS);
268
+ assert (strncmp ("Hello", (char *) stdout_data, stdout_data_len) == 0);
269
+ free (stdout_data);
270
+
271
+ res = _adcli_call_external_program (argv[0], argv, "Hello",
272
+ NULL, NULL);
273
+ assert (res == ADCLI_SUCCESS);
274
+#endif
275
+
276
+#ifdef BIN_REV
277
+ argv[0] = BIN_REV;
278
+ res = _adcli_call_external_program (argv[0], argv, "Hello\n",
279
+ &stdout_data, &stdout_data_len);
280
+ assert (res == ADCLI_SUCCESS);
281
+ assert (strncmp ("olleH\n", (char *) stdout_data, stdout_data_len) == 0);
282
+ free (stdout_data);
283
+#endif
284
+
285
+#ifdef BIN_TAC
286
+ argv[0] = BIN_TAC;
287
+ res = _adcli_call_external_program (argv[0], argv, "Hello\nWorld\n",
288
+ &stdout_data, &stdout_data_len);
289
+ assert (res == ADCLI_SUCCESS);
290
+ assert (strncmp ("World\nHello\n", (char *) stdout_data, stdout_data_len) == 0);
291
+ free (stdout_data);
292
+#endif
293
+
294
+#ifdef BIN_ECHO
295
+ argv[0] = BIN_ECHO;
296
+ argv[1] = "Hello";
297
+ res = _adcli_call_external_program (argv[0], argv, NULL,
298
+ &stdout_data, &stdout_data_len);
299
+ assert (res == ADCLI_SUCCESS);
300
+ assert (strncmp ("Hello\n", (char *) stdout_data, stdout_data_len) == 0);
301
+ free (stdout_data);
302
+#endif
303
+}
304
+
305
int
306
main (int argc,
307
char *argv[])
308
309
test_func (test_strv_count, "/util/strv_count");
310
test_func (test_check_nt_time_string_lifetime, "/util/check_nt_time_string_lifetime");
311
test_func (test_bin_sid_to_str, "/util/bin_sid_to_str");
312
+ test_func (test_call_external_program, "/util/call_external_program");
313
return test_run (argc, argv);
314
}
315
316
--
317
2.16.4
318
319