diff options
Diffstat (limited to '02_exercise/builtins.c')
-rw-r--r-- | 02_exercise/builtins.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/02_exercise/builtins.c b/02_exercise/builtins.c new file mode 100644 index 0000000..ac655d8 --- /dev/null +++ b/02_exercise/builtins.c @@ -0,0 +1,73 @@ +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <wait.h> +#include <stdlib.h> + + +#include "array.h" +#include "builtins.h" + +void handle(int sig) { + /* Do nothing. */ +} + + +void builtin_wait(process p) { + + struct sigaction handler; + handler.sa_handler = handle; + sigemptyset(&handler.sa_mask); + handler.sa_flags = 0; + bool error = false; + pid_t *pids; + arrayInit(pids); + size_t i = 1; + while (!error && p.argv[i] != NULL) { + char *end; + pid_t tmp = strtol(p.argv[i], &end, 10); + if (*end != '\0') { + fprintf(stderr, "Not a valid pid: %s", p.argv[i]); + error = true; + break; + } + arrayPush(pids) = tmp; + ++i; + } + + if (!error) { + while (!arrayIsEmpty(pids)) { + int status; + pid_t current_pid = arrayPop(pids); + printf("Waiting for %ld...\n", (long)current_pid); + // install signal handler without SA_RESTART, so waitpid gets interrupted + sigaction(SIGINT, &handler, NULL); + if (waitpid(current_pid, &status, WUNTRACED) < 0) { + if (EINTR == errno) { + // cancelled by ctrl-c + } else { + perror("Could not wait on process"); + } + } else { + printf("[%i] TERMINATED\n", current_pid); + if (WIFEXITED(status)) { + printf("[%i] exited normally with status: %i\n", current_pid, + WEXITSTATUS(status)); + } else if (WIFSTOPPED(status)) { + printf("[%i] was stopped by signal: %s\n", current_pid, + strsignal(WSTOPSIG(status))); + } else if (WIFSIGNALED(status)) { + printf("[%i] was terminated by signal: %s\n", current_pid, + strsignal(WTERMSIG(status))); + } else { + printf("[%i] exited (not sure why), exit status: %i\n", current_pid, + WEXITSTATUS(status)); + } + } + signal(SIGINT, SIG_DFL); + } + } + + arrayRelease(pids); +}
\ No newline at end of file |