aboutsummaryrefslogtreecommitdiff
path: root/src/eval.cc
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-09-16 11:28:14 +0000
committer_ov4 <ov4@ov4.org>2026-09-16 11:28:14 +0000
commite489a2db5a1e56e66f6df12642ad8cfd988d4b30 (patch)
treeaafcb1d962e9ce24ddccf00aff82d0ed0804fc4c /src/eval.cc
parent165ead4adbf8494db82f7be35c6f8d52ac47ebef (diff)
implement subshell, and fix vector operator[] unvalid index
Diffstat (limited to 'src/eval.cc')
-rw-r--r--src/eval.cc88
1 files changed, 82 insertions, 6 deletions
diff --git a/src/eval.cc b/src/eval.cc
index 0192ab7..6d16cf7 100644
--- a/src/eval.cc
+++ b/src/eval.cc
@@ -30,7 +30,7 @@ extern char **environ;
namespace ov4
{
-int eval_exe(string s, bool is_aync)
+int eval_exe(const string &s, bool is_aync)
{
loggerln("eval_exe: receive {}", s);
@@ -69,10 +69,13 @@ int eval_exe(string s, bool is_aync)
sigprocmask(SIG_SETMASK, &prev, nullptr);
- // program inside execve may use SIGTTIN/SIGTTOU so just restore in child
+ // program inside execve may use SIGTTIN/SIGTTOU
+ // so just restore in child
sigprocmask(SIG_UNBLOCK, &block_io, nullptr);
execve(cmd_c, argv, environ);
+ // execve: if success, never returns
+
wrap_eliminator(cmdline);
cout << cmdline << flush;
switch (errno)
@@ -135,12 +138,85 @@ int eval_exe(string s, bool is_aync)
return 0;
}
-int eval_tree_cd(size_t i, const T_lexer &lexer_instance)
+int eval_subshell(size_t i, const T_lexer &lexer_instance)
+{
+ println("eval_tree_cd: processing subshell");
+
+ // TODO: implement async
+ bool is_aync = false;
+
+ char cmdline[] = "subshell";
+
+ // block_io signals can stop shell
+ // when child is at foreground, parent shell is at background
+ sigprocmask(SIG_BLOCK, &block_io, nullptr);
+
+ sigset_t prev;
+ block_all(&prev);
+
+ shell_pgid = getpgid(0);
+ pid_t pid = fork();
+
+ if (pid == 0) // child
+ {
+ setpgid(0, 0);
+ if (!is_aync) // foreground
+ tcsetpgrp(tty_fd, getpgrp());
+
+ sigprocmask(SIG_SETMASK, &prev, nullptr);
+
+ // program inside execve may use SIGTTIN/SIGTTOU
+ // so just restore in child
+ sigprocmask(SIG_UNBLOCK, &block_io, nullptr);
+ eval_tree_cd(i, lexer_instance, true);
+ exit(0);
+ }
+
+ // parent
+
+ exit_required_pid = pid;
+
+ if (!is_aync) // foreground
+ {
+ addjob(pid, FG, cmdline);
+ sigset_t prev_with_sigchld_blocked = prev;
+ sigaddset(&prev_with_sigchld_blocked, SIGCHLD);
+ sigprocmask(SIG_SETMASK, &prev_with_sigchld_blocked, NULL);
+ waitfg(pid);
+ sigprocmask(SIG_SETMASK, &prev, NULL);
+
+ return exit_code;
+ }
+ else // background
+ {
+ addjob(pid, BG, cmdline);
+ sigprocmask(SIG_SETMASK, &prev, NULL);
+ cout << "[" << pid2jid(pid) << "] (" << pid << ") " << cmdline;
+
+ // POSIX:
+ // async command returns 0 immediately
+ // TODO: recurring async
+ return 0;
+ }
+}
+
+int eval_tree_cd(size_t i, const T_lexer &lexer_instance, bool inside_subshell)
{
// TODO: async
int ret = -1;
+ println("eval_tree_cd: processing {} subshell {}", i, (lexer_instance.ast[i].subshell ? "TRUE" : "FALSE"));
+
+ // if it's a subshell, and current AST's subshell status is not subshell
+ // (subshell should be forkerd already, then set inside_subshell = true)
+ // fork itself
+ if (lexer_instance.ast[i].subshell && !inside_subshell)
+ {
+ eval_subshell(i, lexer_instance);
+ return 0;
+ }
+
if (lexer_instance.ast[i].token_type == TEXT)
{
ret = eval_exe(lexer_instance.ast[i].command_text, false);
@@ -149,7 +225,7 @@ int eval_tree_cd(size_t i, const T_lexer &lexer_instance)
if (lexer_instance.ast[i].left != string::npos)
{
- ret = eval_tree_cd(lexer_instance.ast[i].left, lexer_instance);
+ ret = eval_tree_cd(lexer_instance.ast[i].left, lexer_instance, false);
}
if (lexer_instance.ast[i].right != string::npos)
@@ -157,7 +233,7 @@ int eval_tree_cd(size_t i, const T_lexer &lexer_instance)
if (lexer_instance.ast[i].token_type == LOGIC_AND && ret != 0) return ret;
if (lexer_instance.ast[i].token_type == LOGIC_OR && ret == 0) return ret;
- ret = eval_tree_cd(lexer_instance.ast[i].right, lexer_instance);
+ ret = eval_tree_cd(lexer_instance.ast[i].right, lexer_instance, false);
}
return ret;
}
@@ -190,7 +266,7 @@ void eval(char *cmdline)
return;
}
- eval_tree_cd(0, lexer_instance);
+ eval_tree_cd(0, lexer_instance, false);
return;
}