Merge branch 'job-control-fix'

This commit is contained in:
Jack Halford 2017-02-02 01:21:16 +01:00
commit d5c830d347
25 changed files with 105 additions and 72 deletions

View file

@ -57,6 +57,7 @@ exec/process_redirect.c\
exec/process_reset.c\
exec/process_setexec.c\
exec/process_setgroup.c\
exec/process_setsig.c\
exec/set_exitstatus.c\
glob/dir_glob.c\
glob/expand_brace.c\

View file

@ -33,6 +33,7 @@
# define IS_PIPESTART(a) (a & PROCESS_PIPESTART)
# define IS_PIPEEND(a) (a & PROCESS_PIPEEND)
# define IS_PIPESINGLE(a) (a & (PROCESS_PIPESTART | PROCESS_PIPEEND))
# include "libft.h"
# include "types.h"
@ -46,6 +47,7 @@ struct s_process
pid_t pid;
int fdin;
int fdout;
int toclose;
int status;
t_flag attributes;
};
@ -83,8 +85,9 @@ int exec_command(t_btree **ast);
int launch_process(t_process *p);
int process_setexec(t_type type, t_process *p);
int process_setgroup(t_process *p);
int process_setgroup(t_process *p, pid_t pid);
int process_redirect(t_process *p);
void process_setsig(void);
void process_free(void *content, size_t content_size);
void process_reset(void);
@ -93,7 +96,7 @@ void fd_reset(void);
char *ft_findexec(char *path, char *file);
void set_exitstatus(int status);
void set_exitstatus(int status, int override);
void ast_free(void *data, size_t content_size);

View file

@ -45,7 +45,7 @@ struct s_jobc
# include "exec.h"
t_process *job_getprocess(pid_t pid);
t_list *job_getprocess(pid_t pid);
int job_addprocess(t_process *p);
void job_update_id(void);
void job_update_rank(void);

View file

@ -57,7 +57,7 @@ int exec_command(t_btree **ast)
}
p->av = NULL;
p->pid = 0;
p->attributes = PROCESS_PIPESTART | PROCESS_PIPEEND;
p->attributes &= ~(PROCESS_STATE_MASK | PROCESS_TYPE_MASK);
btree_delone(ast, &ast_free);
return (0);
}

View file

@ -25,11 +25,13 @@ int exec_pipe(t_btree **ast)
DG("pipe %i->%i", fds[PIPE_WRITE], fds[PIPE_READ]);
p->fdout = fds[PIPE_WRITE];
start = IS_PIPESTART(p->attributes);
p->toclose = fds[PIPE_READ];
p->attributes &= ~PROCESS_PIPEEND;
ft_exec(&(*ast)->left);
p->attributes &= ~PROCESS_PIPESTART;
p->toclose = STDIN;
close(fds[PIPE_WRITE]);
p->fdout = STDOUT;
p->fdin = fds[PIPE_READ];

View file

@ -21,11 +21,10 @@ int launch_process(t_process *p)
if (p->attributes & PROCESS_UNKNOWN)
{
ft_dprintf(2, "{red}%s: command not found: %s{eoc}\n", SHELL_NAME, p->av[0]);
set_exitstatus(127);
return (1);
set_exitstatus(127, 1);
}
else if (p->attributes & PROCESS_BUILTIN && p->fdout == STDOUT)
set_exitstatus((*p->execf)(p->path, p->av, data_singleton()->env));
else if (p->attributes & PROCESS_BUILTIN && IS_PIPESINGLE(p->attributes))
set_exitstatus((*p->execf)(p->path, p->av, data_singleton()->env), 1);
else
{
p->attributes &= ~PROCESS_STATE_MASK;
@ -34,26 +33,26 @@ int launch_process(t_process *p)
&& access(p->path, X_OK) == -1)
{
ft_dprintf(2, "{red}%s: permission denied: %s{eoc}\n", SHELL_NAME, p->av[0]);
return (-1);
set_exitstatus(126, 1);
return (1);
}
pid = fork();
if (pid == 0)
{
process_setgroup(p);
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGTSTP, SIG_DFL);
signal(SIGTTIN, sigttin_handler);
signal(SIGTTOU, sigttou_handler);
signal(SIGCHLD, SIG_DFL);
process_setgroup(p, 0);
process_setsig();
process_redirect(p);
(*p->execf)(p->path, p->av, data_singleton()->env);
exit(42);
exit(43);
}
else if (pid > 0)
{
p->pid = pid;
else if (pid == -1)
perror("fork");
}
process_setgroup(p, pid);
return (0);
}
else if (pid == -1)
ft_dprintf(2, "{red}internal fork error{eoc}\n");
}
return (1);
}

View file

