summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Halle <niklas@niklashalle.net>2020-05-25 18:30:38 +0200
committerNiklas Halle <niklas@niklashalle.net>2020-05-25 18:30:38 +0200
commit41775b83ad93264b487bf0dc353b145922ee6d73 (patch)
tree510876af17d5d3d8f012535389b6eb5b2765d28c
parentcc59cc8557aa9b1fdb62261fade15d9ade9d11fb (diff)
downloadbetriebssysteme-41775b83ad93264b487bf0dc353b145922ee6d73.tar.gz
betriebssysteme-41775b83ad93264b487bf0dc353b145922ee6d73.zip
enabled terminating wait whilst resuming the waited for process, also added fg
-rw-r--r--02_exercise/builtins.c22
-rw-r--r--02_exercise/builtins.h2
-rw-r--r--02_exercise/shell.c49
3 files changed, 44 insertions, 29 deletions
diff --git a/02_exercise/builtins.c b/02_exercise/builtins.c
index ac655d8..4ab4c7c 100644
--- a/02_exercise/builtins.c
+++ b/02_exercise/builtins.c
@@ -14,16 +14,17 @@ void handle(int sig) {
}
-void builtin_wait(process p) {
-
+void builtin_wait(process p, bool bind) {
struct sigaction handler;
handler.sa_handler = handle;
sigemptyset(&handler.sa_mask);
handler.sa_flags = 0;
- bool error = false;
+
pid_t *pids;
arrayInit(pids);
+
size_t i = 1;
+ bool error = false;
while (!error && p.argv[i] != NULL) {
char *end;
pid_t tmp = strtol(p.argv[i], &end, 10);
@@ -40,14 +41,25 @@ void builtin_wait(process p) {
while (!arrayIsEmpty(pids)) {
int status;
pid_t current_pid = arrayPop(pids);
- printf("Waiting for %ld...\n", (long)current_pid);
+ if (bind) {
+ printf("Resuming %ld...\n", (long) current_pid);
+ } else {
+ printf("Waiting for %ld...\n", (long) current_pid);
+ }
// install signal handler without SA_RESTART, so waitpid gets interrupted
sigaction(SIGINT, &handler, NULL);
if (waitpid(current_pid, &status, WUNTRACED) < 0) {
if (EINTR == errno) {
// cancelled by ctrl-c
+ if (bind) {
+ kill(current_pid, SIGKILL);
+ waitpid(current_pid, &status, WUNTRACED);
+ printf("Killed [%ld]\n", (long)current_pid);
+ } else {
+ kill(current_pid, SIGCONT);
+ }
} else {
- perror("Could not wait on process");
+ perror("Could not wait for process");
}
} else {
printf("[%i] TERMINATED\n", current_pid);
diff --git a/02_exercise/builtins.h b/02_exercise/builtins.h
index 1779216..43571f7 100644
--- a/02_exercise/builtins.h
+++ b/02_exercise/builtins.h
@@ -2,6 +2,6 @@
#define BUILTINS_H
#include "process.h"
-void builtin_wait(process p);
+void builtin_wait(process p, bool bind);
#endif \ No newline at end of file
diff --git a/02_exercise/shell.c b/02_exercise/shell.c
index fc50995..03ff6b3 100644
--- a/02_exercise/shell.c
+++ b/02_exercise/shell.c
@@ -11,15 +11,14 @@
#include "prompt_utils.h"
#include "builtins.h"
+process *processes;
-process *processes ;
-
-void signal_handeler (int signal) {
+void signal_handler(int signal) {
printf("Received signal %d", signal);
- if(signal == SIGINT) {
- for(size_t i = 0; i < arrayLen(processes); ++i) {
+ if (signal == SIGINT) {
+ for (size_t i = 0; i < arrayLen(processes); ++i) {
pid_t pid = processes[i].pid;
- if(pid != 0) {
+ if (pid != 0) {
kill(pid, SIGINT);
}
}
@@ -29,8 +28,9 @@ void signal_handeler (int signal) {
int main(void) {
setvbuf(stderr, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
+
// I don't think the shell should exit on SIG_TERM
- if(signal(SIGINT, SIG_IGN)== SIG_ERR) {
+ if (signal(SIGINT, SIG_IGN) == SIG_ERR) {
perror("Couldn't ignore sigterm");
exit(errno);
}
@@ -38,19 +38,19 @@ int main(void) {
printf("Welcome! Available built-ins are:\n"
"cd: `cd <path>` - 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 (#TODO)\n"
+ "fg: `fg pid` - pulls a process from the background back in the foreground\n"
"\n"
- "You can put processes in the background using the unary `&` for new processes, and using CTRL-Z (#TODO) for already running ones\n"
- "With `|` you can pipe the output from one process to the input of another\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();
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;
+ char *line = NULL;
+ size_t cap = 0;
+ __ssize_t length;
printf("%s > ", prompt);
if ((length = getline(&line, &cap, stdin)) < 0) {
@@ -73,7 +73,7 @@ int main(void) {
perror("Can't chain cd with other processes");
}
int ret;
- switch(arrayLen(processes[0].argv)) {
+ switch (arrayLen(processes[0].argv)) {
case 3:
ret = chdir(processes[0].argv[1]);
break;
@@ -89,17 +89,20 @@ int main(void) {
if (ret)
printf("[%i] ", ret);
- free((void *)prompt);
+ free((void *) prompt);
char const *current_wd = get_current_dir_name();
prompt = relative_path(original_wd, current_wd);
- free((void *)current_wd);
+ free((void *) current_wd);
} else if (strcmp(processes[0].argv[0], "exit") == 0) {
done = true;
} else if (strcmp(processes[0].argv[0], "wait") == 0) {
- builtin_wait(processes[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[0].blocking) {
- signal(SIGINT, signal_handeler);
+ 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]);
@@ -109,12 +112,12 @@ int main(void) {
signal(SIGINT, SIG_IGN);
}
- free((void *)line);
+ free((void *) line);
line = NULL;
- cap = 0;
+ cap = 0;
free_processes(&processes);
}
- free((void *)original_wd);
- free((void *)prompt);
+ free((void *) original_wd);
+ free((void *) prompt);
}