aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/eval.h21
-rw-r--r--include/ground.h3
-rw-r--r--include/handler.h11
-rw-r--r--src/eval.cc29
-rw-r--r--src/ground.cc8
-rw-r--r--src/handler.cc26
-rw-r--r--src/init.cc3
7 files changed, 68 insertions, 33 deletions
diff --git a/include/eval.h b/include/eval.h
index 919d03f..5e8a1c7 100644
--- a/include/eval.h
+++ b/include/eval.h
@@ -1,25 +1,6 @@
#pragma once
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <iostream>
-#include <vector>
-#include <string>
-
-#include "global.h"
-#include "util/io.h"
-#include "command/builtin.h"
-#include "job.h"
-#include "ground.h"
-#include "parse.h"
-#include "path.h"
+#include "all.h"
namespace ov4
{
diff --git a/include/ground.h b/include/ground.h
index d57f085..a1985eb 100644
--- a/include/ground.h
+++ b/include/ground.h
@@ -13,6 +13,9 @@
namespace ov4
{
+extern pid_t shell_pgid;
+extern int tty_fd;
+
void waitfg(pid_t pid);
void do_bgfg(char **argv);
diff --git a/include/handler.h b/include/handler.h
index 225fc93..100c548 100644
--- a/include/handler.h
+++ b/include/handler.h
@@ -1,7 +1,5 @@
#pragma once
-#include "global.h"
-
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -12,20 +10,25 @@
#include <sys/wait.h>
#include <errno.h>
-#include "util/io.h"
-#include "job.h"
+#include "all.h"
namespace ov4
{
typedef void handler_t(int);
+extern sigset_t
+ block_sig_TTOU,
+ block_job,
+ block_io;
+
void signal_init();
handler_t *Signal(int signum, handler_t *handler);
void sigchld_handler(int sig);
void sigint_handler(int sig);
void sigtstp_handler(int sig);
void sigquit_handler(int sig);
+
int block_all(sigset_t *prev);
int block_handler(sigset_t *prev);
diff --git a/src/eval.cc b/src/eval.cc
index 8785dd6..09d1196 100644
--- a/src/eval.cc
+++ b/src/eval.cc
@@ -1,5 +1,18 @@
#include "eval.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <iostream>
+#include <vector>
+#include <string>
+
using namespace std;
namespace ov4
@@ -29,17 +42,29 @@ void eval(char *cmdline)
if (argv[0] == nullptr) return;
if (exe_bultin_command(argv)) return;
+ // 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);
- pid_t pid = fork();
string cmd = find_cmd(argv[0]);
const char* cmd_c = cmd.c_str();
+
+ shell_pgid = getpgid(0);
+ pid_t pid = fork();
+
if (pid == 0) // child
{
- sigprocmask(SIG_SETMASK, &prev, nullptr);
setpgid(0, 0);
+ if (!ground) // foreground
+ tcsetpgrp(tty_fd, getpgrp());
+
+ // program inside execve may use SIGTTIN/SIGTTOU so just restore in child
+ sigprocmask(SIG_UNBLOCK, &block_io, nullptr);
+
+ sigprocmask(SIG_SETMASK, &prev, nullptr);
execve(cmd_c, argv, environ);
diff --git a/src/ground.cc b/src/ground.cc
index 54a333f..265a22d 100644
--- a/src/ground.cc
+++ b/src/ground.cc
@@ -5,6 +5,9 @@ using namespace std;
namespace ov4
{
+pid_t shell_pgid;
+int tty_fd;
+
/*
* waitfg - Block until process pid is no longer the foreground process
*/
@@ -17,6 +20,11 @@ void waitfg(pid_t pid)
LOG << "waiting for pid "<< fgpid(jobs) << endl;
while (fgpid(jobs) != 0)
sigsuspend(&prev_with_sigchld_unblocked);
+
+ // set shell to foreground again
+ tcsetpgrp(tty_fd, shell_pgid);
+ sigprocmask(SIG_BLOCK, &block_io, nullptr);
+
LOG << "finished fg " << endl;
return;
}
diff --git a/src/handler.cc b/src/handler.cc
index b6399c2..4fa3e2f 100644
--- a/src/handler.cc
+++ b/src/handler.cc
@@ -4,17 +4,29 @@ namespace ov4
{
extern char **environ;
-sigset_t BLOCK_HANDLER;
+
+sigset_t
+ block_sig_TTOU,
+ block_job,
+ block_io;
void signal_init()
{
/* Install the signal handlers */
- sigemptyset(&BLOCK_HANDLER);
- sigaddset(&BLOCK_HANDLER, SIGINT);
- sigaddset(&BLOCK_HANDLER, SIGTSTP);
- sigaddset(&BLOCK_HANDLER, SIGCHLD);
-
+ sigemptyset(&block_job);
+ sigemptyset(&block_sig_TTOU);
+ sigemptyset(&block_io);
+
+ sigaddset(&block_job, SIGINT);
+ sigaddset(&block_job, SIGTSTP);
+ sigaddset(&block_job, SIGCHLD);
+
+ sigaddset(&block_sig_TTOU, SIGTTOU);
+
+ sigaddset(&block_io, SIGTTOU);
+ sigaddset(&block_io, SIGTTIN);
+
Signal(SIGINT, sigint_handler); /* ctrl-c */
Signal(SIGTSTP, sigtstp_handler); /* ctrl-z */
Signal(SIGCHLD, sigchld_handler); /* Terminated or stopped child */
@@ -161,7 +173,7 @@ int block_all(sigset_t *prev)
int block_handler(sigset_t *prev)
{
- return sigprocmask(SIG_BLOCK, &BLOCK_HANDLER, prev);
+ return sigprocmask(SIG_BLOCK, &block_job, prev);
}
void sigquit_handler(int sig)
diff --git a/src/init.cc b/src/init.cc
index 5f6e325..a38aec4 100644
--- a/src/init.cc
+++ b/src/init.cc
@@ -1,5 +1,7 @@
#include "init.h"
+#include <fcntl.h>
+
using namespace std;
namespace ov4
@@ -15,6 +17,7 @@ Published under GNU AFFERO GENERAL PUBLIC LICENSE (AGPL) Version 3." << endl;
signal_init();
+ tty_fd = open("/dev/tty", O_RDWR);
}