Blame SOURCES/0003-library-add-_adcli_call_external_program.patch

539d92
From 8abf673c508db9d8bbdaaa5bbee50dedd3a95faf Mon Sep 17 00:00:00 2001
539d92
From: Sumit Bose <sbose@redhat.com>
539d92
Date: Tue, 30 Jan 2018 14:39:17 +0100
539d92
Subject: [PATCH 3/9] library: add _adcli_call_external_program()
539d92
539d92
Allow adcli to call an external program given by an absolute path name
539d92
and an array of options. stdin and stdout can be used if needed.
539d92
539d92
https://bugs.freedesktop.org/show_bug.cgi?id=100118
539d92
539d92
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
539d92
---
539d92
 configure.ac        |  28 +++++++
539d92
 library/adprivate.h |   6 ++
539d92
 library/adutil.c    | 211 ++++++++++++++++++++++++++++++++++++++++++++++++++++
539d92
 3 files changed, 245 insertions(+)
539d92
539d92
diff --git a/configure.ac b/configure.ac
539d92
index 221d8ae..fe86638 100644
539d92
--- a/configure.ac
539d92
+++ b/configure.ac
539d92
@@ -263,6 +263,34 @@ AC_SUBST(LCOV)
539d92
 AC_SUBST(GCOV)
539d92
 AC_SUBST(GENHTML)
539d92
 
539d92
+AC_PATH_PROG(BIN_CAT, cat, no)
539d92
+if test "$BIN_CAT" = "no" ; then
539d92
+	AC_MSG_ERROR([cat is not available])
539d92
+else
539d92
+	AC_DEFINE_UNQUOTED(BIN_CAT, "$BIN_CAT", [path to cat, used in unit test])
539d92
+fi
539d92
+
539d92
+AC_PATH_PROG(BIN_TAC, tac, no)
539d92
+if test "$BIN_TAC" = "no" ; then
539d92
+	AC_MSG_ERROR([tac is not available])
539d92
+else
539d92
+	AC_DEFINE_UNQUOTED(BIN_TAC, "$BIN_TAC", [path to tac, used in unit test])
539d92
+fi
539d92
+
539d92
+AC_PATH_PROG(BIN_REV, rev, no)
539d92
+if test "$BIN_REV" = "no" ; then
539d92
+	AC_MSG_ERROR([rev is not available])
539d92
+else
539d92
+	AC_DEFINE_UNQUOTED(BIN_REV, "$BIN_REV", [path to rev, used in unit test])
539d92
+fi
539d92
+
539d92
+AC_PATH_PROG(BIN_ECHO, echo, no)
539d92
+if test "$BIN_ECHO" = "no" ; then
539d92
+	AC_MSG_ERROR([echo is not available])
539d92
+else
539d92
+	AC_DEFINE_UNQUOTED(BIN_ECHO, "$BIN_ECHO", [path to echo, used in unit test])
539d92
+fi
539d92
+
539d92
 # ---------------------------------------------------------------------
539d92
 
539d92
 ADCLI_LT_RELEASE=$ADCLI_CURRENT:$ADCLI_REVISION:$ADCLI_AGE
