Project

General

Profile

Bug #3268 » main.c

mikdusan, 05/09/2021 09:08 AM

 
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

// invoke with something like: `main /bin/ls -al /`

int main(int argc, char *argv[], char *envp[]) {
int i = 0;
for (int i = 0; i < argc; i += 1) {
printf("[%d] %s\n", i, argv[i]);
}

if (argc < 2) {
fprintf(stderr, "usage: %s exe [arg]...\n", argv[0]);
exit(1);
}

int stdout_pipe[2];
if (pipe(stdout_pipe) == -1) {
fprintf(stderr, "pipe(stdout_pipe) failed: %s\n", strerror(errno));
exit(1);
}

int stderr_pipe[2];
if (pipe(stderr_pipe) == -1) {
fprintf(stderr, "pipe(stderr_pipe) failed: %s\n", strerror(errno));
exit(1);
}

printf("pipes: %d,%d,%d,%d\n", stdout_pipe[0], stdout_pipe[1], stderr_pipe[0], stderr_pipe[1]);

pid_t child_pid = fork();
if (child_pid == -1) {
fprintf(stderr, "fork failed: %s\n", strerror(errno));
exit(1);
}

// child
if (child_pid == 0) {
if (dup2(stdout_pipe[1], STDOUT_FILENO) == -1) {
fprintf(stderr, "dup2(STDOUT_FILENO) failed: %s\n", strerror(errno));
exit(1);
}
if (dup2(stderr_pipe[1], STDERR_FILENO) == -1) {
fprintf(stderr, "dup2(STDOUT_FILENO) failed: %s\n", strerror(errno));
exit(1);
}

close(stdout_pipe[0]);
close(stdout_pipe[1]);
close(stderr_pipe[0]);
close(stderr_pipe[1]);

int rv = execve(argv[1], &argv[1], envp);
if (rv == -1) {
fprintf(stderr, "execve failed: %s\n", strerror(errno));
exit(1);
}
}

// parent

close(stdout_pipe[1]);
close(stderr_pipe[1]);

struct pollfd fds[2];
fds[0].fd = stdout_pipe[0];
fds[0].events = POLLIN;
fds[1].fd = stderr_pipe[0];
fds[1].events = POLLIN;

int nactive = 2;
while (nactive > 0) {
int rv = poll(fds, 2, -1);
if (rv == -1) {
fprintf(stderr, "poll failed: %s\n", strerror(errno));
exit(1);
}
printf("poll rv=%d\n", rv);
if (rv == 0) continue;

printf("fd[0].revents=0x%04x [1].revents=0x%04x\n", fds[0].revents, fds[1].revents);
char buf[8192];
if (fds[0].revents & POLLIN) {
memset(buf, 0, sizeof(buf));
ssize_t nbytes = read(fds[0].fd, buf, sizeof(buf) - 1);
printf("fd[0] read=%ld bytes\n", nbytes);
}

if (fds[1].revents & POLLIN) {
memset(buf, 0, sizeof(buf));
ssize_t nbytes = read(fds[1].fd, buf, sizeof(buf) - 1);
printf("fd[1] read=%ld bytes\n", nbytes);
}

if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
fds[0].fd = -1;
nactive -= 1;
}
if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) {
fds[1].fd = -1;
nactive -= 1;
}
}

int status;
int rv = waitpid(child_pid, &status, 0);
if (rv == -1) {
fprintf(stderr, "waitpid failed: %s\n", strerror(errno));
exit(1);
}

printf("child %d exited with status %d\n", child_pid, status);

return 0;
}
(1-1/3)