From 04576dc2a3f761eb041b808b56f13a58052e7655 Mon Sep 17 00:00:00 2001 From: Stefan Zabka Date: Sun, 24 May 2020 12:19:52 +0200 Subject: Moved back to 02_exercise --- shell/.gitignore | 3 - shell/CMakeLists.txt | 34 ------ shell/Makefile | 32 ------ shell/array.c | 59 ----------- shell/array.h | 142 ------------------------- shell/beispiele/dup/Makefile | 18 ---- shell/beispiele/dup/dup.c | 51 --------- shell/beispiele/fork_example/Makefile | 18 ---- shell/beispiele/fork_example/fork.c | 36 ------- shell/beispiele/fork_signal/Makefile | 19 ---- shell/beispiele/fork_signal/fork.c | 39 ------- shell/beispiele/fork_signal/signal.c | 21 ---- shell/beispiele/pipe_bidirect/Makefile | 19 ---- shell/beispiele/pipe_bidirect/log.txt | 19 ---- shell/beispiele/pipe_bidirect/pingpong.c | 125 ---------------------- shell/beispiele/pipe_example/Makefile | 18 ---- shell/beispiele/pipe_example/pipe.c | 60 ----------- shell/process.c | 173 ------------------------------- shell/process.h | 29 ------ shell/process_test.c | 63 ----------- shell/prog.c | 52 ---------- shell/prompt_utils.c | 90 ---------------- shell/prompt_utils.h | 10 -- shell/prompt_utils_test.c | 45 -------- shell/prompt_utils_test.h | 7 -- shell/shell.c | 77 -------------- 26 files changed, 1259 deletions(-) delete mode 100644 shell/.gitignore delete mode 100644 shell/CMakeLists.txt delete mode 100644 shell/Makefile delete mode 100644 shell/array.c delete mode 100644 shell/array.h delete mode 100644 shell/beispiele/dup/Makefile delete mode 100644 shell/beispiele/dup/dup.c delete mode 100644 shell/beispiele/fork_example/Makefile delete mode 100644 shell/beispiele/fork_example/fork.c delete mode 100644 shell/beispiele/fork_signal/Makefile delete mode 100644 shell/beispiele/fork_signal/fork.c delete mode 100644 shell/beispiele/fork_signal/signal.c delete mode 100644 shell/beispiele/pipe_bidirect/Makefile delete mode 100644 shell/beispiele/pipe_bidirect/log.txt delete mode 100644 shell/beispiele/pipe_bidirect/pingpong.c delete mode 100644 shell/beispiele/pipe_example/Makefile delete mode 100644 shell/beispiele/pipe_example/pipe.c delete mode 100644 shell/process.c delete mode 100644 shell/process.h delete mode 100644 shell/process_test.c delete mode 100644 shell/prog.c delete mode 100644 shell/prompt_utils.c delete mode 100644 shell/prompt_utils.h delete mode 100644 shell/prompt_utils_test.c delete mode 100644 shell/prompt_utils_test.h delete mode 100644 shell/shell.c (limited to 'shell') diff --git a/shell/.gitignore b/shell/.gitignore deleted file mode 100644 index 819a501..0000000 --- a/shell/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -prog -shell -build \ No newline at end of file diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt deleted file mode 100644 index 9cae089..0000000 --- a/shell/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -cmake_minimum_required(VERSION 3.5) - -project(shell C) - -set(CMAKE_C_COMPILER gcc) -set(CMAKE_C_STANDARD 11) -set(CMAKE_C_STANDARD_REQUIRED True) - -find_package(Sanitizers) - -add_executable(prog prog.c) -add_executable(shell shell.c) -target_link_libraries(shell PRIVATE array prompt_utils process) - -add_sanitizers(shell) -add_compile_definitions(_GNU_SOURCE) - -add_library(array array.c) - -add_library(prompt_utils prompt_utils.c) -target_link_libraries(prompt_utils PRIVATE array) - -add_executable(prompt_utils_test prompt_utils_test.c) -target_link_libraries(prompt_utils_test PRIVATE prompt_utils array) - -add_library(process process.c) -target_link_libraries(process PRIVATE array) - -add_executable(process_test process_test.c) -target_link_libraries(process_test PRIVATE process) - -target_compile_options(shell INTERFACE ${PROJECT_WARNINGS}) -target_compile_options(prompt_utils INTERFACE ${PROJECT_WARNINGS}) -target_compile_options(process INTERFACE ${PROJECT_WARNINGS}) diff --git a/shell/Makefile b/shell/Makefile deleted file mode 100644 index 5d1b360..0000000 --- a/shell/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/make -.SUFFIXES: -.PHONY: all run pack clean -TAR = shell prog -SRC = $(wildcard *.c) -OBJ = $(SRC:%.c=%.o) -PCK = lab-2.zip - -CFLAGS = -std=gnu11 -c -g -Os -Wall -Werror -MMD -MP -D=_GNU_SOURCE - -DEP = $(OBJ:%.o=%.d) --include $(DEP) - -%.o: %.c - $(CC) $(CFLAGS) $< -o $@ - -all: $(TAR) - -prog: prog.o - $(CC) -o $@ $^ - -shell: $(filter-out prog.o,$(OBJ)) - $(CC) -o $@ $^ - -run: all - ./shell - -pack: - zip $(PCK) $(SRC) $(wildcard *.h) Makefile - -clean: - $(RM) $(RMFILES) $(TAR) $(OBJ) $(DEP) $(PCK) diff --git a/shell/array.c b/shell/array.c deleted file mode 100644 index 4f08366..0000000 --- a/shell/array.c +++ /dev/null @@ -1,59 +0,0 @@ -/***************************************************************************//** - * @file array.c - * @author Dorian Weber - * @brief Implementation des generalisierten Arrays. - ******************************************************************************/ - -#include "array.h" -#include -#include -#include - -/* ********************************************************* public functions */ - -/* (die runden Klammern um einige Funktionsnamen sind notwendig, da Makros - * gleichen Namens existieren und der Präprozessor diese expandieren würde) */ - -void* (arrayInit)(size_t capacity, size_t size) { - ArrayHdr *hdr = malloc(sizeof(*hdr) + size*capacity); - - if (hdr == NULL) - return NULL; - - hdr->len = 0; - hdr->cap = capacity; - - return hdr + 1; -} - -void arrayRelease(void* self) { - free(((ArrayHdr*) self) - 1); -} - -void* (arrayPush)(void* self, size_t size) { - ArrayHdr *hdr = ((ArrayHdr*) self) - 1; - - if (hdr->len == hdr->cap) { - hdr->cap *= 2; - hdr = realloc(hdr, sizeof(*hdr) + size*hdr->cap); - - if (hdr == NULL) { - fputs("program ran out of heap memory\n", stderr); - exit(-1); - } - } - - ++hdr->len; - return hdr + 1; -} - -void (arrayPop)(void* self) { - ArrayHdr *hdr = ((ArrayHdr*) self) - 1; - assert(hdr->len > 0); - --hdr->len; -} - -/* Symbol für die Inline-Funktionen erzeugen und aus diesem Modul exportieren */ -extern void arrayClear(void* self); -extern int arrayIsEmpty(const void* self); -extern size_t arrayLen(const void* self); diff --git a/shell/array.h b/shell/array.h deleted file mode 100644 index 78d21c9..0000000 --- a/shell/array.h +++ /dev/null @@ -1,142 +0,0 @@ -/***************************************************************************//** - * @file array.h - * @author Dorian Weber - * @brief Generischer Array-Typ. - * - * @details - * Diese Datei enthält die Schnittstelle eines generischen Array-Typs. Um den - * Element-Typ des Arrays festzulegen, deklariert man eine Variable als Zeiger - * auf den Element-Typ. Diese kann danach initialisiert und so benutzt werden, - * als wäre sie ein Zeiger auf ein Array variabler Länge. - * - * Hier ist ein Nutzungsbeispiel: - * @code - * int *array; - * - * arrayInit(array); - * arrayPush(array) = 1; - * arrayPush(array) = 2; - * arrayPush(array) = 3; - * - * while (!arrayIsEmpty(array)) - * printf("%i\n", arrayPop(array)); - * - * arrayRelease(array); - * @endcode - * - * Viele der genutzten Funktionen sind in Form von Makros implementiert, die die - * Variable, die den Zeiger auf das Array hält, aktualisieren, obwohl es so - * aussieht, als würde sich dieser Wert niemals ändern. Das macht es riskant - * mehr als einen Zeiger auf das Array zu halten, da jede Vergrößerung des - * Arrays alle Zeiger auf und in das Array potentiell invalidiert. Obwohl diese - * Fehlerquelle subtil und äußerst schwer diagnostizierbar ist - es ist eine - * extrem einfache Abstraktion - führt diese Datenstruktur meiner Meinung nach - * trotzdem zu einem massiven Produktivitätsgewinn; man sollte sich nur in etwa - * im Klaren über die unterliegende Implementation sein, um genau die Untermenge - * von Programmiertechniken auszuwählen, die korrekt funktioniert. - ******************************************************************************/ - -#ifndef ARRAY_H_INCLUDED -#define ARRAY_H_INCLUDED - -/* *** includes ************************************************************* */ - -#include - -/* *** structures *********************************************************** */ - -/**@brief Arrayheader. - * - * Diese Struktur wird jedem Array im Speicher vorangestellt und beinhaltet - * Informationen über Kapazität und aktuelle Auslastung des Arrays. Die - * Arrayelemente schließen sich dieser Struktur unmittelbar an, so dass der - * Nutzer von dieser versteckten Information nichts bemerkt. - */ -typedef struct ArrayHdr -{ - size_t len; /**<@brief Anzahl der Array-Elemente. */ - size_t cap; /**<@brief Kapazität des reservierten Speichers. */ -} ArrayHdr; - -/* *** interface ************************************************************ */ - -/**@internal - * @brief Initialisiert und gibt einen Zeiger auf den Start des Arrays zurück. - * @param capacity initiale Kapazität - * @param size Größe der Arrayelemente - * @return ein Zeiger auf den Start des Arrays, falls erfolgreich,\n - * \c NULL im Falle eines Speicherfehlers - */ -extern void* arrayInit(size_t capacity, size_t size); - -/**@brief Initialisiert ein neues Array. - * @param self das Array - * @return 0, falls keine Fehler bei der Initialisierung aufgetreten sind,\n - * -1 ansonsten - */ -#define arrayInit(self) \ - ((self = arrayInit(8, sizeof((self)[0]))) == NULL ? -1 : 0) - -/**@brief Gibt das Array und alle assoziierten Strukturen frei. - * @param self das Array - */ -extern void arrayRelease(void* self); - -/**@internal - * @brief Reserviert Platz für einen neuen Wert im Array. - * @param self das Array - * @param size Größe der Arrayelemente - * @return der neue Zeiger auf den Start des Arrays - */ -extern void* arrayPush(void* self, size_t size); - -/**@brief Legt einen Wert auf das Array. - * @param self das Array - */ -#define arrayPush(self) \ - (self = arrayPush(self, sizeof((self)[0])), (self)+arrayLen(self)-1)[0] - -/**@brief Entfernt das oberste Element des Arrays. - * @param self das Array - */ -extern void arrayPop(void* self); - -/**@brief Entfernt und liefert das oberste Element des Arrays. - * @param self das Array - * @return das oberste Element von \p self - */ -#define arrayPop(self) \ - (arrayPop(self), (self)+arrayLen(self))[0] - -/**@brief Gibt das oberste Element des Arrays zurück. - * @param self das Array - * @return das oberste Element von \p self - */ -#define arrayTop(self) \ - (self)[arrayLen(self) - 1] - -/**@brief Setzt die Länge des Arrays auf 0 zurück. -* @param self das Array -*/ -inline void arrayClear(void* self) { - ((ArrayHdr*) self)[-1].len = 0; -} - -/**@brief Gibt zurück, ob das Array leer ist. - * @param self das Array - * @return 0, falls nicht leer\n - 1, falls leer - */ -inline int arrayIsEmpty(const void* self) { - return ((ArrayHdr*) self)[-1].len == 0; -} - -/**@brief Gibt die Anzahl der Array-Elemente zurück. - * @param self das Array - * @return Anzahl der Elemente des Arrays - */ -inline size_t arrayLen(const void* self) { - return ((ArrayHdr*) self)[-1].len; -} - -#endif /* ARRAY_H_INCLUDED */ diff --git a/shell/beispiele/dup/Makefile b/shell/beispiele/dup/Makefile deleted file mode 100644 index 0f73ac4..0000000 --- a/shell/beispiele/dup/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/make -.SUFFIXES: - -CFLAGS = -c -Os -Wall -Werror - -%.o: %.c - $(CC) $(CFLAGS) $^ -o $@ - -%: %.o - $(CC) -o $@ $^ - -all: dup - -run: all - ./dup - -clean: - $(RM) $(RMFILES) dup diff --git a/shell/beispiele/dup/dup.c b/shell/beispiele/dup/dup.c deleted file mode 100644 index ea3c5a6..0000000 --- a/shell/beispiele/dup/dup.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include - -/* https://www.youtube.com/watch?v=gaXigSu72A4 */ -static inline void die(const char* msg) { - perror(msg); - exit(EXIT_FAILURE); -} - -int main(int argc, char **argv) { - int pdes[2]; - pid_t child; - - if (pipe(pdes) < 0) - die("pipe()"); - - if ((child = fork()) < 0) - die("fork()"); - - if (child == 0) { - /* child process */ - close(pdes[0]); - close(1); /* close stdout */ - - if (dup(pdes[1]) < 0) - die("dup()"); - - /* now stdout and pdes[1] are equivalent (dup returns lowest free descriptor) */ - if (execlp("cat", "cat", "/etc/passwd", NULL) < 0) - die("execlp()"); - - exit(EXIT_SUCCESS); - } - else { - /* parent process */ - close(0); /* close stdin */ - close(pdes[1]); - - if (dup(pdes[0]) < 0) - die("dup()"); - - /* now stdin and pdes[0] are equivalent (dup returns lowest free descriptor) */ - if (execlp("wc", "wc", "-l", NULL) < 0) - die("execlp()"); - - exit(EXIT_SUCCESS); - } - - return 0; -} diff --git a/shell/beispiele/fork_example/Makefile b/shell/beispiele/fork_example/Makefile deleted file mode 100644 index 8f69ed9..0000000 --- a/shell/beispiele/fork_example/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/make -.SUFFIXES: - -CFLAGS = -c -Os -Wall -Werror - -%.o: %.c - $(CC) $(CFLAGS) $^ -o $@ - -%: %.o - $(CC) -o $@ $^ - -all: fork - -run: all - ./fork - -clean: - $(RM) $(RMFILES) fork diff --git a/shell/beispiele/fork_example/fork.c b/shell/beispiele/fork_example/fork.c deleted file mode 100644 index 7377b0f..0000000 --- a/shell/beispiele/fork_example/fork.c +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include -#include - -int main(void) { - pid_t proc_id; - int status = 0; - - proc_id = fork(); - - if (proc_id < 0) { - fprintf(stderr, "fork error\n"); - fflush(stderr); - return EXIT_FAILURE; - } - - if (proc_id == 0) { - /* child process */ - printf("[child] process id: %d\n", (int) getpid()); - - char* args[] = {"sleep", "1", NULL}; - execvp(args[0], args); - exit(-1); - } - else { - /* parent */ - printf("[parent] process id: %d\n", (int) getpid()); - pid_t child_id = wait(&status); - - printf("[parent] child %d returned: %d\n", - child_id, WEXITSTATUS(status)); - } - - return EXIT_SUCCESS; -} diff --git a/shell/beispiele/fork_signal/Makefile b/shell/beispiele/fork_signal/Makefile deleted file mode 100644 index 499b8cb..0000000 --- a/shell/beispiele/fork_signal/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/make -.SUFFIXES: - -CFLAGS = -c -O0 - -%.o: %.c - $(CC) $(CFLAGS) $^ -o $@ - -%: %.o - $(CC) -o $@ $^ - -all: fork signal - -run: all - ./fork 10 - ./signal - -clean: - $(RM) $(RMFILES) fork signal diff --git a/shell/beispiele/fork_signal/fork.c b/shell/beispiele/fork_signal/fork.c deleted file mode 100644 index b144577..0000000 --- a/shell/beispiele/fork_signal/fork.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include -#include - -int main(int argc, const char* argv[]) { - pid_t pid; - int h; - int count; - - if (argc < 2) { - printf("Usage: ./fork process#\n"); - return 0; - } - - count = atoi(argv[1]) - 1; - printf("Process#: %d\n", count + 1); - printf("Parent started\n"); - - pid = 1; - for (h = 0; h < count; ++h) { - if ((pid = fork()) < 0) - printf("fork error\n"); - else if (pid == 0) { - printf("Child %d started\n", h); - sleep(1); - printf("Child %d finished\n", h); - exit(0); - } - } - - printf("Parent waiting\n"); - for (h = 0; h < count; ++h) { - wait(NULL); - } - printf("Parent finished\n"); - return EXIT_SUCCESS; -} diff --git a/shell/beispiele/fork_signal/signal.c b/shell/beispiele/fork_signal/signal.c deleted file mode 100644 index 500d2e1..0000000 --- a/shell/beispiele/fork_signal/signal.c +++ /dev/null @@ -1,21 +0,0 @@ -#include -#include -#include -#include - -void sig_handler(int signo) { - const char msg[] = "Speicherzugriffsfehler!\n"; - write(2, msg, sizeof(msg) - 1); - exit(-1); -} - -int main(void) { - if (signal(SIGSEGV, sig_handler) == SIG_ERR) { - perror("signal"); - exit(-1); - } - - int array[1] = {0}; - array[1000000] = 3; - return 0; -} diff --git a/shell/beispiele/pipe_bidirect/Makefile b/shell/beispiele/pipe_bidirect/Makefile deleted file mode 100644 index 361ac97..0000000 --- a/shell/beispiele/pipe_bidirect/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/make -.SUFFIXES: - -CFLAGS = -c -Os -Wall -Werror - -%.o: %.c - $(CC) $(CFLAGS) $^ -o $@ - -%: %.o - $(CC) -o $@ $^ - -all: pingpong - -run: all - @echo "writing into log.txt; stop execution with CTRL+C" - ./pingpong - -clean: - $(RM) $(RMFILES) pingpong diff --git a/shell/beispiele/pipe_bidirect/log.txt b/shell/beispiele/pipe_bidirect/log.txt deleted file mode 100644 index c59b0bb..0000000 --- a/shell/beispiele/pipe_bidirect/log.txt +++ /dev/null @@ -1,19 +0,0 @@ -[3225581]: ping -[3225580]: pong -[3225581]: ping -[3225580]: pong -[3225581]: ping -[3225580]: pong -[3225581]: ping -[3225580]: pong -[3225581]: ping -[3225580]: pong -[3225581]: ping -[3225580]: pong -[3225581]: ping -[3225580]: pong -[3225581]: ping -[3225580]: pong -[3225581]: ping -[3225580]: pong -Programmabbruch durch Nutzer diff --git a/shell/beispiele/pipe_bidirect/pingpong.c b/shell/beispiele/pipe_bidirect/pingpong.c deleted file mode 100644 index f38394f..0000000 --- a/shell/beispiele/pipe_bidirect/pingpong.c +++ /dev/null @@ -1,125 +0,0 @@ -#include -#include -#include -#include -#include - -static int split(int fd[2]); -static int redir(int fd, const char *file); -static void sig_handler(int sig); - -static int parent; - -int main(void) { - ssize_t bytes; - char buf[256]; - int fd[2]; - - // disable buffering for stdout - setvbuf(stdout, NULL, _IONBF, 0); - - // redirect stdout to write into a file - if (redir(1, "log.txt") < 0) { - perror("redir()"); - exit(-1); - } - - // install the signal handler for Ctrl+C - if (signal(SIGINT, sig_handler) == SIG_ERR) { - perror("signal()"); - exit(-1); - } - - // split processes and assign file descriptors for communication - switch (split(fd)) { - case -1: // error - exit(-1); - - case 0: // child - while ((bytes = read(fd[0], buf, sizeof(buf))) > 0) { - printf("[%u]: %s\n", getpid(), buf); - sleep(1); - write(fd[1], "pong", 5); - } - break; - - case 1: // parent - parent = 1; - write(fd[1], "ping", 5); - while ((bytes = read(fd[0], buf, sizeof(buf))) > 0) { - printf("[%u]: %s\n", getpid(), buf); - sleep(1); - write(fd[1], "ping", 5); - } - break; - } - - // close the file descriptors - close(fd[0]); - close(fd[1]); - - return 0; -} - -int split(int fd[2]) { - int pfd[2][2]; - - if (pipe(pfd[0]) < 0) { - perror("pipe()"); - goto err_pipe1; - } - - if (pipe(pfd[1]) < 0) { - perror("pipe()"); - goto err_pipe2; - } - - switch (fork()) { - case -1: - perror("fork()"); - goto err_fork; - - case 0: // child process - close(pfd[0][1]); // close write for child - close(pfd[1][0]); // close read for parent - fd[0] = pfd[0][0]; // keep read for child - fd[1] = pfd[1][1]; // keep write for parent - return 0; - - default: // parent process - close(pfd[1][1]); // close write for parent - close(pfd[0][0]); // close read for child - fd[0] = pfd[1][0]; // keep read for parent - fd[1] = pfd[0][1]; // keep write for child - return 1; - } - -err_fork: - close(pfd[1][0]); - close(pfd[1][1]); -err_pipe2: - close(pfd[0][0]); - close(pfd[0][1]); -err_pipe1: - return -1; -} - -int redir(int fd, const char *file) { - int fd2 = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0644); - - if (fd2 < 0) - return -1; - - dup2(fd2, fd); - close(fd2); - - return 0; -} - -void sig_handler(int sig) { - if (parent) { - const char msg[] = "Programmabbruch durch Nutzer\n"; - write(1, msg, sizeof(msg) - 1); - } - exit(0); -} diff --git a/shell/beispiele/pipe_example/Makefile b/shell/beispiele/pipe_example/Makefile deleted file mode 100644 index d69473e..0000000 --- a/shell/beispiele/pipe_example/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/make -.SUFFIXES: - -CFLAGS = -c -Os -Wall -Werror - -%.o: %.c - $(CC) $(CFLAGS) $^ -o $@ - -%: %.o - $(CC) -o $@ $^ - -all: pipe - -run: all - ./pipe - -clean: - $(RM) $(RMFILES) pipe diff --git a/shell/beispiele/pipe_example/pipe.c b/shell/beispiele/pipe_example/pipe.c deleted file mode 100644 index 422e4d5..0000000 --- a/shell/beispiele/pipe_example/pipe.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include -#include - -#define BUF_SIZE 32 - -int pipe_fds[2]; - -void term(const char *msg) { - if (msg) { - fprintf(stderr, "Error: %s\n", msg); - fflush(stderr); - } - - int close_fail = 0; - int ret = close(pipe_fds[0]); - - if (ret < 0) { - fprintf(stderr, "Error: Couldn't close reading end of pipe\n"); - fflush(stderr); - close_fail = 1; - } - - ret = close(pipe_fds[1]); - - if (ret < 0) { - fprintf(stderr, "Error: Couldn't close writing end of pipe\n"); - fflush(stderr); - close_fail = 1; - } - - exit((msg || close_fail) ? EXIT_FAILURE : EXIT_SUCCESS); -} - -int main(void) { - int ret = pipe(pipe_fds); - - if (ret < 0) - term("Couldn't create pipe"); - - char out_buf[] = "hello"; - ret = write(pipe_fds[1], out_buf, strlen(out_buf) + 1); - - if (ret < 0) - term("Couldn't write to pipe"); - - printf("send msg: %s\n", out_buf); - - char in_buf[BUF_SIZE]; - memset(in_buf, 0, BUF_SIZE); - - ret = read(pipe_fds[0], in_buf, BUF_SIZE - 1); - - if (ret < 0) - term("Couldn't read from pipe"); - - printf("recv msg: %s\n", in_buf); - return 0; -} diff --git a/shell/process.c b/shell/process.c deleted file mode 100644 index 093b712..0000000 --- a/shell/process.c +++ /dev/null @@ -1,173 +0,0 @@ -#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; - } - - 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 = {.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.blocking) { - // if the process is to be put in the background let a fork handle it - if (fork() != 0) - return 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]); - 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, 0) < 0) { - fprintf(stderr, "wait error'ed out\n"); - } - - if (!p.blocking) { - printf("[%i] TERMINATED\n", p.pid); - printf("[%i] EXIT STATUS: %i\n", p.pid, status); // TODO: exit status is wrong - exit(0); - } - - return WEXITSTATUS(status); -} - -void 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 diff --git a/shell/process.h b/shell/process.h deleted file mode 100644 index 3b7e833..0000000 --- a/shell/process.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SHELL_PROCESS_H -#define SHELL_PROCESS_H -#include -#include - -typedef struct { - char **argv; - size_t argc; - int in_fd; - int out_fd; - int pid; - bool blocking; -} Process; - -/* - * Parses the given line and creates an array of processes at *processes - * Expects tail -F file | grep panic & to mean that both processes should - * run in the background - */ -int parse_line(char const *line, Process ** processes); - -/* - * returns the return code of the executed program - */ -int exec_command(Process p); - -void free_processes(Process ** processes); - -#endif // SHELL_PROCESS_H diff --git a/shell/process_test.c b/shell/process_test.c deleted file mode 100644 index c14aa59..0000000 --- a/shell/process_test.c +++ /dev/null @@ -1,63 +0,0 @@ -#include -#include - -#include "array.h" -#include "process.h" - -void test_simple_case() { - Process *processes = NULL; - parse_line("cat my_txt ", &processes); - assert(arrayLen(processes) == 1); - assert(arrayLen(processes[0].argv) == 3); - assert(strcmp(processes[0].argv[0], "cat") == 0); - assert(strcmp(processes[0].argv[1], "my_txt") == 0); - free_processes(&processes); -} - -void test_detached() { - Process *processes = NULL; - parse_line("cat my_txt &", &processes); - assert(arrayLen(processes) == 1); - assert(arrayLen(processes[0].argv) == 3); - assert(strcmp(processes[0].argv[0], "cat") == 0); - assert(strcmp(processes[0].argv[1], "my_txt") == 0); - assert(processes[0].blocking == false); - free_processes(&processes); -} - - -void test_pipe() { - Process *processes = NULL; - parse_line("echo my_txt | grep txt", &processes); - assert(arrayLen(processes) == 2); - assert(arrayLen(processes[0].argv) == 3); - assert(strcmp(processes[0].argv[0], "echo") == 0); - assert(strcmp(processes[0].argv[1], "my_txt") == 0); - assert(processes[0].out_fd != 0); - assert(arrayLen(processes[1].argv) == 3); - assert(strcmp(processes[1].argv[0], "grep") == 0); - assert(strcmp(processes[1].argv[1], "txt") == 0); - 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_detached(); - test_pipe(); - return 0; -} diff --git a/shell/prog.c b/shell/prog.c deleted file mode 100644 index efd2527..0000000 --- a/shell/prog.c +++ /dev/null @@ -1,52 +0,0 @@ -#include -#include -#include -#include - -static unsigned int hash(const void* key, size_t size) { - const char* ptr = key; - unsigned int hval; - - for (hval = 0x811c9dc5u; size --> 0; ++ptr) { - hval ^= *ptr; - hval *= 0x1000193u; - } - - return hval; -} - -static inline int roll(int sides) { - return rand() / (RAND_MAX + 1.0) * sides; -} - -int main(int argc, const char* argv[]) { - int rc, delay; - time_t now = time(0); - - /* initialize the random number generator */ - srand(hash(&now, sizeof(now))); - - /* determine exit code and time delay */ - switch (argc) { - default: - delay = atoi(argv[1]); - rc = atoi(argv[2]); - break; - - case 2: - delay = atoi(argv[1]); - rc = roll(2) - 1; - break; - - case 1: - delay = roll(10); - rc = roll(2) - 1; - break; - } - - printf("Delay: %ds, Exit Code: %d\n", delay, rc); - fflush(stdout); - sleep(delay); - - return rc; -} diff --git a/shell/prompt_utils.c b/shell/prompt_utils.c deleted file mode 100644 index 168c088..0000000 --- a/shell/prompt_utils.c +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include - -#include "array.h" -#include "prompt_utils.h" - -char const *relative_path(char const *const from_dir, char const *const to_dir) { - // easiest cases first - { - if (strcmp(from_dir, to_dir) == 0) { - char *return_value = malloc(2); - strcpy(return_value, "."); - return return_value; - } - } - { - if (strcmp("/", from_dir) == 0) { - char *return_value = malloc(strlen(to_dir) + 2); - return_value[0] = '.'; - memcpy(return_value + 1, to_dir, strlen(to_dir) + 1); - return return_value; - } - } - - // splitting path into pieces so we can do strcmp on each of them - size_t const *const from_dir_indeces = get_separator_indices(from_dir, '/'); - size_t const *const to_dir_indeces = get_separator_indices(to_dir, '/'); - - size_t from_dir_len = arrayLen(from_dir_indeces); - size_t to_dir_len = arrayLen(to_dir_indeces); - - // finding the longest common substring - size_t array_len = from_dir_len < to_dir_len ? from_dir_len : to_dir_len; - size_t i = 0; - size_t common_position = 0; - for (; i < array_len - 1; ++i) { - if (from_dir_indeces[i + 1] != to_dir_indeces[i + 1]) { - break; - } - size_t index = from_dir_indeces[i]; - size_t count = from_dir_indeces[i + 1] - from_dir_indeces[i]; - if (strncmp(from_dir + index, to_dir + index, count) != 0) { - break; - } - common_position = from_dir_indeces[i + 1]; - } - - size_t levels_up = from_dir_len - i - 1; - char *return_value; - if (levels_up == 0) { - // equal dirs for whole length of path and not equal => subdir - size_t length = strlen(to_dir + common_position) + strlen("./") + 1; - return_value = malloc(length * sizeof(char)); - strcpy(return_value, "."); - strcat(return_value, to_dir + common_position); - } else { - char const *const go_up = "/.."; - size_t length = strlen(to_dir + common_position) + strlen("..") + - strlen(go_up) * (levels_up - 1) + 1; - return_value = malloc(length * sizeof(char)); - strcpy(return_value, ".."); - for (size_t j = 0; j < levels_up - 1; ++j) { - strcat(return_value, go_up); - } - if (strcmp("/", to_dir) != 0) { - strcat(return_value, to_dir + common_position); - } - } - - arrayRelease((void *)from_dir_indeces); - arrayRelease((void *)to_dir_indeces); - - return return_value; -} - -size_t *get_separator_indices(char const *const text, char seperator) { - size_t *indices; - arrayInit(indices); - char const *current = text; - if (strchr(current, seperator) == NULL) { - arrayRelease(indices); - return NULL; - } - while ((current = strchr(current, seperator)) != NULL) { - arrayPush(indices) = (size_t) (current - text); - ++current; - } - arrayPush(indices) = strlen(text); - return indices; -} diff --git a/shell/prompt_utils.h b/shell/prompt_utils.h deleted file mode 100644 index 36d065d..0000000 --- a/shell/prompt_utils.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef PROMPT_UTILS_H_INCLUDED -#define PROMPT_UTILS_H_INCLUDED - -// returns the relative path to get from the `from_dir` to the `to_dir` -char const *relative_path(char const *from_dir, char const *to_dir); - -// returns the position of each occurrence of the separator -size_t *get_separator_indices(char const *text, char separator); - -#endif // PROMPT_UTILS_H_INCLUDED diff --git a/shell/prompt_utils_test.c b/shell/prompt_utils_test.c deleted file mode 100644 index 1be6162..0000000 --- a/shell/prompt_utils_test.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "array.h" -#include "prompt_utils.h" -#include -#include -#include - -void test_get_separator_indices() { - char const *const test_str = "/This/is/a/test"; - size_t const *const result = get_separator_indices(test_str, '/'); - for (size_t i = 0; i < arrayLen(result); i++) { - printf("%ld : %s \n", result[i], test_str + result[i]); - } -} -void test_paths(char const *const from, char const *const to, - char const *const expected) { - size_t const *const result = get_separator_indices(from, '/'); - for (size_t i = 0; i < arrayLen(result); i++) { - printf("%ld : %s \n", result[i], from + result[i]); - } - size_t const *const result2 = get_separator_indices(to, '/'); - for (size_t i = 0; i < arrayLen(result2); i++) { - printf("%ld : %s \n", result2[i], to + result2[i]); - } - char const *const path = relative_path(from, to); - printf("The relative path of %s to %s is %s \n", from, to, path); - - assert(strcmp(path, expected) == 0); -} -void test_relative_path() { - test_paths("/Test", "/Test/a", "./a"); - test_paths("/abc/def/ghi", "/abc/def/ghi", "."); - test_paths("/Test", "/Test/a/asd", "./a/asd"); - test_paths("/Test/b/c", "/Test/b", ".."); - test_paths("/", "/Test/a/asd", "./Test/a/asd"); - test_paths("/Test/c", "/Test/b", "../b"); - test_paths("/B/C", "/", "../.."); -} - - -int main(void) { - test_relative_path(); - test_get_separator_indices(); - return 0; -} - diff --git a/shell/prompt_utils_test.h b/shell/prompt_utils_test.h deleted file mode 100644 index 59717d0..0000000 --- a/shell/prompt_utils_test.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef PROMPT_UTILS_TEST_H_INCLUDED -#define PROMPT_UTILS_TEST_H_INCLUDED - -void test_get_separator_indices(); -void test_relative_path(); - -#endif diff --git a/shell/shell.c b/shell/shell.c deleted file mode 100644 index dd0085d..0000000 --- a/shell/shell.c +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include -#include - -#include "array.h" -#include "process.h" -#include "prompt_utils.h" - - -int main(void) { - chdir("."); - setvbuf(stdout, NULL, _IONBF, 0); - - char const *const original_wd = get_current_dir_name(); - char const *prompt = relative_path(original_wd, original_wd); - bool done = false; - while (!done) { - char *line = NULL; - size_t cap = 0; - __ssize_t length = 0; - - printf("%s > ", prompt); - if ((length = getline(&line, &cap, stdin)) < 0) { - fprintf(stderr, "Failed to read from STDIN"); - exit(-1); - } - - if (strspn(line, " \n\t") == strlen(line)) { - continue; - } - line[length - 1] = '\0'; // cut the line feed - - Process * processes = NULL; - parse_line(line, &processes); - - if (strcmp(processes[0].argv[0], "cd") == 0) { - - if(arrayLen(processes) != 1) { - perror("Can't chain cd with other processes"); - } - if (arrayLen(processes[0].argv) != 3) { - fprintf(stderr, "usage: cd "); - goto clean; - } - - int ret = chdir(processes[0].argv[1]); - if (ret) - printf("[%i] ", ret); - - free((void *)prompt); - 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[0], "exit") == 0) { - done = true; - } else { - int ret; - for (size_t i = 0; i < arrayLen(processes); ++i) { - ret = exec_command(processes[i]); - if (ret) - printf("[%i] ", ret); - } - - } - - clean: - free((void *)line); - line = NULL; - cap = 0; - free_processes(&processes); - } - - free((void *)original_wd); - free((void *)prompt); -} -- cgit v1.2.3-54-g00ecf