@ -14,15 +14,15 @@
int process_redirect(t_process *p)
{
if (p->toclose != STDIN)
close(p->toclose);
if (p->fdin != STDIN)
{
/* DG("redirect STDIN to %i", p->fdin); */
dup2(p->fdin, STDIN);
close(p->fdin);
}
if (p->fdout != STDOUT)
{
/* DG("redirect STDOUT to %i", p->fdout); */
dup2(p->fdout, STDOUT);
close(p->fdout);
}

View file

@ -13,23 +13,18 @@
#include "job_control.h"
#include "exec.h"
int process_setgroup(t_process *p)
int process_setgroup(t_process *p, pid_t pid)
{
t_job *job;
int pid;
t_job *j;
(void)p;
job = &data_singleton()->exec.job;
pid = getpid();
if (job->pgid == 0)
job->pgid = pid;
if (setpgid(pid, job->pgid))
DG("setpgid(%i, %i) failed", pid, job->pgid);
if (JOB_IS_FG(job->attributes))
{
signal(SIGTTOU, SIG_IGN);
tcsetpgrp(STDIN, job->pgid);
signal(SIGTTOU, SIG_DFL);
}
if (!SHELL_HAS_JOBC(data_singleton()->opts))
return (0);
j = &data_singleton()->exec.job;
if (!j->pgid)
j->pgid = pid ? pid : getpid();
setpgid(pid, j->pgid);
if (pid == 0 && JOB_IS_FG(j->attributes))
tcsetpgrp(STDIN, j->pgid);
return (0);
}

View file

@ -0,0 +1,11 @@
#include "exec.h"
void process_setsig(void)
{
/* signal(SIGINT, SIG_DFL); */
signal(SIGQUIT, SIG_DFL);
signal(SIGTSTP, SIG_DFL);
signal(SIGTTIN, SIG_DFL);
signal(SIGTTOU, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
}

View file

@ -12,11 +12,27 @@
#include "minishell.h"
void set_exitstatus(int status)
void set_exitstatus(int status, int override)
{
char *astatus;
int exitval;
astatus = ft_itoa(status);
builtin_setenv("setenv", (char*[3]){"?", astatus}, data_singleton()->env);
if (override)
exitval = status;
else
{
if (WIFEXITED(status))
exitval = WEXITSTATUS(status);
else if (WIFSIGNALED(status))
exitval = 128 + WTERMSIG(status);
else
{
DG("fail: process was not exited nor signaled.");
return ;
}
}
astatus = ft_itoa(exitval);
builtin_setenv("setenv", (char*[]){"setenv", "?", astatus, 0},
data_singleton()->env);
ft_strdel(&astatus);
}

View file

@ -18,7 +18,6 @@ void job_format_head(t_job *j)
int rank[2];
job_getrank(&rank);
DG("rank[0]=%i,rank[1]=%i", rank[0], rank[1]);
if (j->id == rank[0])
crank = '+';
else if (j->id == rank[1])

View file

@ -12,7 +12,7 @@
#include "job_control.h"
t_process *job_getprocess(pid_t pid)
t_list *job_getprocess(pid_t pid)
{
t_jobc *jobc;
t_job *j;
@ -25,7 +25,7 @@ t_process *job_getprocess(pid_t pid)
{
j = jlist->content;
if ((lst = ft_lst_find(j->first_process, &pid, &process_cmp_pid)))
return (lst->content);
return (lst);
jlist = jlist->next;
}
return (NULL);

View file

@ -24,11 +24,9 @@ void job_getrank(int (*rank)[2])
jlist = jobc->first_job;
(*rank)[0] = 0;
(*rank)[1] = 0;
DG("check 1");
while (jlist && i < 2)
{
job = jlist->content;
DG("check 2: id=%i", job->id);
if (job_is_stopped(job->id))
(*rank)[i++] = job->id;
jlist = jlist->next;

View file

@ -15,10 +15,15 @@
void job_remove(int id)
{
t_jobc *jobc;
t_job *j;
t_process *p;
jobc = &data_singleton()->jobc;
j = ft_lst_find(jobc->first_job, &id, job_cmp_id)->content;
if (job_is_completed(id))
{
p = ft_lstlast(j->first_process)->content;
set_exitstatus(p->status, 0);
if (id < data_singleton()->jobc.current_id)
data_singleton()->jobc.current_id = id;
ft_lst_delif(&jobc->first_job, &id, job_cmp_id, job_free);

View file

@ -16,5 +16,8 @@ void job_run(t_job *job, int foreground)
{
mark_job_as_running(job);
job_format(job, JOBS_OPTS_L);
foreground ? put_job_in_foreground(job, 1) : put_job_in_background(job, 1);
if (foreground)
put_job_in_foreground(job, 1);
else
put_job_in_background(job, 1);
}

View file

@ -17,8 +17,9 @@ int job_wait(int id)
pid_t pid;
int status;
if (job_is_stopped(id) || job_is_completed(id))
if (job_is_stopped(id))
return (0);
job_update_status();
pid = waitpid(WAIT_ANY, &status, WUNTRACED);
while (!process_mark_status(pid, status)
&& !job_is_completed(id)

View file

@ -14,12 +14,14 @@
int process_mark_status(pid_t pid, int status)
{
t_list *plist;
t_process *p;
if (pid > 1)
{
if ((p = job_getprocess(pid)))
if ((plist = job_getprocess(pid)))
{
p = plist->content;
p->status = status;
if (WIFSTOPPED(status))
{
@ -32,7 +34,7 @@ int process_mark_status(pid_t pid, int status)
p->attributes |= PROCESS_COMPLETED;
if (WIFSIGNALED(status))
ft_printf("{mag}%d: Terminated by signal %d.\n{eoc}",
(int)pid, WTERMSIG(p->status));
(int)pid, WTERMSIG(status));
}
return (0);
}

View file

@ -12,10 +12,10 @@
#include "job_control.h"
int put_job_in_background(t_job *job, int cont)
int put_job_in_background(t_job *j, int cont)
{
if (cont)
if (kill(-job->pgid, SIGCONT) < 0)
perror("kill (SIGCONT)");
if (kill(-j->pgid, SIGCONT) < 0)
DG("kill(SIGCONT) failed");
return (0);
}

View file

@ -12,27 +12,26 @@
#include "job_control.h"
int put_job_in_foreground(t_job *job, int cont)
int put_job_in_foreground(t_job *j, int cont)
{
t_jobc *jobc;
jobc = &data_singleton()->jobc;
tcsetpgrp(STDIN, j->pgid);
tcsetattr(STDIN, TCSADRAIN, &jobc->shell_tmodes);
if (cont)
{
signal(SIGTTOU, SIG_IGN);
if (tcsetpgrp(STDIN, job->pgid) == -1)
return (1);
signal(SIGTTOU, sigttou_handler);
tcsetattr(STDIN, TCSANOW, &job->tmodes);
if (kill(-job->pgid, SIGCONT) < 0)
perror("kill (SIGCONT)");
tcsetattr(STDIN, TCSADRAIN, &j->tmodes);
if (kill(-j->pgid, SIGCONT) < 0)
DG("kill(SIGCONT) failed");
}
job_wait(job->id);
job_remove(job->id);
signal(SIGTTOU, SIG_IGN);
job_wait(j->id);
job_remove(j->id);
tcsetpgrp(STDIN, jobc->shell_pgid);
signal(SIGTTOU, sigttou_handler);
tcgetattr(STDIN, &job->tmodes);
tcgetattr(STDIN, &j->tmodes);
tcsetattr(STDIN, TCSADRAIN, &jobc->shell_tmodes);
return (0);
}

View file

@ -15,5 +15,5 @@
void sigint_handler(int signo)
{
(void)signo;
DG("got SIGINT in process %i", getpid());
DG("pid:%i got SIGINT", getpid());
}

View file

@ -15,5 +15,5 @@
void sigttin_handler(int signo)
{
(void)signo;
DG("got SIGTTIN");
DG("got SIGTTIN, pid=%i, pgid=%i", getpid(), getpgrp());
}

View file

@ -15,5 +15,5 @@
void sigttou_handler(int signo)
{
(void)signo;
DG("got SIGTTOU");
DG("got SIGTTOU, pid=%i, pgid=%i", getpid(), getpgid(getpid()));
}

View file

@ -66,6 +66,7 @@ void ft_reset_stats_term(int signal)
int ft_readline(void)
{
signal(SIGWINCH, ft_reset_stats_term);
ft_save_stats_term();
if (tcsetattr(0, TCSANOW, ft_stats_term_termcaps()) == -1)
return (-1);
if (data_singleton()->line.input)

View file

@ -28,7 +28,6 @@ int shell_single_command(char *command)
return (0);
if (ft_post_tokenize(&token, command))
return (1);
DG("after post_tokenize");
token_print(token);
if (ft_parse(&ast, &token))
return (1);

View file

@ -28,9 +28,8 @@ void shell_init(int ac, char **av)
signal(SIGINT, sigint_handler);
signal(SIGQUIT, SIG_IGN);
signal(SIGTSTP, sigtstp_handler);
/* signal(SIGTSTP, SIG_IGN); */
signal(SIGTTIN, sigttin_handler);
signal(SIGTTOU, sigttou_handler);
signal(SIGTTIN, SIG_IGN);
signal(SIGTTOU, SIG_IGN);
signal(SIGCHLD, sigchld_handler);
*shell_pgid = getpid();
if (setpgid(*shell_pgid, *shell_pgid))