summaryrefslogtreecommitdiff
path: root/ctdb
diff options
context:
space:
mode:
authorAmitay Isaacs <amitay@gmail.com>2017-05-06 02:47:00 +1000
committerMartin Schwenke <martins@samba.org>2017-05-30 03:58:06 +0200
commit16c188c7f8e335e5c8c191148be2f8347020178a (patch)
tree33782cc590a919294147e741629d4ae26249a73b /ctdb
parent15367ce4b413b6d7c42b6e0a3eac1f42eeedc564 (diff)
downloadsamba-16c188c7f8e335e5c8c191148be2f8347020178a.tar.gz
ctdb-common: Update run_proc api to re-assign stdin
This allows to pass data to a child process via stdin. Signed-off-by: Amitay Isaacs <amitay@gmail.com> Reviewed-by: Martin Schwenke <martin@meltin.net>
Diffstat (limited to 'ctdb')
-rw-r--r--ctdb/common/run_proc.c13
-rw-r--r--ctdb/common/run_proc.h3
-rw-r--r--ctdb/server/ctdb_eventd.c4
-rwxr-xr-xctdb/tests/cunit/run_proc_001.sh38
-rw-r--r--ctdb/tests/src/run_proc_test.c14
5 files changed, 52 insertions, 20 deletions
diff --git a/ctdb/common/run_proc.c b/ctdb/common/run_proc.c
index f9fee80e907..53862026bd5 100644
--- a/ctdb/common/run_proc.c
+++ b/ctdb/common/run_proc.c
@@ -67,7 +67,7 @@ static void proc_read_handler(struct tevent_context *ev,
void *private_data);
static int proc_start(struct proc_context *proc, struct tevent_context *ev,
- const char *path, const char **argv)
+ const char *path, const char **argv, int stdin_fd)
{
int fd[2];
int ret;
@@ -99,6 +99,13 @@ static int proc_start(struct proc_context *proc, struct tevent_context *ev,
close(fd[1]);
+ if (stdin_fd != -1) {
+ ret = dup2(stdin_fd, STDIN_FILENO);
+ if (ret == -1) {
+ exit(64 + errno);
+ }
+ }
+
ret = setpgid(0, 0);
if (ret != 0) {
exit(64 + errno);
@@ -382,7 +389,7 @@ struct tevent_req *run_proc_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct run_proc_context *run_ctx,
const char *path, const char **argv,
- struct timeval timeout)
+ int stdin_fd, struct timeval timeout)
{
struct tevent_req *req;
struct run_proc_state *state;
@@ -415,7 +422,7 @@ struct tevent_req *run_proc_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
- ret = proc_start(state->proc, ev, path, argv);
+ ret = proc_start(state->proc, ev, path, argv, stdin_fd);
if (ret != 0) {
tevent_req_error(req, ret);
return tevent_req_post(req, ev);
diff --git a/ctdb/common/run_proc.h b/ctdb/common/run_proc.h
index 4287347cc64..7de0c84f857 100644
--- a/ctdb/common/run_proc.h
+++ b/ctdb/common/run_proc.h
@@ -68,6 +68,7 @@ int run_proc_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
* @param[in] run_ctx Run_proc context
* @param[in] prog The path to the executable
* @param[in] argv Arguments to the executable
+ * @param[in] stdin_fd Assign stdin_fd as stdin for the process, -1 if not
* @param[in] timeout How long to wait for execution
* @return new tevent request, or NULL on failure
*
@@ -77,7 +78,7 @@ struct tevent_req *run_proc_send(TALLOC_CTX *mem_ctx,
struct tevent_context *ev,
struct run_proc_context *run_ctx,
const char *prog, const char **argv,
- struct timeval timeout);
+ int stdin_fd, struct timeval timeout);
/**
* @brief Async computation end to run an executable
diff --git a/ctdb/server/ctdb_eventd.c b/ctdb/server/ctdb_eventd.c
index 232711ce4e2..3542b4fb6f0 100644
--- a/ctdb/server/ctdb_eventd.c
+++ b/ctdb/server/ctdb_eventd.c
@@ -343,7 +343,7 @@ static struct tevent_req *run_debug_send(TALLOC_CTX *mem_ctx,
debug_script, argv[1], argv[2]);
subreq = run_proc_send(state, ev, ectx->run_ctx, debug_script, argv,
- tevent_timeval_zero());
+ -1, tevent_timeval_zero());
if (tevent_req_nomem(subreq, req)) {
return tevent_req_post(req, ev);
}
@@ -709,7 +709,7 @@ static struct tevent_req *run_event_run_script(struct tevent_req *req)
path, state->argv[0], state->argv[1]);
subreq = run_proc_send(state, state->ev, state->ectx->run_ctx,
- path, state->argv, state->timeout);
+ path, state->argv, -1, state->timeout);
talloc_free(path);
diff --git a/ctdb/tests/cunit/run_proc_001.sh b/ctdb/tests/cunit/run_proc_001.sh
index e1937a82f28..b817637e574 100755
--- a/ctdb/tests/cunit/run_proc_001.sh
+++ b/ctdb/tests/cunit/run_proc_001.sh
@@ -6,7 +6,7 @@
ok <<EOF
Process exited with error 2
EOF
-unit_test run_proc_test 0 /a/b/c
+unit_test run_proc_test 0 -1 /a/b/c
# Non-executable path
prog=$(mktemp --tmpdir="$TEST_VAR_DIR")
@@ -17,7 +17,7 @@ EOF
ok <<EOF
Process exited with error 13
EOF
-unit_test run_proc_test 0 "$prog"
+unit_test run_proc_test 0 -1 "$prog"
# Executable path
chmod +x "$prog"
@@ -25,7 +25,7 @@ chmod +x "$prog"
ok <<EOF
Process exited with error 8
EOF
-unit_test run_proc_test 0 "$prog"
+unit_test run_proc_test 0 -1 "$prog"
# Capture output
cat > "$prog" <<EOF
@@ -38,7 +38,7 @@ Process exited with status 0
Output = (hello
)
EOF
-unit_test run_proc_test 0 "$prog"
+unit_test run_proc_test 0 -1 "$prog"
# Specify timeout
ok <<EOF
@@ -46,7 +46,7 @@ Process exited with status 0
Output = (hello
)
EOF
-unit_test run_proc_test 5 "$prog"
+unit_test run_proc_test 5 -1 "$prog"
# Redirected output
output=$(mktemp --tmpdir="$TEST_VAR_DIR")
@@ -59,7 +59,7 @@ EOF
ok <<EOF
Process exited with status 0
EOF
-unit_test run_proc_test 0 "$prog"
+unit_test run_proc_test 0 -1 "$prog"
ok <<EOF
hello
@@ -75,7 +75,7 @@ EOF
ok <<EOF
Process exited with status 1
EOF
-unit_test run_proc_test 0 "$prog"
+unit_test run_proc_test 0 -1 "$prog"
# Exit with signal
cat > "$prog" <<EOF
@@ -86,7 +86,7 @@ EOF
ok <<EOF
Process exited with signal 15
EOF
-unit_test run_proc_test 0 "$prog"
+unit_test run_proc_test 0 -1 "$prog"
# Exit with timeout
cat > "$prog" <<EOF
@@ -107,7 +107,7 @@ Child = PID
Output = (Sleeping for 5 seconds
)
EOF
-unit_test run_proc_test 1 "$prog"
+unit_test run_proc_test 1 -1 "$prog"
# No zombie processes
pidfile=$(mktemp --tmpdir="$TEST_VAR_DIR")
@@ -122,7 +122,7 @@ ok <<EOF
Process exited with error 62
Child = PID
EOF
-unit_test run_proc_test 1 "$prog"
+unit_test run_proc_test 1 -1 "$prog"
result_filter ()
{
@@ -136,5 +136,23 @@ HEADER
EOF
unit_test ps -p "$pid"
+# Redirect stdin
+cat > "$prog" <<EOF
+#!/bin/sh
+cat -
+EOF
+
+cat > "$output" <<EOF
+this is sample input
+EOF
+
+ok <<EOF
+Process exited with status 0
+Output = (this is sample input
+)
+EOF
+(unit_test run_proc_test 0 4 "$prog") 4<"$output"
+
rm -f "$pidfile"
+rm -f "$output"
rm -f "$prog"
diff --git a/ctdb/tests/src/run_proc_test.c b/ctdb/tests/src/run_proc_test.c
index 6db783d378f..7cfb8703e99 100644
--- a/ctdb/tests/src/run_proc_test.c
+++ b/ctdb/tests/src/run_proc_test.c
@@ -35,11 +35,12 @@ int main(int argc, const char **argv)
char *output;
struct run_proc_result result;
pid_t pid;
- int timeout, ret;
+ int timeout, ret, fd;
bool status;
- if (argc < 3) {
- fprintf(stderr, "Usage: %s <timeout> <program> <args>\n",
+ if (argc < 4) {
+ fprintf(stderr,
+ "Usage: %s <timeout> <stdin-fd> <program> <args>\n",
argv[0]);
exit(1);
}
@@ -63,13 +64,18 @@ int main(int argc, const char **argv)
tv = tevent_timeval_current_ofs(timeout, 0);
}
+ fd = atoi(argv[2]);
+ if (fd < 0) {
+ fd = -1;
+ }
+
ret = run_proc_init(mem_ctx, ev, &run_ctx);
if (ret != 0) {
fprintf(stderr, "run_proc_init() failed, ret=%d\n", ret);
exit(1);
}
- req = run_proc_send(mem_ctx, ev, run_ctx, argv[2], &argv[2], tv);
+ req = run_proc_send(mem_ctx, ev, run_ctx, argv[3], &argv[3], fd, tv);
if (req == NULL) {
fprintf(stderr, "run_proc_send() failed\n");
exit(1);