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/shell.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 03_exercise/srv/shell.c (limited to '03_exercise/srv/shell.c') diff --git a/03_exercise/srv/shell.c b/03_exercise/srv/shell.c new file mode 100644 index 0000000..a32fc5f --- /dev/null +++ b/03_exercise/srv/shell.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "array.h" +#include "process.h" +#include "prompt_utils.h" +#include "builtins.h" + +#define BUF_SIZE 256 + +process *processes; + +const char * const get_current_dir_name(); + +void signal_handler(int signal) { + if (signal == SIGINT) { + for (size_t i = 0; i < arrayLen(processes); ++i) { + pid_t pid = processes[i].pid; + if (pid != 0) { + kill(pid, SIGINT); + } + } + } +} + +int shell(int in_fd) { + setvbuf(stderr, NULL, _IONBF, 0); + setvbuf(stdout, NULL, _IONBF, 0); + + dup2(in_fd, 1); + dup2(in_fd, 2); + + // I don't think the shell should exit on SIG_TERM + if (signal(SIGINT, SIG_IGN) == SIG_ERR) { + perror("Couldn't ignore sigterm"); + exit(errno); + } + + printf("Welcome! Available built-ins are:\n" + "cd: `cd ` - if no path is given, return to the current dir\n" + "wait: `wait pid1 ... pidN` - wait on the processes and report their exit conditions\n" + "fg: `fg pid` - pulls a process from the background back in the foreground\n" + "\n" + "You can put processes in the background using `&`\n" + "And with `|` you can pipe the output from one process to the input of another\n" + ); + + char const *const original_wd = get_current_dir_name(); + + bool done = false; + while (!done) { + char line[BUF_SIZE]; + + for (int i = 0; i < BUF_SIZE; ++i) { + read(in_fd, line + i, 1); + if (line[i] == '\n') { + line[i] = 0; + break; + } + } + + if (strspn(line, " \n\t") == strlen(line)) { + // skip empty lines - empty being just spaces or tabs + continue; + } + + 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"); + } + int ret; + switch (arrayLen(processes[0].argv)) { + case 3: + ret = chdir(processes[0].argv[1]); + break; + case 2: + ret = chdir(original_wd); + break; + default: + fprintf(stderr, "usage: cd \n"); + fflush(stderr); + ret = -1; + } + + if (ret) + printf("[%i] ", ret); + + } else if (strcmp(processes[0].argv[0], "exit") == 0) { + done = true; + } else if (strcmp(processes[0].argv[0], "wait") == 0) { + builtin_wait(processes[0], false); + } else if (strcmp(processes[0].argv[0], "fg") == 0) { + // same behaviour as wait, just bind to shell again (i.e. terminate process on ctrl-c) + builtin_wait(processes[0], true); + } else { + if (arrayLen(processes) != 0 && processes[arrayLen(processes) - 1].blocking) { + signal(SIGINT, signal_handler); + } + for (size_t i = 0; i < arrayLen(processes); ++i) { + int ret = exec_command(processes[i]); + if (ret) + printf("[%i] ", ret); + } + signal(SIGINT, SIG_IGN); + } + + free_processes(&processes); + } + + free((void *) original_wd); + + return 0; +} -- cgit v1.2.3-54-g00ecf