From 74abc79434fe895d0ca863e4d1d6c5c16b54f296 Mon Sep 17 00:00:00 2001 From: Niklas Halle Date: Mon, 1 Jun 2020 15:46:28 +0200 Subject: trying to connect server and shell, weird --- 03_exercise/srv/process.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 03_exercise/srv/process.c (limited to '03_exercise/srv/process.c') diff --git a/03_exercise/srv/process.c b/03_exercise/srv/process.c new file mode 100644 index 0000000..c5be8c3 --- /dev/null +++ b/03_exercise/srv/process.c @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include + +#include "array.h" +#include "process.h" + + +// given a substring of a line tries to parse out as much information as possible +int parse_command(char const *line, char const *end, process *p) { + char *part; + char **local_parts; + if (arrayInit(part) != 0 || arrayInit(local_parts) != 0) { + fprintf(stderr, "Failed to prepare new part / parts array whilst parsing line"); + return -1; + } + + for (size_t i = 0; line + i < end; ++i) { + char c; + switch (c = line[i]) { + default: + arrayPush(part) = c; + break; + case ' ': + case '\t': + case '\0': + if (arrayLen(part) == 0) + continue; + + arrayPush(part) = '\0'; + arrayPush(local_parts) = part; + arrayInit(part); + } + } + + if (arrayLen(part) == 0) { + arrayRelease(part); + } else { + arrayPush(part) = '\0'; + arrayPush(local_parts) = part; + } + + arrayPush(local_parts) = NULL; + p->argc = arrayLen(local_parts) - 1; + p->argv = local_parts; + + return 0; +} + +int parse_line(char const *const line, process **processes) { + // splits the line at | and then parses the commands + int ret_code; + + if (arrayInit(*processes) != 0) { + perror("Failed to initialize processes array"); + return -1; + } + + bool done = false; + char const *cursor = line; + while (!done) { + process p = {.argv = NULL, .argc = 0, .in_fd = 0, .out_fd = 0, .pid = 0, .blocking = true}; + char const *end = strchr(cursor, '|'); + + if (end == NULL) { + done = true; + end = line + strlen(line); + } + + if ((ret_code = parse_command(cursor, end, &p)) != 0) { + return ret_code; + } + + arrayPush(*processes) = p; + cursor = end + 1; + } + + size_t p_len = arrayLen(*processes); + process *last = *processes + (p_len - 1); + + // linking up all processes as we currently only have pipes for multiple commands + for (size_t i = 0; i < p_len - 1; ++i) { + int fds[2]; + if (pipe(fds) != 0) { + perror("Failed to create pipe"); + return -1; + } + (*processes)[i].out_fd = fds[1]; + (*processes)[i + 1].in_fd = fds[0]; + } + + // setting all processes to non blocking when + if (strcmp(last->argv[last->argc - 1], "&") == 0) { + arrayPop(last->argv) = NULL; + last->argc = last->argc - 1; + last->argv[last->argc] = NULL; + + for (size_t i = 0; i < p_len; ++i) { + (*processes)[i].blocking = false; + } + } + + return ret_code; +} + +int exec_command(process p) { + int status; + + if ((p.pid = fork()) == 0) { + if (p.in_fd != 0) { + dup2(p.in_fd, 0); + close(p.in_fd); + } + if(p.in_fd == 0 && !p.blocking) { + close(0); + } + + if (p.out_fd != 0) { + dup2(p.out_fd, 1); + close(p.out_fd); + } + + execvp(p.argv[0], p.argv); + fprintf(stderr, "command not found: \"%s\"\n", p.argv[0]); + fflush(stderr); + exit(-1); + } + + if (p.pid < 0) { + fprintf(stderr, "no fork\n"); + exit(-2); + } + + if (p.in_fd != 0) { + close(p.in_fd); + } + + if (p.out_fd != 0) { + close(p.out_fd); + } + + if (!p.blocking) + printf("[%i]\n", p.pid); + + if (waitpid(p.pid, &status, p.blocking ? 0 : WNOHANG) < 0) { + fprintf(stderr, "wait error'ed out\n"); + } + + return WEXITSTATUS(status); +} + +void free_processes(process **pr) { + process *processes = *pr; + while (!arrayIsEmpty(processes)) { + process p = arrayPop(processes); + while (!arrayIsEmpty(p.argv)) { + char *tmp = arrayTop(p.argv); + if (tmp) { + arrayRelease(tmp); + } + arrayPop(p.argv) = NULL; + } + arrayRelease(p.argv); + } + arrayRelease(processes); + *pr = NULL; +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf