acl_action_type_t pipe_action(milter_stage_t stage, char *stagename, var_t *mailspec, void *data, int depth) { exp_t *exp = data; var_t *v; char *dest; char *message; int size; acl_action_type_t a; v = exp_eval(exp, mailspec); if (v == NULL) { log_error("pipe_exec: exp_eval failed"); return ACL_ERROR; } if (v->v_type != VT_STRING) { log_error("pipe_exec: bad expression in mail.acl"); return ACL_ERROR; } dest = v->v_data; log_message(LOG_ERR, mailspec, "pipe_exec: %s", dest); size = milter_message(mailspec, &message); if (size == -1) { log_error("pipe_exec: milter_message failed"); return ACL_ERROR; } if (strncmp(dest, "inet:", 5) == 0 || strncmp(dest, "unix:", 5) == 0) { a = pipe_socket(dest, message, size); } else { a = pipe_exec(dest, message, size); } free(message); return a; }
void pipes_loop(t_pipe pi, t_env *e, long tot) { int p[2]; pid_t pid; char *cat[3]; if (*(pi.table + tot + pi.redir) && **(pi.table + tot + pi.redir) == '|') { if (pipe(p) == -1) return (pipe_error("pipe() failed.", -1, e)); if ((pid = fork()) < 0) return (pipe_error("fork() failed.", -1, e)); if (pid == 0) { if (pi.pipe) { dup2(pi.pipe, STDIN_FILENO); close(pi.pipe); pi.pipe = 0; } close(p[0]); dup2(p[1], STDOUT_FILENO); close(p[1]); pipe_exec(*(pi.cmd + tot), e, 0); } else { close(p[1]); waitpid(pid, &e->ret, 0); if (e->ret) return (pipe_error(NULL, p[0], e)); tot += pi.redir + 1; pi.redir = 0; if (*(pi.table + tot + pi.redir)) { pi.pipe = p[0]; pipes_loop(pi, e, tot); close(p[0]); } else { dup2(p[0], STDIN_FILENO); close(p[0]); pipe_exec(*(pi.cmd + tot + pi.redir), e, 1); dup2(1, STDIN_FILENO); } tot += pi.redir + 1; pi.redir = 0; } } else if (*(pi.table + tot + pi.redir) && **(pi.table + tot + pi.redir) == '<') { if (pipe(p) == -1) return (pipe_error("pipe() failed.", -1, e)); if ((pid = fork()) < 0) return (pipe_error("fork() failed.", -1, e)); if (pid == 0) { if (pi.pipe) { dup2(pi.pipe, STDIN_FILENO); close(pi.pipe); pi.pipe = 0; } close(p[0]); if (**(pi.cmd + tot + pi.redir)) dup2(p[1], STDOUT_FILENO); close(p[1]); int i = 0; while (*(pi.table + tot + i) && **(pi.table + tot + i) == '<') i++; char *more[i + 1]; int j = 0; more[j] = "cat"; while (*(pi.table + tot + j) && **(pi.table + tot + j) == '<') { more[j + 1] = **(pi.cmd + tot + j + 1); j++; } more[j + 1] = NULL; pipe_exec(more, e, 0); } else { close(p[1]); waitpid(pid, &e->ret, 0); if (e->ret) return (pipe_error(NULL, p[0], e)); while (*(pi.table + tot + pi.redir) && **(pi.table + tot + pi.redir) == '<') pi.redir++; if (*(pi.table + tot + pi.redir)) { pi.pipe = p[0]; pipes_loop(pi, e, tot); close(p[0]); } else { dup2(p[0], STDIN_FILENO); close(p[0]); if (**(pi.cmd + tot)) pipe_exec(*(pi.cmd + tot), e, 1); dup2(1, STDIN_FILENO); } } } else if (*(pi.table + tot + pi.redir) && **(pi.table + tot + pi.redir) == '>') { if ((pid = fork()) < 0) return (pipe_error("fork() failed.", -1, e)); if (pid == 0) { if (pi.pipe) { dup2(pi.pipe, STDIN_FILENO); close(pi.pipe); pi.pipe = 0; } pi.redir++; dup2(*(pi.fds + tot + pi.redir), STDOUT_FILENO); close(*(pi.fds + tot + pi.redir)); if (tot + pi.redir - 2 >= 0 && **(pi.table + tot + pi.redir - 2) == '>') { cat[0] = "cat"; cat[1] = **(pi.cmd + tot + pi.redir - 1); pipe_exec(cat, e, 0); } else if (**(pi.cmd + tot)) pipe_exec(*(pi.cmd + tot), e, 0); else { cat[0] = "cat"; pipe_exec(cat, e, 0); } } else { waitpid(pid, &e->ret, 0); if (e->ret) return (pipe_error(NULL, p[0], e)); pi.redir++; if (*(pi.table + tot + pi.redir)) { pi.pipe = *(pi.fds + tot + pi.redir); pipes_loop(pi, e, tot); } } } }