From 38fb13571b2d0c6a2bb32a955e3d00d7d320f093 Mon Sep 17 00:00:00 2001 From: Marius Halden Date: Sat, 31 Oct 2015 02:25:38 +0100 Subject: Add version of piper modified for starting mc --- .gitignore | 4 + Makefile | 15 +++ mcwrapper.c | 319 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 338 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 mcwrapper.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..de99981 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +piper +mcwrapper +bidirtest +*.o diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9c347bc --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ + + +piper: piper.c + ${CC} -o piper -Wall -Werror piper.c + +mcwrapper: mcwrapper.c + ${CC} -o mcwrapper -Wall -Werror mcwrapper.c + +bidirtest: bidirtest.c + ${CC} -o bidirtest -Wall -Werror bidirtest.c + +.PHONY: clean + +clean: + rm -f piper bidirtest mcwrapper diff --git a/mcwrapper.c b/mcwrapper.c new file mode 100644 index 0000000..6aedd14 --- /dev/null +++ b/mcwrapper.c @@ -0,0 +1,319 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_PROCS 2 + +struct proc { + pid_t pid; + char *cmd; + char **argv; + int _stdin; + int _stdout; + int _stderr; +} procs[NUM_PROCS]; + +int fds[2]; + +volatile sig_atomic_t terminate = 0; +volatile sig_atomic_t sendsignal = 0; + +void +reap_all() +{ + int i; + for (i = 0; i < NUM_PROCS; i++) { + if (procs[i].pid != -1) + kill(procs[i].pid, SIGTERM); + } + + sleep(5); + + for (i = 0; i < NUM_PROCS; i++) { + if (procs[i].pid != -1) + kill(procs[i].pid, SIGKILL); + } + + while (wait(NULL) != -1 || errno == EINTR) + ; +} + +void +fail(int exit, const char *msg, ...) +{ + reap_all(); + + va_list args; + va_start(args, msg); + verr(exit, msg, args); + va_end(args); // Not reached? +} + +void +failx(int exit, const char *msg, ...) +{ + reap_all(); + + va_list args; + va_start(args, msg); + verrx(exit, msg, args); + va_end(args); // Not reached? +} + +void +grow_argv(char ***argv, size_t *len) +{ +#define GROW_SIZE 32 + + char **ret = realloc(*argv, sizeof(char *) * (*len + GROW_SIZE)); + if (ret == NULL) + err(1, "realloc"); + + *argv = ret; + *len += GROW_SIZE; + +#undef GROW_SIZE +} + +void +gen_argv(struct proc *proc) +{ + char *saveptr, *tmp, *cmd; + char **argv = NULL, **head; + + size_t len = 0, used = 0; + + + cmd = strdup(proc->cmd); + if (cmd == NULL) + err(1, "strdup"); + + grow_argv(&argv, &len); + head = argv; + + tmp = strtok_r(cmd, " \t", &saveptr); + while (tmp != NULL) { + *(head++) = strdup(tmp); + used++; + + if (used >= len) { + grow_argv(&argv, &len); + head = argv + used; + } + + tmp = strtok_r(NULL, " \t", &saveptr); + } + *head = NULL; + + free(cmd); + + proc->argv = argv; +} + +void +run_cmd(struct proc *proc) +{ + pid_t cpid; + + cpid = fork(); + if (cpid == 0) { + if (proc->_stdin != -1) { + if (close(0) == -1) + fail(1, "close"); + if (dup2(proc->_stdin, 0) == -1) + fail(1, "dup2"); + } + if (proc->_stdout != -1) { + if (close(1) == -1) + fail(1, "close"); + if (dup2(proc->_stdout, 1) == -1) + fail(1, "dup2"); + } + if (proc->_stderr != -1) { + if (close(2) == -1) + fail(1, "close"); + if (dup2(proc->_stderr, 2) == -1) + fail(1, "dup2"); + } + + close(fds[0]); // These aren't very important if they fail + close(fds[1]); + + execvp(proc->argv[0], proc->argv); + + perror("execvp"); + _exit(128); + } else if (cpid == -1) { + fail(1, "fork"); + } else { + proc->pid = cpid; + } +} + +int +have_children() +{ + int i; + for (i = 0; i < NUM_PROCS; i++) { + if (procs[i].pid != -1) + return 1; + } + + return 0; +} + +void +signal_procs() +{ + if (terminate == 1) { + if (procs[0].pid != -1) + kill(procs[0].pid, sendsignal); + else + kill(procs[1].pid, sendsignal); + } else { + int i; + for (i = 0; i < NUM_PROCS; i++) + kill(procs[i].pid, sendsignal); + } + + sendsignal = 0; +} + +void +handle_nonfatal(int sig, siginfo_t *siginfo, void *ucontext) +{ + sendsignal = sig; +} + +void +handle_fatal(int sig, siginfo_t *siginfo, void *ucontext) +{ + terminate = 1; + sendsignal = sig; +} + +void +setup_signals() +{ + struct sigaction act; + memset(&act, 0, sizeof(act)); + + act.sa_sigaction = &handle_fatal; + act.sa_flags = SA_SIGINFO; + + if (sigaction(SIGINT, &act, NULL) == -1) + err(1, "sigaction"); + if (sigaction(SIGHUP, &act, NULL) == -1) + err(1, "sigaction"); + if (sigaction(SIGTERM, &act, NULL) == -1) + err(1, "sigaction"); + + act.sa_sigaction = &handle_nonfatal; + if (sigaction(SIGUSR1, &act, NULL) == -1) + err(1, "sigaction"); + if (sigaction(SIGUSR2, &act, NULL) == -1) + err(1, "sigaction"); +} + +void +start_missing_procs() +{ + int i; + for (i = NUM_PROCS - 1; i >= 0; i--) { + if (procs[i].pid == -1) + run_cmd(&procs[i]); + } +} + +void +print_argv() +{ + int i; + for (i = 0; i < NUM_PROCS; i++) { + char **tmp = procs[i].argv; + + while (*tmp) + printf("%s ", *tmp++); + + printf("\n"); + } +} + +int +have_nonstarted() +{ + return 0; +} + +int +main(int argc, char **argv) +{ + int i; + + if (argc < 3) { + fprintf(stderr, "Usage: piper \n"); + return 1; + } + + setup_signals(); + + for (i = 0; i < NUM_PROCS; i++) { + procs[i].cmd = strdup(argv[i + 1]); + if (procs[i].cmd == NULL) + err(1, "strdup"); + + procs[i].pid = -1; + procs[i]._stdin = -1; + procs[i]._stdout = -1; + procs[i]._stderr = -1; + gen_argv(&procs[i]); + } + + if (pipe(fds) == -1) + err(1, "pipe"); + + procs[0]._stdout = fds[1]; + procs[0]._stderr = fds[1]; + procs[1]._stdin = fds[0]; + + while (!terminate || have_children()) { + pid_t pid; + + if (!terminate) + start_missing_procs(); + + if (sendsignal != 0) + signal_procs(); + + pid = waitpid(0, NULL, 0); + if (pid == -1) { + if (errno == EINTR) { + continue; + } else + fail(1, "wait"); + } else if (pid == procs[0].pid) { + terminate = 1; + + //if (sendsignal == 0) + // sendsignal = SIGTERM; + + close(fds[0]); + close(fds[1]); + + procs[0].pid = -1; + } else if (pid == procs[1].pid) { + procs[1].pid = -1; + } + } + + return 0; +} -- cgit v1.2.3