From f959165cdece3c1bfae8abce834a2bb78db96190 Mon Sep 17 00:00:00 2001 From: Stefan Zabka Date: Thu, 21 May 2020 23:37:38 +0200 Subject: Process parse_line working --- 02_exercise/process.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 02_exercise/process.c (limited to '02_exercise/process.c') diff --git a/02_exercise/process.c b/02_exercise/process.c new file mode 100644 index 0000000..9bc85be --- /dev/null +++ b/02_exercise/process.c @@ -0,0 +1,148 @@ +// +// Created by stefan on 21.05.20. +// + +#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 = line[i]; + if (c == ' ' || c == '\0') { + if (arrayLen(part) == 0) + continue; + arrayPush(part) = '\0'; + arrayPush(local_parts) = part; + if (c == '\0') { + arrayPush(local_parts) = NULL; + break; + } else { + arrayInit(part); + } + } else { + arrayPush(part) = c; + } + } + if (arrayLen(part) == 0) { + arrayRelease(part); + } else { + arrayPush(local_parts) = part; + } + + arrayInit(part); + arrayPush(part) = '\0'; + arrayPush(local_parts) = part; + p->argc = arrayLen(local_parts); + 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 = 0; + + if (arrayInit(*processes) != 0) { + perror("Failed to initialize processes array"); + return -1; + } + bool done = false; + char const *cursor = line; + while (!done) { + process p = {.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-2], "&")== 0) { + arrayPop(last->argv); + last->argc = last->argc - 1; + + for (size_t i = 0; i < p_len; ++i) { + (*processes)[i].blocking = false; + } + } + return ret_code; +} + +int exec_command(process p, unsigned timeout) { + timeout = timeout ^ timeout; + int pid; + int status; + + if ((pid = fork()) == 0) { + if (p.in_fd != 0) { + dup2(p.in_fd, 0); + } + if (p.out_fd != 0) { + dup2(p.out_fd, 1); + } + execvp(p.argv[0], p.argv); + fprintf(stderr, "could not execute \"%s\"\n", p.argv[0]); + fflush(stderr); + exit(-1); + } + + if (pid < 0) { + fprintf(stderr, "no fork\n"); + exit(-2); + } + + waitpid(pid, &status, 0); + + return WEXITSTATUS(status); +} + +int free_processes(process ** pr) { + process * processes = * pr; + while (!arrayIsEmpty(processes)) { + process p = arrayPop(processes); + while (!arrayIsEmpty(p.argv)) { + char *tmp = arrayPop(p.argv); + if (tmp) + arrayRelease(tmp); + } + arrayRelease(p.argv); + } + arrayRelease(processes); + *pr = NULL; +} \ No newline at end of file -- cgit v1.2.3-54-g00ecf From 40d578c09654ba6720ffd6e365e0d411cfa38613 Mon Sep 17 00:00:00 2001 From: Stefan Zabka Date: Fri, 22 May 2020 00:24:51 +0200 Subject: Somewhat working pipes --- 02_exercise/process.c | 26 ++++++++++++-------------- 02_exercise/process_test.c | 13 +++++++++++++ 02_exercise/shell.c | 2 +- 3 files changed, 26 insertions(+), 15 deletions(-) (limited to '02_exercise/process.c') diff --git a/02_exercise/process.c b/02_exercise/process.c index 9bc85be..00f8762 100644 --- a/02_exercise/process.c +++ b/02_exercise/process.c @@ -44,17 +44,15 @@ int parse_command(char const *line, char const *end, process *p) { arrayPush(local_parts) = part; } - arrayInit(part); - arrayPush(part) = '\0'; - arrayPush(local_parts) = part; - p->argc = arrayLen(local_parts); + 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 + // Splits the line at | and then parses the commands int ret_code = 0; if (arrayInit(*processes) != 0) { @@ -78,24 +76,24 @@ int parse_line(char const *const line, process **processes) { cursor = end + 1; } size_t p_len = arrayLen(*processes); - process * last = *processes + (p_len -1); + 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) { + for (size_t i = 0; i < p_len - 1; ++i) { int fds[2]; - if(pipe(fds) != 0) { + if (pipe(fds) != 0) { perror("Failed to create pipe"); return -1; } - (*processes)[i].out_fd=fds[1]; - (*processes)[i+1].in_fd=fds[0]; - + (*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-2], "&")== 0) { + if (strcmp(last->argv[last->argc - 1], "&") == 0) { arrayPop(last->argv); last->argc = last->argc - 1; + last->argv[last->argc] = NULL; for (size_t i = 0; i < p_len; ++i) { (*processes)[i].blocking = false; @@ -132,8 +130,8 @@ int exec_command(process p, unsigned timeout) { return WEXITSTATUS(status); } -int free_processes(process ** pr) { - process * processes = * pr; +int free_processes(process **pr) { + process *processes = *pr; while (!arrayIsEmpty(processes)) { process p = arrayPop(processes); while (!arrayIsEmpty(p.argv)) { diff --git a/02_exercise/process_test.c b/02_exercise/process_test.c index 89eb2fb..dc3a291 100644 --- a/02_exercise/process_test.c +++ b/02_exercise/process_test.c @@ -43,7 +43,20 @@ void test_pipe() { assert(processes[1].in_fd != 0); free_processes(&processes); } + +void test_ls(){ + process * processes= NULL; + parse_line("ls", &processes); + assert(arrayLen(processes) == 1); + process p = processes[0]; + assert(arrayLen(p.argv)==2); + assert(p.argc == 1); + assert(strcmp(p.argv[0], "ls") == 0); + assert(p.argc[p.argv] == NULL); + free_processes(&processes); +} int main() { + test_ls(); test_simple_case(); test_detatched(); test_pipe(); diff --git a/02_exercise/shell.c b/02_exercise/shell.c index 9653189..eed8e64 100644 --- a/02_exercise/shell.c +++ b/02_exercise/shell.c @@ -57,7 +57,7 @@ int main(void) { char const *current_wd = get_current_dir_name(); prompt = relative_path(original_wd, current_wd); free((void *)current_wd); - } else if (strcmp(processes[0].argv[1], "exit") == 0) { + } else if (strcmp(processes[0].argv[0], "exit") == 0) { done = true; } else { int ret; -- cgit v1.2.3-54-g00ecf From 4f80f043aacc568fac0e3681b62aa1971a97291a Mon Sep 17 00:00:00 2001 From: Stefan Zabka Date: Fri, 22 May 2020 00:30:47 +0200 Subject: FUCK YEAH ls -lisa | grep works --- 02_exercise/process.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to '02_exercise/process.c') diff --git a/02_exercise/process.c b/02_exercise/process.c index 00f8762..08be0fd 100644 --- a/02_exercise/process.c +++ b/02_exercise/process.c @@ -104,15 +104,16 @@ int parse_line(char const *const line, process **processes) { int exec_command(process p, unsigned timeout) { timeout = timeout ^ timeout; - int pid; int status; - if ((pid = fork()) == 0) { + if ((p.pid = fork()) == 0) { if (p.in_fd != 0) { dup2(p.in_fd, 0); + close(p.in_fd); } if (p.out_fd != 0) { dup2(p.out_fd, 1); + close(p.out_fd); } execvp(p.argv[0], p.argv); fprintf(stderr, "could not execute \"%s\"\n", p.argv[0]); @@ -120,12 +121,18 @@ int exec_command(process p, unsigned timeout) { exit(-1); } - if (pid < 0) { + 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); + } - waitpid(pid, &status, 0); + waitpid(p.pid, &status, 0); return WEXITSTATUS(status); } -- cgit v1.2.3-54-g00ecf