summaryrefslogtreecommitdiff
path: root/Userland/sh.cpp
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2018-11-03 02:04:36 +0100
committerAndreas Kling <awesomekling@gmail.com>2018-11-03 02:08:06 +0100
commit20fb1fc3771d3b5f199abd2b7c5ee00419ca5967 (patch)
tree899b29536afff6d5c84b7b46f76f79ebe4d2ee1f /Userland/sh.cpp
parent202bdb553c2dc073f06105b12fbf0b2a8045069b (diff)
downloadserenity-20fb1fc3771d3b5f199abd2b7c5ee00419ca5967.zip
Fix some bugs in execve() and make sh use it for process launching.
Interrupting children of sh now always works with ^C :^)
Diffstat (limited to 'Userland/sh.cpp')
-rw-r--r--Userland/sh.cpp34
1 files changed, 18 insertions, 16 deletions
diff --git a/Userland/sh.cpp b/Userland/sh.cpp
index 6c83c806e4..8df8ae9c58 100644
--- a/Userland/sh.cpp
+++ b/Userland/sh.cpp
@@ -142,16 +142,15 @@ static bool handle_builtin(int argc, const char** argv, int& retval)
return false;
}
-static int try_spawn(const char* path, const char** argv)
+static int try_exec(const char* path, const char** argv)
{
- int ret = spawn(path, argv);
- if (ret >= 0)
- return ret;
+ int ret = execve(path, argv, nullptr);
+ assert(ret < 0);
const char* search_path = "/bin";
char pathbuf[128];
sprintf(pathbuf, "%s/%s", search_path, argv[0]);
- ret = spawn(pathbuf, argv);
+ ret = execve(pathbuf, argv, nullptr);
if (ret == -1)
return -1;
return ret;
@@ -181,21 +180,24 @@ static int runcmd(char* cmd)
return 0;
}
- int ret = try_spawn(argv[0], argv);
- if (ret < 0) {
- printf("spawn failed: %s (%s)\n", cmd, strerror(errno));
- return 1;
+ pid_t child = fork();
+ if (!child) {
+ setpgid(0, 0);
+ tcsetpgrp(0, getpid());
+ int ret = try_exec(argv[0], argv);
+ if (ret < 0) {
+ printf("exec failed: %s (%s)\n", cmd, strerror(errno));
+ exit(1);
+ }
+ // We should never get here!
+ assert(false);
}
- // FIXME: This is racy, since spawn has already started the new process.
- // Once I have fork()+exec(), pgrp setup can be done in the child before exec()ing.
- tcsetpgrp(0, ret);
-
- // FIXME: waitpid should give us the spawned process's exit status
int wstatus = 0;
- waitpid(ret, &wstatus, 0);
+ waitpid(child, &wstatus, 0);
- // FIXME: Racy as mentioned above. Rework once we have fork()+exec().
+ // FIXME: Should I really have to tcsetpgrp() after my child has exited?
+ // Is the terminal controlling pgrp really still the PGID of the dead process?
tcsetpgrp(0, getpid());
if (WIFEXITED(wstatus)) {