aboutsummaryrefslogtreecommitdiffstats
path: root/libexec_pipe_commandsvn.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libexec_pipe_commandsvn.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/libexec_pipe_commandsvn.c b/libexec_pipe_commandsvn.c
new file mode 100644
index 0000000..d6aa1d5
--- /dev/null
+++ b/libexec_pipe_commandsvn.c
@@ -0,0 +1,106 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+#ifndef TEST
+
+
+static void
+remove_last_pluming(struct libexec_command *cmd)
+{
+ if (!cmd->nplumings || !cmd->plumings)
+ abort();
+ if (cmd->plumings[--cmd->nplumings].type != LIBEXEC_PLUMING_PIPE)
+ abort();
+ close(cmd->plumings[cmd->nplumings].target.fd);
+ if (!cmd->nplumings) {
+ free(cmd->plumings);
+ cmd->plumings = NULL;
+ }
+}
+
+
+static int
+pipe_two_commands(enum libexec_pipe how, struct libexec_command *left, struct libexec_command *right)
+{
+ int fds[2], r;
+ struct libexec_pluming tmp;
+
+ if (!left || !right) {
+ einval:
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (how == LIBEXEC_PIPE)
+ r = pipe(fds);
+ else if (how == LIBEXEC_SOCK_STREAM)
+ r = socketpair(PF_UNIX, SOCK_STREAM, 0, fds);
+ else if (how == LIBEXEC_SOCK_SEQPACKET)
+ r = socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds);
+ else if (how == LIBEXEC_SOCK_DGRAM)
+ r = socketpair(PF_UNIX, SOCK_DGRAM, 0, fds);
+ else if (how == LIBEXEC_DIRECT_PIPE)
+ r = pipe2(fds, O_DIRECT);
+ else
+ goto einval;
+ if (r)
+ return -1;
+
+ if (libexec_dup(left, STDOUT_FILENO, fds[1])) {
+ close(fds[0]);
+ close(fds[1]);
+ return -1;
+ }
+ left->plumings[left->nplumings - 1].type = LIBEXEC_PLUMING_PIPE;
+
+ if (libexec_dup(right, STDIN_FILENO, fds[0])) {
+ remove_last_pluming(left);
+ close(fds[0]);
+ return -1;
+ }
+ right->plumings[right->nplumings - 1].type = LIBEXEC_PLUMING_PIPE;
+
+ /* pluming shall be at the front */
+ tmp = left->plumings[left->nplumings - 1];
+ memcpy(&left->plumings[1], &left->plumings[0], (left->nplumings - 1) * sizeof(*left->plumings));
+ left->plumings[0] = tmp;
+ tmp = right->plumings[right->nplumings - 1];
+ memcpy(&right->plumings[1], &right->plumings[0], (right->nplumings - 1) * sizeof(*right->plumings));
+ right->plumings[0] = tmp;
+
+ return 0;
+}
+
+
+int
+libexec_pipe_commandsvn(enum libexec_pipe how, struct libexec_command *const *cmds, size_t n)
+{
+ enum libexec_pipe circular;
+ size_t i;
+
+ circular = how;
+ circular &= LIBEXEC_PIPE_CIRCULARLY;
+ how ^= circular;
+
+ for (i = 1; i < n; i++)
+ if (pipe_two_commands(how, cmds[i - 1], cmds[i]))
+ goto fail;
+
+ if (circular && n)
+ if (pipe_two_commands(how, cmds[n - 1], cmds[0]))
+ goto fail;
+
+ return 0;
+
+fail:
+ i -= 1;
+ while (i) {
+ remove_last_pluming(cmds[i--]);
+ remove_last_pluming(cmds[i]);
+ }
+ return -1;
+}
+
+
+#else
+LIBEXEC_CONST__ int main(void) {return 0;} /* TODO test */
+#endif