summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Halle <niklas@niklashalle.net>2020-05-21 13:15:25 +0200
committerNiklas Halle <niklas@niklashalle.net>2020-05-21 13:15:25 +0200
commit47f29d306e120f8233e87d43bccd8c97ccf88831 (patch)
tree43856013ec499dec21f9c8e5b2e4cd1a02d77df9
parentdd4f3ec7551fddb88c5d6b96ed1aff3521c937ca (diff)
parent5e2b718c15087ee3401a6c0e1d80196e92f2aa06 (diff)
downloadbetriebssysteme-47f29d306e120f8233e87d43bccd8c97ccf88831.tar.gz
betriebssysteme-47f29d306e120f8233e87d43bccd8c97ccf88831.zip
Merge branch 'dev/niklas'
-rw-r--r--02_exercise/.gitignore2
-rw-r--r--02_exercise/shell.c146
2 files changed, 125 insertions, 23 deletions
diff --git a/02_exercise/.gitignore b/02_exercise/.gitignore
new file mode 100644
index 0000000..5aacf99
--- /dev/null
+++ b/02_exercise/.gitignore
@@ -0,0 +1,2 @@
+prog
+shell
diff --git a/02_exercise/shell.c b/02_exercise/shell.c
index 46b169a..ed53897 100644
--- a/02_exercise/shell.c
+++ b/02_exercise/shell.c
@@ -1,56 +1,156 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-#include <assert.h>
-#include <fcntl.h>
-#include <signal.h>
+#include <unistd.h>
#include <stdbool.h>
-#include <sys/stat.h>
-#include <sys/types.h>
#include <sys/wait.h>
-#include <unistd.h>
#include "array.h"
#include "prompt_utils.h"
-void print_prompt(char const *const original_wd, char const *current_wd);
+int parse_line(char const *line, char ***parts, size_t *part_count);
-// Returns the return code of the executed programm
-int exec_command(char *command);
+// returns the return code of the executed program
+int exec_command(const char *path, char *const argv[], unsigned timeout);
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);
- printf("%s \n", original_wd);
- while (true) {
- char *command = NULL;
+ bool done = false;
+ while (!done) {
+ char *line = NULL;
size_t cap = 0;
__ssize_t length = 0;
printf("%s > ", prompt);
- if ((length = getline(&command, &cap, stdin)) < 0) {
+ if ((length = getline(&line, &cap, stdin)) < 0) {
fprintf(stderr, "Failed to read from STDIN");
exit(-1);
}
- if (strstr(command, "cd") != NULL) {
- printf("Changing dirs \n");
- chdir("beispiele");
+
+ line[length - 1] = '\0'; // cut the line feed
+
+ char **arguments = NULL;
+ size_t argument_count;
+ parse_line(line, &arguments, &argument_count);
+
+ if (strcmp(arguments[0], "cd") == 0) {
+ if (arrayLen(arguments) != 3) {
+ fprintf(stderr, "usage: cd <path>");
+ goto clean;
+ }
+
+ int ret = chdir(arguments[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(command, "exit\n") == 0) {
- exit(0);
+ } else if (strcmp(arguments[0], "exit") == 0) {
+ done = true;
} else {
- exec_command(command);
+ int ret = exec_command(arguments[0], arguments, 0);
+ if (ret)
+ printf("[%i] ", ret);
}
- free((void *)command);
+
+ clean:
+ free((void *)line);
+ while (arrayLen(arguments) > 0) {
+ char *tmp = arrayPop(arguments);
+ if (tmp)
+ arrayRelease(tmp);
+ }
+ arrayRelease(arguments);
}
- // Gotta cast to void otherwise we discard qualifiers
+
free((void *)original_wd);
free((void *)prompt);
}
-int exec_command(char *command) { return 0; }
+int parse_line(char const *line, char ***parts, size_t *part_count) {
+ 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;
+ }
+
+ char c;
+ int i = 0;
+ while (true) {
+ c = line[i++];
+ if (c == ' ' || c == '\0') {
+ arrayPush(part) = '\0';
+ arrayPush(local_parts) = part;
+ if (c == '\0') {
+ arrayPush(local_parts) = NULL;
+ break;
+ } else {
+ arrayInit(part);
+ }
+ } else {
+ arrayPush(part) = c;
+ }
+ }
+
+ *part_count = arrayLen(local_parts);
+ *parts = local_parts;
+
+ return 0;
+}
+
+void print_prompt() {
+ size_t length = 1024;
+ char *buffer = malloc(length * sizeof(char));
+ getcwd(buffer, length);
+ if (buffer == NULL) {
+ printf(".> ");
+ } else {
+ printf("%s > ", buffer);
+ }
+}
+
+int exec_command(const char *path, char *const argv[], unsigned timeout) {
+ timeout = timeout ^ timeout;
+ int pid;
+ int pipefd[2];
+ int status;
+ char buf[512];
+
+ pipe(pipefd);
+ if ((pid = fork()) == 0) {
+ close(pipefd[0]);
+ dup2(pipefd[1], 1); // includes close(1);
+ close(pipefd[1]);
+ execvp(path, argv);
+ fprintf(stderr, "could not execute \"%s\"\n", path);
+ exit(-1);
+ }
+
+ if (pid < 0) {
+ fprintf(stderr, "no fork\n");
+ exit(-2);
+ }
+
+ close(pipefd[1]);
+
+ __ssize_t length = 0;
+ while ((length = read(pipefd[0], buf, 10)) > 0) {
+ buf[length] = '\0';
+ fprintf(stdout, "%s", buf);
+ fflush(stdout);
+ }
+
+ waitpid(pid, &status, 0);
+
+ close(pipefd[0]);
+
+ return WEXITSTATUS(status);
+}