static struct pipe *job_list;
static unsigned int last_bg_pid;
static unsigned int last_jobid;
-static unsigned int ctty;
+static unsigned int shell_terminal;
static char *PS1;
static char *PS2;
struct variables shell_ver = { "HUSH_VERSION", "0.01", 1, 1, 0 };
static char *get_local_var(const char *var);
static void unset_local_var(const char *name);
static int set_local_var(const char *s, int flg_export);
-static void sigchld_handler(int sig);
/* Table of built-in functions. They can be forked or not, depending on
* context: within pipes, they fork. As simple commands, they do not.
}
if (*child->argv[0] == 'f') {
- /* Make this job the foreground job */
- signal(SIGTTOU, SIG_IGN);
- /* suppress messages when run from /linuxrc mag@sysgo.de */
- if (tcsetpgrp(ctty, pi->pgrp) && errno != ENOTTY)
- perror_msg("tcsetpgrp-1");
- signal(SIGTTOU, SIG_DFL);
+ /* Put the job into the foreground. */
+ tcsetpgrp(shell_terminal, pi->pgrp);
}
/* Restart the processes in the job */
for (i = 0; i < pi->num_progs; i++)
pi->progs[i].is_stopped = 0;
- kill(-pi->pgrp, SIGCONT);
+ if ( (i=kill(- pi->pgrp, SIGCONT)) < 0) {
+ if (i == ESRCH) {
+ remove_bg_job(pi);
+ } else {
+ perror_msg("kill (SIGCONT)");
+ }
+ }
pi->stopped_progs = 0;
return EXIT_SUCCESS;
*prompt_str = PS2;
}
#else
- *prompt_str = (promptmode==0)? PS1 : PS2;
+ *prompt_str = (promptmode==1)? PS1 : PS2;
#endif
debug_printf("result %s\n",*prompt_str);
}
prev_pipe = prev_pipe->next;
prev_pipe->next = pi->next;
}
+ if (job_list)
+ last_jobid = job_list->jobid;
+ else
+ last_jobid = 0;
+
pi->stopped_progs = 0;
free_pipe(pi, 0);
free(pi);
perror_msg("waitpid");
/* move the shell to the foreground */
- if (interactive && tcsetpgrp(ctty, getpgid(0)))
- perror_msg("tcsetpgrp-2");
+ //if (interactive && tcsetpgrp(shell_terminal, getpgid(0)))
+ // perror_msg("tcsetpgrp-2");
return -1;
}
/* Figure out our controlling tty, checking in order stderr,
* stdin, and stdout. If check_pgrp is set, also check that
* we belong to the foreground process group associated with
- * that tty. The value of ctty is needed in order to call
- * tcsetpgrp(ctty, ...); */
+ * that tty. The value of shell_terminal is needed in order to call
+ * tcsetpgrp(shell_terminal, ...); */
void controlling_tty(int check_pgrp)
{
pid_t curpgrp;
- if ((curpgrp = tcgetpgrp(ctty = 2)) < 0
- && (curpgrp = tcgetpgrp(ctty = 0)) < 0
- && (curpgrp = tcgetpgrp(ctty = 1)) < 0)
- goto ctty_error;
+ if ((curpgrp = tcgetpgrp(shell_terminal = 2)) < 0
+ && (curpgrp = tcgetpgrp(shell_terminal = 0)) < 0
+ && (curpgrp = tcgetpgrp(shell_terminal = 1)) < 0)
+ goto shell_terminal_error;
if (check_pgrp && curpgrp != getpgid(0))
- goto ctty_error;
+ goto shell_terminal_error;
return;
-ctty_error:
- ctty = -1;
+shell_terminal_error:
+ shell_terminal = -1;
return;
}
/* XXX test for failed 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(SIGCHLD, SIG_DFL);
close_all();
pi->pgrp = getpid();
}
if (setpgid(0, pi->pgrp) == 0) {
- signal(SIGTTOU, SIG_IGN);
tcsetpgrp(2, pi->pgrp);
- signal(SIGTTOU, SIG_DFL);
}
}
} else {
if (interactive) {
/* 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");
rcode = checkjobs(pi);
/* 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");
} else {
rcode = checkjobs(pi);
if ( (rcode==EXIT_SUCCESS && pi->followup==PIPE_OR) ||
(rcode!=EXIT_SUCCESS && pi->followup==PIPE_AND) )
skip_more_in_this_rmode=rmode;
+ checkjobs(NULL);
}
- checkjobs(NULL);
return rcode;
}
return rcode;
}
-static void sigchld_handler(int sig)
-{
- checkjobs(NULL);
- 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()
{
- /* 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 */
- /* don't pay any attention to this signal; it just confuses
- things and isn't really meant for shells anyway */
- setpgrp();
- controlling_tty(0);
+ static pid_t shell_pgrp;
+ /* Loop until we are in the foreground. */
+ while (tcgetpgrp (shell_terminal) != (shell_pgrp = getpgrp ()))
+ kill (- shell_pgrp, SIGTTIN);
+
+ /* 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);
- setpgid(0, getpid());
- tcsetpgrp(ctty, getpid());
- signal(SIGCHLD, sigchld_handler);
-}
+ signal(SIGCHLD, SIG_IGN);
+ /* Put ourselves in our own process group. */
+ setsid();
+ shell_pgrp = getpid ();
+ setpgid (shell_pgrp, shell_pgrp);
+
+ /* Grab control of the terminal. */
+ tcsetpgrp(shell_terminal, shell_pgrp);
+}
int shell_main(int argc, char **argv)
{
if (argv[0] && argv[0][0] == '-') {
debug_printf("\nsourcing /etc/profile\n");
- input = xfopen("/etc/profile", "r");
- mark_open(fileno(input));
- parse_file_outer(input);
- mark_closed(fileno(input));
- fclose(input);
+ if ((input = fopen("/etc/profile", "r")) != NULL) {
+ mark_open(fileno(input));
+ parse_file_outer(input);
+ mark_closed(fileno(input));
+ fclose(input);
+ }
}
input=stdin;