Merge branch 'job-control-fix'
This commit is contained in:
commit
d5c830d347
25 changed files with 105 additions and 72 deletions
|
|
@ -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\
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
11
42sh/src/exec/process_setsig.c
Normal file
11
42sh/src/exec/process_setsig.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,5 +15,5 @@
|
|||
void sigint_handler(int signo)
|
||||
{
|
||||
(void)signo;
|
||||
DG("got SIGINT in process %i", getpid());
|
||||
DG("pid:%i got SIGINT", getpid());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,5 +15,5 @@
|
|||
void sigttin_handler(int signo)
|
||||
{
|
||||
(void)signo;
|
||||
DG("got SIGTTIN");
|
||||
DG("got SIGTTIN, pid=%i, pgid=%i", getpid(), getpgrp());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,5 +15,5 @@
|
|||
void sigttou_handler(int signo)
|
||||
{
|
||||
(void)signo;
|
||||
DG("got SIGTTOU");
|
||||
DG("got SIGTTOU, pid=%i, pgid=%i", getpid(), getpgid(getpid()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
Loading…
Reference in a new issue