summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiklas Halle <niklas@niklashalle.net>2020-05-24 17:08:04 +0200
committerNiklas Halle <niklas@niklashalle.net>2020-05-24 17:08:04 +0200
commit922b46952d38f51850640a20d7be4747e84e95f4 (patch)
treecff5b0ddfde0f1fd6eaa9a95d960ebf4a85f9a19
parent8f33ab3bf8b7d5a256c1d996e572fa67a5578b4f (diff)
downloadbetriebssysteme-922b46952d38f51850640a20d7be4747e84e95f4.tar.gz
betriebssysteme-922b46952d38f51850640a20d7be4747e84e95f4.zip
implemented a basic wait, not much tests yet, some functionality missing
-rw-r--r--02_exercise/process.c14
-rw-r--r--02_exercise/shell.c56
2 files changed, 50 insertions, 20 deletions
diff --git a/02_exercise/process.c b/02_exercise/process.c
index fb55236..95a0600 100644
--- a/02_exercise/process.c
+++ b/02_exercise/process.c
@@ -107,12 +107,6 @@ int parse_line(char const *const line, process **processes) {
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);
@@ -146,16 +140,10 @@ int exec_command(process p) {
if (!p.blocking)
printf("[%i]\n", p.pid);
- if (waitpid(p.pid, &status, 0) < 0) {
+ if (waitpid(p.pid, &status, p.blocking ? 0 : WNOHANG) < 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);
}
diff --git a/02_exercise/shell.c b/02_exercise/shell.c
index ea1b13f..35de455 100644
--- a/02_exercise/shell.c
+++ b/02_exercise/shell.c
@@ -3,14 +3,14 @@
#include <string.h>
#include <unistd.h>
#include <stdbool.h>
+#include <wait.h>
#include "array.h"
#include "process.h"
#include "prompt_utils.h"
-
int main(void) {
- chdir(".");
+ setvbuf(stderr, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
char const *const original_wd = get_current_dir_name();
@@ -24,6 +24,7 @@ int main(void) {
printf("%s > ", prompt);
if ((length = getline(&line, &cap, stdin)) < 0) {
fprintf(stderr, "Failed to read from STDIN");
+ fflush(stderr);
exit(-1);
}
@@ -41,12 +42,20 @@ int main(void) {
perror("Can't chain cd with other processes");
}
- if (arrayLen(processes[0].argv) != 3) {
- fprintf(stderr, "usage: cd <path>");
- goto clean;
+ 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 <path>\n");
+ fflush(stderr);
+ ret = -1;
}
- int ret = chdir(processes[0].argv[1]);
if (ret)
printf("[%i] ", ret);
@@ -56,6 +65,40 @@ int main(void) {
free((void *)current_wd);
} else if (strcmp(processes[0].argv[0], "exit") == 0) {
done = true;
+ } else if (strcmp(processes[0].argv[0], "wait") == 0) {
+ bool error = false;
+ pid_t *pids;
+ arrayInit(pids);
+ size_t i = 1;
+ while (!error && processes[0].argv[i] != NULL) {
+ char *end;
+ pid_t tmp = strtol(processes[0].argv[i], &end, 10);
+ if (*end != '\0') {
+ fprintf(stderr, "Not a valid pid: %s", processes[0].argv[i]);
+ error = true;
+ break;
+ }
+ arrayPush(pids) = tmp;
+ ++i;
+ }
+
+ if (!error) {
+ while (!arrayIsEmpty(pids)) {
+ int status;
+ pid_t current_pid = arrayPop(pids);
+ printf("Waiting for %ld...\n", (long) current_pid);
+ if (waitpid(current_pid, &status, WUNTRACED) < 0) {
+ perror("Could not wait on process");
+ } else {
+ printf("[%i] TERMINATED\n", current_pid);
+ printf("[%i] EXIT STATUS: %i\n", current_pid, status); // TODO: exit status is wrong
+ }
+ // TODO: catch ctrl-c
+ }
+ }
+
+ arrayRelease(pids);
+
} else {
for (size_t i = 0; i < arrayLen(processes); ++i) {
int ret = exec_command(processes[i]);
@@ -65,7 +108,6 @@ int main(void) {
}
- clean:
free((void *)line);
line = NULL;
cap = 0;