#include #include #include #include void checked_close(int fd) { if (close(fd) == -1) { perror("close"); exit(1); } } void checked_pipe(int filedes[2]) { if (pipe(filedes) == -1) { perror("filedes"); exit(1); } } int checked_dup2(int oldfd, int newfd) { int ret; if ((ret = dup2(oldfd, newfd)) == -1) { perror("dup2"); exit(1); } return ret; } int main() { int c2p[2]; int errpipe[2]; pid_t pid; char errpipe_buf[16]; char buf[16394]; ssize_t errpipe_count; size_t count; FILE *output; checked_pipe(c2p); checked_pipe(errpipe); fcntl(errpipe[1], F_SETFD, FD_CLOEXEC); pid = fork(); switch (pid) { case -1: perror("fork"); exit(1); break; case 0: /* child */ checked_close(c2p[0]); checked_close(errpipe[0]); dup2(c2p[1], 1); dup2(c2p[1], 2); checked_close(c2p[1]); execlp("/bin/ls", "/bin/ls", "/etc/passwd", "/somebogus"); /* If we are still around, exec failed */ write(errpipe[1], "1", 1); _exit(255); break; default: /* parent */ break; } checked_close(errpipe[1]); checked_close(c2p[1]); errpipe_count = read(errpipe[0], errpipe_buf, 1); switch (errpipe_count) { case -1: perror("read"); exit(1); break; case 0: /* EOF, good */ break; default: /* Our "1", exec failed */ fprintf(stderr, "exec in child failed\n"); exit(1); break; } /* now read output from child, via a FILE stream */ if ((output = fdopen(c2p[0], "rb")) == NULL) { perror("fdopen"); exit(1); } setvbuf(output, 0, _IONBF, 0); clearerr(output); count = fread(buf, 1, sizeof(buf), output); if (count >= 0) { fprintf(stderr, "Got %d bytes:\n", count); fprintf(stderr, "%s|", buf); } if (feof(output)) { fprintf(stderr, "EOF has been reached.\n"); } if (ferror(output)) { fprintf(stderr, "An error occured.\n"); } return 0; }