Fix the code for establishing a controlling terminal.
-Erik
This commit is contained in:
74
hush.c
74
hush.c
@@ -251,7 +251,7 @@ static const char *cwd;
|
|||||||
static struct pipe *job_list;
|
static struct pipe *job_list;
|
||||||
static unsigned int last_bg_pid;
|
static unsigned int last_bg_pid;
|
||||||
static unsigned int last_jobid;
|
static unsigned int last_jobid;
|
||||||
static unsigned int ctty;
|
static unsigned int shell_terminal;
|
||||||
static char *PS1;
|
static char *PS1;
|
||||||
static char *PS2;
|
static char *PS2;
|
||||||
struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
|
struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
|
||||||
@@ -570,11 +570,9 @@ static int builtin_fg_bg(struct child_prog *child)
|
|||||||
|
|
||||||
if (*child->argv[0] == 'f') {
|
if (*child->argv[0] == 'f') {
|
||||||
/* Make this job the foreground job */
|
/* Make this job the foreground job */
|
||||||
signal(SIGTTOU, SIG_IGN);
|
|
||||||
/* suppress messages when run from /linuxrc mag@sysgo.de */
|
/* suppress messages when run from /linuxrc mag@sysgo.de */
|
||||||
if (tcsetpgrp(ctty, pi->pgrp) && errno != ENOTTY)
|
if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY)
|
||||||
perror_msg("tcsetpgrp-1");
|
perror_msg("tcsetpgrp-1");
|
||||||
signal(SIGTTOU, SIG_DFL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restart the processes in the job */
|
/* Restart the processes in the job */
|
||||||
@@ -1263,7 +1261,7 @@ static int checkjobs(struct pipe* fg_pipe)
|
|||||||
perror_msg("waitpid");
|
perror_msg("waitpid");
|
||||||
|
|
||||||
/* move the shell to the foreground */
|
/* move the shell to the foreground */
|
||||||
if (interactive && tcsetpgrp(ctty, getpgid(0)))
|
if (interactive && tcsetpgrp(shell_terminal, getpgid(0)))
|
||||||
perror_msg("tcsetpgrp-2");
|
perror_msg("tcsetpgrp-2");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1271,24 +1269,24 @@ static int checkjobs(struct pipe* fg_pipe)
|
|||||||
/* Figure out our controlling tty, checking in order stderr,
|
/* Figure out our controlling tty, checking in order stderr,
|
||||||
* stdin, and stdout. If check_pgrp is set, also check that
|
* stdin, and stdout. If check_pgrp is set, also check that
|
||||||
* we belong to the foreground process group associated with
|
* we belong to the foreground process group associated with
|
||||||
* that tty. The value of ctty is needed in order to call
|
* that tty. The value of shell_terminal is needed in order to call
|
||||||
* tcsetpgrp(ctty, ...); */
|
* tcsetpgrp(shell_terminal, ...); */
|
||||||
void controlling_tty(int check_pgrp)
|
void controlling_tty(int check_pgrp)
|
||||||
{
|
{
|
||||||
pid_t curpgrp;
|
pid_t curpgrp;
|
||||||
|
|
||||||
if ((curpgrp = tcgetpgrp(ctty = 2)) < 0
|
if ((curpgrp = tcgetpgrp(shell_terminal = 2)) < 0
|
||||||
&& (curpgrp = tcgetpgrp(ctty = 0)) < 0
|
&& (curpgrp = tcgetpgrp(shell_terminal = 0)) < 0
|
||||||
&& (curpgrp = tcgetpgrp(ctty = 1)) < 0)
|
&& (curpgrp = tcgetpgrp(shell_terminal = 1)) < 0)
|
||||||
goto ctty_error;
|
goto shell_terminal_error;
|
||||||
|
|
||||||
if (check_pgrp && curpgrp != getpgid(0))
|
if (check_pgrp && curpgrp != getpgid(0))
|
||||||
goto ctty_error;
|
goto shell_terminal_error;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ctty_error:
|
shell_terminal_error:
|
||||||
ctty = -1;
|
shell_terminal = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1402,7 +1400,13 @@ static int run_pipe_real(struct pipe *pi)
|
|||||||
|
|
||||||
/* XXX test for failed fork()? */
|
/* XXX test for failed fork()? */
|
||||||
if (!(child->pid = fork())) {
|
if (!(child->pid = fork())) {
|
||||||
|
/* Set the handling for job control signals back to the default. */
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
signal(SIGQUIT, SIG_DFL);
|
||||||
|
signal(SIGTSTP, SIG_DFL);
|
||||||
|
signal(SIGTTIN, SIG_DFL);
|
||||||
signal(SIGTTOU, SIG_DFL);
|
signal(SIGTTOU, SIG_DFL);
|
||||||
|
signal(SIGCHLD, SIG_DFL);
|
||||||
|
|
||||||
close_all();
|
close_all();
|
||||||
|
|
||||||
@@ -1429,9 +1433,7 @@ static int run_pipe_real(struct pipe *pi)
|
|||||||
pi->pgrp = getpid();
|
pi->pgrp = getpid();
|
||||||
}
|
}
|
||||||
if (setpgid(0, pi->pgrp) == 0) {
|
if (setpgid(0, pi->pgrp) == 0) {
|
||||||
signal(SIGTTOU, SIG_IGN);
|
|
||||||
tcsetpgrp(2, pi->pgrp);
|
tcsetpgrp(2, pi->pgrp);
|
||||||
signal(SIGTTOU, SIG_DFL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1489,11 +1491,11 @@ static int run_list_real(struct pipe *pi)
|
|||||||
} else {
|
} else {
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
/* move the new process group into the foreground */
|
/* move the new process group into the foreground */
|
||||||
if (tcsetpgrp(ctty, pi->pgrp) && errno != ENOTTY)
|
if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY)
|
||||||
perror_msg("tcsetpgrp-3");
|
perror_msg("tcsetpgrp-3");
|
||||||
rcode = checkjobs(pi);
|
rcode = checkjobs(pi);
|
||||||
/* move the shell to the foreground */
|
/* move the shell to the foreground */
|
||||||
if (tcsetpgrp(ctty, getpgid(0)) && errno != ENOTTY)
|
if (tcsetpgrp(shell_terminal, getpgid(0)) && errno != ENOTTY)
|
||||||
perror_msg("tcsetpgrp-4");
|
perror_msg("tcsetpgrp-4");
|
||||||
} else {
|
} else {
|
||||||
rcode = checkjobs(pi);
|
rcode = checkjobs(pi);
|
||||||
@@ -2534,21 +2536,33 @@ static void sigchld_handler(int sig)
|
|||||||
signal(SIGCHLD, sigchld_handler);
|
signal(SIGCHLD, sigchld_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure we have a controlling tty. If we get started under a job
|
||||||
|
* aware app (like bash for example), make sure we are now in charge so
|
||||||
|
* we don't fight over who gets the foreground */
|
||||||
static void setup_job_control()
|
static void setup_job_control()
|
||||||
{
|
{
|
||||||
/* If we get started under a job aware app (like bash
|
static pid_t shell_pgrp;
|
||||||
* for example), make sure we are now in charge so we
|
/* Loop until we are in the foreground. */
|
||||||
* don't fight over who gets the foreground */
|
while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ()))
|
||||||
/* don't pay any attention to this signal; it just confuses
|
kill (- shell_pgrp, SIGTTIN);
|
||||||
things and isn't really meant for shells anyway */
|
|
||||||
setpgrp();
|
|
||||||
controlling_tty(0);
|
|
||||||
signal(SIGTTOU, SIG_IGN);
|
|
||||||
setpgid(0, getpid());
|
|
||||||
tcsetpgrp(ctty, getpid());
|
|
||||||
signal(SIGCHLD, sigchld_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Ignore interactive and job-control signals. */
|
||||||
|
signal(SIGINT, SIG_IGN);
|
||||||
|
signal(SIGQUIT, SIG_IGN);
|
||||||
|
signal(SIGTSTP, SIG_IGN);
|
||||||
|
signal(SIGTTIN, SIG_IGN);
|
||||||
|
signal(SIGTTOU, SIG_IGN);
|
||||||
|
signal(SIGCHLD, sigchld_handler);
|
||||||
|
|
||||||
|
/* Put ourselves in our own process group. */
|
||||||
|
shell_pgrp = getpid ();
|
||||||
|
if (setpgid (shell_pgrp, shell_pgrp) < 0) {
|
||||||
|
perror_msg_and_die("Couldn't put the shell in its own process group");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grab control of the terminal. */
|
||||||
|
tcsetpgrp(shell_terminal, shell_pgrp);
|
||||||
|
}
|
||||||
|
|
||||||
int shell_main(int argc, char **argv)
|
int shell_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
74
shell/hush.c
74
shell/hush.c
@@ -251,7 +251,7 @@ static const char *cwd;
|
|||||||
static struct pipe *job_list;
|
static struct pipe *job_list;
|
||||||
static unsigned int last_bg_pid;
|
static unsigned int last_bg_pid;
|
||||||
static unsigned int last_jobid;
|
static unsigned int last_jobid;
|
||||||
static unsigned int ctty;
|
static unsigned int shell_terminal;
|
||||||
static char *PS1;
|
static char *PS1;
|
||||||
static char *PS2;
|
static char *PS2;
|
||||||
struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
|
struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
|
||||||
@@ -570,11 +570,9 @@ static int builtin_fg_bg(struct child_prog *child)
|
|||||||
|
|
||||||
if (*child->argv[0] == 'f') {
|
if (*child->argv[0] == 'f') {
|
||||||
/* Make this job the foreground job */
|
/* Make this job the foreground job */
|
||||||
signal(SIGTTOU, SIG_IGN);
|
|
||||||
/* suppress messages when run from /linuxrc mag@sysgo.de */
|
/* suppress messages when run from /linuxrc mag@sysgo.de */
|
||||||
if (tcsetpgrp(ctty, pi->pgrp) && errno != ENOTTY)
|
if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY)
|
||||||
perror_msg("tcsetpgrp-1");
|
perror_msg("tcsetpgrp-1");
|
||||||
signal(SIGTTOU, SIG_DFL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restart the processes in the job */
|
/* Restart the processes in the job */
|
||||||
@@ -1263,7 +1261,7 @@ static int checkjobs(struct pipe* fg_pipe)
|
|||||||
perror_msg("waitpid");
|
perror_msg("waitpid");
|
||||||
|
|
||||||
/* move the shell to the foreground */
|
/* move the shell to the foreground */
|
||||||
if (interactive && tcsetpgrp(ctty, getpgid(0)))
|
if (interactive && tcsetpgrp(shell_terminal, getpgid(0)))
|
||||||
perror_msg("tcsetpgrp-2");
|
perror_msg("tcsetpgrp-2");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1271,24 +1269,24 @@ static int checkjobs(struct pipe* fg_pipe)
|
|||||||
/* Figure out our controlling tty, checking in order stderr,
|
/* Figure out our controlling tty, checking in order stderr,
|
||||||
* stdin, and stdout. If check_pgrp is set, also check that
|
* stdin, and stdout. If check_pgrp is set, also check that
|
||||||
* we belong to the foreground process group associated with
|
* we belong to the foreground process group associated with
|
||||||
* that tty. The value of ctty is needed in order to call
|
* that tty. The value of shell_terminal is needed in order to call
|
||||||
* tcsetpgrp(ctty, ...); */
|
* tcsetpgrp(shell_terminal, ...); */
|
||||||
void controlling_tty(int check_pgrp)
|
void controlling_tty(int check_pgrp)
|
||||||
{
|
{
|
||||||
pid_t curpgrp;
|
pid_t curpgrp;
|
||||||
|
|
||||||
if ((curpgrp = tcgetpgrp(ctty = 2)) < 0
|
if ((curpgrp = tcgetpgrp(shell_terminal = 2)) < 0
|
||||||
&& (curpgrp = tcgetpgrp(ctty = 0)) < 0
|
&& (curpgrp = tcgetpgrp(shell_terminal = 0)) < 0
|
||||||
&& (curpgrp = tcgetpgrp(ctty = 1)) < 0)
|
&& (curpgrp = tcgetpgrp(shell_terminal = 1)) < 0)
|
||||||
goto ctty_error;
|
goto shell_terminal_error;
|
||||||
|
|
||||||
if (check_pgrp && curpgrp != getpgid(0))
|
if (check_pgrp && curpgrp != getpgid(0))
|
||||||
goto ctty_error;
|
goto shell_terminal_error;
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ctty_error:
|
shell_terminal_error:
|
||||||
ctty = -1;
|
shell_terminal = -1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1402,7 +1400,13 @@ static int run_pipe_real(struct pipe *pi)
|
|||||||
|
|
||||||
/* XXX test for failed fork()? */
|
/* XXX test for failed fork()? */
|
||||||
if (!(child->pid = fork())) {
|
if (!(child->pid = fork())) {
|
||||||
|
/* Set the handling for job control signals back to the default. */
|
||||||
|
signal(SIGINT, SIG_DFL);
|
||||||
|
signal(SIGQUIT, SIG_DFL);
|
||||||
|
signal(SIGTSTP, SIG_DFL);
|
||||||
|
signal(SIGTTIN, SIG_DFL);
|
||||||
signal(SIGTTOU, SIG_DFL);
|
signal(SIGTTOU, SIG_DFL);
|
||||||
|
signal(SIGCHLD, SIG_DFL);
|
||||||
|
|
||||||
close_all();
|
close_all();
|
||||||
|
|
||||||
@@ -1429,9 +1433,7 @@ static int run_pipe_real(struct pipe *pi)
|
|||||||
pi->pgrp = getpid();
|
pi->pgrp = getpid();
|
||||||
}
|
}
|
||||||
if (setpgid(0, pi->pgrp) == 0) {
|
if (setpgid(0, pi->pgrp) == 0) {
|
||||||
signal(SIGTTOU, SIG_IGN);
|
|
||||||
tcsetpgrp(2, pi->pgrp);
|
tcsetpgrp(2, pi->pgrp);
|
||||||
signal(SIGTTOU, SIG_DFL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1489,11 +1491,11 @@ static int run_list_real(struct pipe *pi)
|
|||||||
} else {
|
} else {
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
/* move the new process group into the foreground */
|
/* move the new process group into the foreground */
|
||||||
if (tcsetpgrp(ctty, pi->pgrp) && errno != ENOTTY)
|
if (tcsetpgrp(shell_terminal, pi->pgrp) && errno != ENOTTY)
|
||||||
perror_msg("tcsetpgrp-3");
|
perror_msg("tcsetpgrp-3");
|
||||||
rcode = checkjobs(pi);
|
rcode = checkjobs(pi);
|
||||||
/* move the shell to the foreground */
|
/* move the shell to the foreground */
|
||||||
if (tcsetpgrp(ctty, getpgid(0)) && errno != ENOTTY)
|
if (tcsetpgrp(shell_terminal, getpgid(0)) && errno != ENOTTY)
|
||||||
perror_msg("tcsetpgrp-4");
|
perror_msg("tcsetpgrp-4");
|
||||||
} else {
|
} else {
|
||||||
rcode = checkjobs(pi);
|
rcode = checkjobs(pi);
|
||||||
@@ -2534,21 +2536,33 @@ static void sigchld_handler(int sig)
|
|||||||
signal(SIGCHLD, sigchld_handler);
|
signal(SIGCHLD, sigchld_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make sure we have a controlling tty. If we get started under a job
|
||||||
|
* aware app (like bash for example), make sure we are now in charge so
|
||||||
|
* we don't fight over who gets the foreground */
|
||||||
static void setup_job_control()
|
static void setup_job_control()
|
||||||
{
|
{
|
||||||
/* If we get started under a job aware app (like bash
|
static pid_t shell_pgrp;
|
||||||
* for example), make sure we are now in charge so we
|
/* Loop until we are in the foreground. */
|
||||||
* don't fight over who gets the foreground */
|
while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ()))
|
||||||
/* don't pay any attention to this signal; it just confuses
|
kill (- shell_pgrp, SIGTTIN);
|
||||||
things and isn't really meant for shells anyway */
|
|
||||||
setpgrp();
|
|
||||||
controlling_tty(0);
|
|
||||||
signal(SIGTTOU, SIG_IGN);
|
|
||||||
setpgid(0, getpid());
|
|
||||||
tcsetpgrp(ctty, getpid());
|
|
||||||
signal(SIGCHLD, sigchld_handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* Ignore interactive and job-control signals. */
|
||||||
|
signal(SIGINT, SIG_IGN);
|
||||||
|
signal(SIGQUIT, SIG_IGN);
|
||||||
|
signal(SIGTSTP, SIG_IGN);
|
||||||
|
signal(SIGTTIN, SIG_IGN);
|
||||||
|
signal(SIGTTOU, SIG_IGN);
|
||||||
|
signal(SIGCHLD, sigchld_handler);
|
||||||
|
|
||||||
|
/* Put ourselves in our own process group. */
|
||||||
|
shell_pgrp = getpid ();
|
||||||
|
if (setpgid (shell_pgrp, shell_pgrp) < 0) {
|
||||||
|
perror_msg_and_die("Couldn't put the shell in its own process group");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Grab control of the terminal. */
|
||||||
|
tcsetpgrp(shell_terminal, shell_pgrp);
|
||||||
|
}
|
||||||
|
|
||||||
int shell_main(int argc, char **argv)
|
int shell_main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user