539d92
diff --git a/library/adprivate.h b/library/adprivate.h
539d92
index e99f9fc..7257c93 100644
539d92
--- a/library/adprivate.h
539d92
+++ b/library/adprivate.h
539d92
@@ -285,4 +285,10 @@ struct _adcli_attrs {
539d92
 
539d92
 bool             _adcli_check_nt_time_string_lifetime (const char *nt_time_string, unsigned int lifetime);
539d92
 
539d92
+adcli_result     _adcli_call_external_program     (const char *binary,
539d92
+                                                   char * const *argv,
539d92
+                                                   const char *stdin_data,
539d92
+                                                   uint8_t **stdout_data,
539d92
+                                                   size_t *stdout_data_len);
539d92
+
539d92
 #endif /* ADPRIVATE_H_ */
539d92
diff --git a/library/adutil.c b/library/adutil.c
539d92
index 829cdd9..a27bd68 100644
539d92
--- a/library/adutil.c
539d92
+++ b/library/adutil.c
539d92
@@ -36,6 +36,7 @@
539d92
 #include <unistd.h>
539d92
 #include <stdint.h>
539d92
 #include <time.h>
539d92
+#include <sys/wait.h>
539d92
 
539d92
 static adcli_message_func message_func = NULL;
539d92
 static char last_error[2048] = { 0, };
539d92
@@ -506,6 +507,161 @@ _adcli_check_nt_time_string_lifetime (const char *nt_time_string,
539d92
 	return false;
539d92
 }
539d92
 
539d92
+adcli_result
539d92
+_adcli_call_external_program (const char *binary, char * const *argv,
539d92
+                              const char *stdin_data,
539d92
+                              uint8_t **stdout_data, size_t *stdout_data_len)
539d92
+{
539d92
+	int ret;
539d92
+	int pipefd_to_child[2] = { -1, -1};
539d92
+	int pipefd_from_child[2] = { -1, -1};
539d92
+	pid_t child_pid = 0;
539d92
+	int err;
539d92
+	size_t len;
539d92
+	ssize_t rlen;
539d92
+	pid_t wret;
539d92
+	int status;
539d92
+	uint8_t read_buf[4096];
539d92
+	uint8_t *out;
539d92
+
539d92
+	errno = 0;
539d92
+	ret = access (binary, X_OK);
539d92
+	if (ret != 0) {
539d92
+		err = errno;
539d92
+		_adcli_err ("Cannot run [%s]: [%d][%s].", binary, err,
539d92
+		                                          strerror (err));
539d92
+		ret = ADCLI_ERR_FAIL;
539d92
+		goto done;
539d92
+	}
539d92
+
539d92
+	ret = pipe (pipefd_from_child);
539d92
+	if (ret == -1) {
539d92
+		err = errno;
539d92
+		_adcli_err ("pipe failed [%d][%s].", err, strerror (err));
539d92
+		ret = ADCLI_ERR_FAIL;
539d92
+		goto done;
539d92
+	}
539d92
+
539d92
+	ret = pipe (pipefd_to_child);
539d92
+	if (ret == -1) {
539d92
+		err = errno;
539d92
+		_adcli_err ("pipe failed [%d][%s].", err, strerror (err));
539d92
+		ret = ADCLI_ERR_FAIL;
539d92
+		goto done;
539d92
+	}
539d92
+
539d92
+	child_pid = fork ();
539d92
+
539d92
+	if (child_pid == 0) { /* child */
539d92
+		close (pipefd_to_child[1]);
539d92
+		ret = dup2 (pipefd_to_child[0], STDIN_FILENO);
539d92
+		if (ret == -1) {
539d92
+			err = errno;
539d92
+			_adcli_err ("dup2 failed [%d][%s].", err,
539d92
+			                                     strerror (err));
539d92
+			exit (EXIT_FAILURE);
539d92
+		}
539d92
+
539d92
+		close (pipefd_from_child[0]);
539d92
+		ret = dup2 (pipefd_from_child[1], STDOUT_FILENO);
539d92
+		if (ret == -1) {
539d92
+			err = errno;
539d92
+			_adcli_err ("dup2 failed [%d][%s].", err,
539d92
+			                                     strerror (err));
539d92
+			exit (EXIT_FAILURE);
539d92
+		}
539d92
+
539d92
+		execv (binary, argv);
539d92
+		_adcli_err ("Failed to run %s.", binary);
539d92
+		ret = ADCLI_ERR_FAIL;
539d92
+		goto done;
539d92
+	} else if (child_pid > 0) { /* parent */
539d92
+
539d92
+		if (stdin_data != NULL) {
539d92
+			len = strlen (stdin_data);
539d92
+			ret = write (pipefd_to_child[1], stdin_data, len);
539d92
+			if (ret != len) {
539d92
+				_adcli_err ("Failed to send computer account password "
539d92
+				            "to net command.");
539d92
+				ret = ADCLI_ERR_FAIL;
539d92
+				goto done;
539d92
+			}
539d92
+		}
539d92
+
539d92
+		close (pipefd_to_child[0]);
539d92
+		pipefd_to_child[0] = -1;
539d92
+		close (pipefd_to_child[1]);
539d92
+		pipefd_to_child[0] = -1;
539d92
+
539d92
+		if (stdout_data != NULL || stdout_data_len != NULL) {
539d92
+			rlen = read (pipefd_from_child[0], read_buf, sizeof (read_buf));
539d92
+			if (rlen < 0) {
539d92
+				ret = errno;
539d92
+				_adcli_err ("Failed to read from child [%d][%s].\n",
539d92
+				            ret, strerror (ret));
539d92
+				ret = ADCLI_ERR_FAIL;
539d92
+				goto done;
539d92
+			}
539d92
+
539d92
+			out = malloc (sizeof(uint8_t) * rlen);
539d92
+			if (out == NULL) {
539d92
+				_adcli_err ("Failed to allocate memory "
539d92
+				            "for child output.");
539d92
+				ret = ADCLI_ERR_FAIL;
539d92
+				goto done;
539d92
+			} else {
539d92
+				memcpy (out, read_buf, rlen);
539d92
+			}
539d92
+
539d92
+			if (stdout_data != NULL) {
539d92
+				*stdout_data = out;
539d92
+			} else {
539d92
+				free (out);
539d92
+			}
539d92
+
539d92
+			if (stdout_data_len != NULL) {
539d92
+				*stdout_data_len = rlen;
539d92
+			}
539d92
+		}
539d92
+
539d92
+	} else {
539d92
+		_adcli_err ("Cannot run net command.");
539d92
+		ret = ADCLI_ERR_FAIL;
539d92
+		goto done;
539d92
+	}
539d92
+
539d92
+	ret = ADCLI_SUCCESS;
539d92
+
539d92
+done:
539d92
+	if (pipefd_from_child[0] != -1) {
539d92
+		close (pipefd_from_child[0]);
539d92
+	}
539d92
+	if (pipefd_from_child[1] != -1) {
539d92
+		close (pipefd_from_child[1]);
539d92
+	}
539d92
+	if (pipefd_to_child[0] != -1) {
539d92
+		close (pipefd_to_child[0]);
539d92
+	}
539d92
+	if (pipefd_to_child[1] != -1) {
539d92
+		close (pipefd_to_child[1]);
539d92
+	}
539d92
+
539d92
+	if (child_pid > 0) {
539d92
+		wret = waitpid (child_pid, &status, 0);
539d92
+		if (wret == -1) {
539d92
+			_adcli_err ("No sure what happend to net command.");
539d92
+		} else {
539d92
+			if (WIFEXITED (status)) {
539d92
+				_adcli_err ("net command failed with %d.",
539d92
+				            WEXITSTATUS (status));
539d92
+			}
539d92
+		}
539d92
+	}
539d92
+
539d92
+	return ret;
539d92
+}
539d92
+
539d92
+
539d92
 #ifdef UTIL_TESTS
539d92
 
539d92
 #include "test.h"
539d92
@@ -620,6 +776,60 @@ test_bin_sid_to_str (void)
539d92
 	free (str);
539d92
 }
