/* 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; /* TOOD should `fds[0]` be closed from `left`, and `fds[1]` close from `right` * (isn't this a problem in general with 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