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_reset.c\
exec/process_setexec.c\ exec/process_setexec.c\
exec/process_setgroup.c\ exec/process_setgroup.c\
exec/process_setsig.c\
exec/set_exitstatus.c\ exec/set_exitstatus.c\
glob/dir_glob.c\ glob/dir_glob.c\
glob/expand_brace.c\ glob/expand_brace.c\

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -13,23 +13,18 @@
#include "job_control.h" #include "job_control.h"
#include "exec.h" #include "exec.h"
int process_setgroup(t_process *p) int process_setgroup(t_process *p, pid_t pid)
{ {
t_job *job; t_job *j;
int pid;
(void)p; (void)p;
job = &data_singleton()->exec.job; if (!SHELL_HAS_JOBC(data_singleton()->opts))
pid = getpid(); return (0);
if (job->pgid == 0) j = &data_singleton()->exec.job;
job->pgid = pid; if (!j->pgid)
if (setpgid(pid, job->pgid)) j->pgid = pid ? pid : getpid();
DG("setpgid(%i, %i) failed", pid, job->pgid); setpgid(pid, j->pgid);
if (JOB_IS_FG(job->attributes)) if (pid == 0 && JOB_IS_FG(j->attributes))
{ tcsetpgrp(STDIN, j->pgid);
signal(SIGTTOU, SIG_IGN);
tcsetpgrp(STDIN, job->pgid);
signal(SIGTTOU, SIG_DFL);
}
return (0); 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" #include "minishell.h"
void set_exitstatus(int status) void set_exitstatus(int status, int override)
{ {
char *astatus; char *astatus;
int exitval;
astatus = ft_itoa(status); if (override)
builtin_setenv("setenv", (char*[3]){"?", astatus}, data_singleton()->env); 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); ft_strdel(&astatus);
} }

View file

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

View file

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

View file

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

View file

@ -14,11 +14,16 @@
void job_remove(int id) void job_remove(int id)
{ {
t_jobc *jobc; t_jobc *jobc;
t_job *j;
t_process *p;
jobc = &data_singleton()->jobc; jobc = &data_singleton()->jobc;
j = ft_lst_find(jobc->first_job, &id, job_cmp_id)->content;
if (job_is_completed(id)) if (job_is_completed(id))
{ {
p = ft_lstlast(j->first_process)->content;
set_exitstatus(p->status, 0);
if (id < data_singleton()->jobc.current_id) if (id < data_singleton()->jobc.current_id)
data_singleton()->jobc.current_id = id; data_singleton()->jobc.current_id = id;
ft_lst_delif(&jobc->first_job, &id, job_cmp_id, job_free); 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); mark_job_as_running(job);
job_format(job, JOBS_OPTS_L); 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; pid_t pid;
int status; int status;
if (job_is_stopped(id) || job_is_completed(id)) if (job_is_stopped(id))
return (0); return (0);
job_update_status();
pid = waitpid(WAIT_ANY, &status, WUNTRACED); pid = waitpid(WAIT_ANY, &status, WUNTRACED);
while (!process_mark_status(pid, status) while (!process_mark_status(pid, status)
&& !job_is_completed(id) && !job_is_completed(id)

View file

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

View file

@ -12,10 +12,10 @@
#include "job_control.h" #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 (cont)
if (kill(-job->pgid, SIGCONT) < 0) if (kill(-j->pgid, SIGCONT) < 0)
perror("kill (SIGCONT)"); DG("kill(SIGCONT) failed");
return (0); return (0);
} }

View file

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

View file

@ -15,5 +15,5 @@
void sigint_handler(int signo) void sigint_handler(int signo)
{ {
(void)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 sigttin_handler(int signo)
{ {
(void)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 sigttou_handler(int signo)
{ {
(void)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) int ft_readline(void)
{ {
signal(SIGWINCH, ft_reset_stats_term); signal(SIGWINCH, ft_reset_stats_term);
ft_save_stats_term();
if (tcsetattr(0, TCSANOW, ft_stats_term_termcaps()) == -1) if (tcsetattr(0, TCSANOW, ft_stats_term_termcaps()) == -1)
return (-1); return (-1);
if (data_singleton()->line.input) if (data_singleton()->line.input)

View file

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

View file

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