539d92
 
539d92
+static void
539d92
+test_call_external_program (void)
539d92
+{
539d92
+	adcli_result res;
539d92
+	char *argv[] = { NULL, NULL, NULL };
539d92
+	uint8_t *stdout_data;
539d92
+	size_t stdout_data_len;
539d92
+
539d92
+	argv[0] = "/does/not/exists";
539d92
+	res = _adcli_call_external_program (argv[0], argv, NULL, NULL, NULL);
539d92
+	assert (res == ADCLI_ERR_FAIL);
539d92
+
539d92
+#ifdef BIN_CAT
539d92
+	argv[0] = BIN_CAT;
539d92
+	res = _adcli_call_external_program (argv[0], argv, "Hello",
539d92
+	                                    &stdout_data, &stdout_data_len);
539d92
+	assert (res == ADCLI_SUCCESS);
539d92
+	assert (strncmp ("Hello", (char *) stdout_data, stdout_data_len) == 0);
539d92
+	free (stdout_data);
539d92
+
539d92
+	res = _adcli_call_external_program (argv[0], argv, "Hello",
539d92
+	                                    NULL, NULL);
539d92
+	assert (res == ADCLI_SUCCESS);
539d92
+#endif
539d92
+
539d92
+#ifdef BIN_REV
539d92
+	argv[0] = BIN_REV;
539d92
+	res = _adcli_call_external_program (argv[0], argv, "Hello\n",
539d92
+	                                    &stdout_data, &stdout_data_len);
539d92
+	assert (res == ADCLI_SUCCESS);
539d92
+	assert (strncmp ("olleH\n", (char *) stdout_data, stdout_data_len) == 0);
539d92
+	free (stdout_data);
539d92
+#endif
539d92
+
539d92
+#ifdef BIN_TAC
539d92
+	argv[0] = BIN_TAC;
539d92
+	res = _adcli_call_external_program (argv[0], argv, "Hello\nWorld\n",
539d92
+	                                    &stdout_data, &stdout_data_len);
539d92
+	assert (res == ADCLI_SUCCESS);
539d92
+	assert (strncmp ("World\nHello\n", (char *) stdout_data, stdout_data_len) == 0);
539d92
+	free (stdout_data);
539d92
+#endif
539d92
+
539d92
+#ifdef BIN_ECHO
539d92
+	argv[0] = BIN_ECHO;
539d92
+	argv[1] = "Hello";
539d92
+	res = _adcli_call_external_program (argv[0], argv, NULL,
539d92
+	                                    &stdout_data, &stdout_data_len);
539d92
+	assert (res == ADCLI_SUCCESS);
539d92
+	assert (strncmp ("Hello\n", (char *) stdout_data, stdout_data_len) == 0);
539d92
+	free (stdout_data);
539d92
+#endif
539d92
+}
539d92
+
539d92
 int
539d92
 main (int argc,
539d92
       char *argv[])
539d92
@@ -629,6 +839,7 @@ main (int argc,
539d92
 	test_func (test_strv_count, "/util/strv_count");
539d92
 	test_func (test_check_nt_time_string_lifetime, "/util/check_nt_time_string_lifetime");
539d92
 	test_func (test_bin_sid_to_str, "/util/bin_sid_to_str");
539d92
+	test_func (test_call_external_program, "/util/call_external_program");
539d92
 	return test_run (argc, argv);
539d92
 }
539d92
 
539d92
-- 
539d92
2.14.4
539d92