#include #include #include #include #include #include #define PIPE_WRITE 1 #define PIPE_READ 0 #define BP_IGNORE(v) if (v) {} //Required to workarround GCC bug void CleanupHandles(int fdStdOut[2], int fdStdErr[2], int fdStdIn[2], int commonfd[2]) { for (int i = 0; i != 2; ++i) { if (fdStdOut[i] != -1) close(fdStdOut[i]); } for (int i = 0; i != 2; ++i) { if (fdStdErr[i] != -1) close(fdStdErr[i]); } for (int i = 0; i != 2; ++i) { if (fdStdIn[i] != -1) close(fdStdIn[i]); } for (int i = 0; i != 2; ++i) { if (commonfd[i] != -1) close(commonfd[i]); } } void ProcessWorker(int fdStdOut[2], int fdStdErr[2], int fdStdIn[2], int commonfd[2]) { char *argv[] = {NULL}; char *envp[] = {NULL}; for (int fd = 0; fd != 256; ++fd) { if (fd != 0 && fd != 1 && fd != 2 && fd != fdStdOut[PIPE_WRITE] && fd != fdStdErr[PIPE_WRITE] && fd != fdStdIn[PIPE_READ] && fd != commonfd[PIPE_WRITE]) close(fd); } if (fcntl(commonfd[PIPE_WRITE], FD_CLOEXEC, 1) != 0) { BP_IGNORE(write(commonfd[PIPE_WRITE], "fcntl failure", 14)); close(commonfd[PIPE_WRITE]); exit(1); } if (dup2(fdStdOut[PIPE_WRITE], 1) == -1) goto redirecterr; if (dup2(fdStdErr[PIPE_WRITE], 2) == -1) goto redirecterr; if (dup2(fdStdIn[PIPE_READ], 0) == -1) goto redirecterr; #ifdef CLOSE_BEFORE_EXEC close(commonfd[PIPE_WRITE]); #endif if (execve("/usr/bin/cat", argv, envp) == -1) { #ifndef CLOSE_BEFORE_EXEC BP_IGNORE(write(commonfd[PIPE_WRITE], "execve failure", 15)); close(commonfd[PIPE_WRITE]); #endif exit(1); } redirecterr: BP_IGNORE(write(commonfd[PIPE_WRITE], "Could not create one or more redirection(s)", 44)); close(commonfd[PIPE_WRITE]); exit(1); } void ProcessMaster(int pid, int fdStdOut[2], int fdStdErr[2], int fdStdIn[2], int commonfd[2]) { if (commonfd[PIPE_WRITE] != -1) close(commonfd[PIPE_WRITE]); if (fdStdOut[PIPE_WRITE] != -1) close(fdStdOut[PIPE_WRITE]); if (fdStdErr[PIPE_WRITE] != -1) close(fdStdErr[PIPE_WRITE]); if (fdStdIn[PIPE_READ] != -1) close(fdStdIn[PIPE_READ]); char buf[4096]; int len = read(commonfd[PIPE_READ], buf, 4096); if (len > 0) { close(commonfd[PIPE_READ]); return; //We have got a system error } close(commonfd[PIPE_READ]); } int main() { int fdStdOut[2] = {-1, -1}; int fdStdIn[2] = {-1, -1}; int fdStdErr[2] = {-1, -1}; int commonfd[2]; if (pipe(commonfd) != 0) return (1); if (pipe(fdStdOut) != 0) { CleanupHandles(fdStdOut, fdStdErr, fdStdIn, commonfd); return (2); } if (pipe(fdStdErr) != 0) { CleanupHandles(fdStdOut, fdStdErr, fdStdIn, commonfd); return (3); } if (pipe(fdStdIn) != 0) { CleanupHandles(fdStdOut, fdStdErr, fdStdIn, commonfd); return (4); } int pid = fork(); if (pid == -1) { CleanupHandles(fdStdOut, fdStdErr, fdStdIn, commonfd); return (5); } if (pid == 0) { // Worker/Child ProcessWorker(fdStdOut, fdStdErr, fdStdIn, commonfd); return (0); // This will never trigger } else // Master { int status; char buf[128]; ProcessMaster(pid, fdStdOut, fdStdErr, fdStdIn, commonfd); write(fdStdIn[PIPE_WRITE], "test\n", 5); close(fdStdIn[PIPE_WRITE]); waitpid(pid, &status, 0); printf("Status %d\n", WEXITSTATUS(status)); int res = read(fdStdOut[PIPE_READ], buf, 128); buf[res] = 0; printf("Output = %s", buf); return (0); } }