sh: should wait for -1 in non-interactive shells

This commit is contained in:
K. Lange 2018-10-28 18:52:44 +09:00
parent 02d5f77f10
commit 4fb42341dd

102
apps/sh.c
View File

@ -324,15 +324,11 @@ void draw_prompt(void) {
}
volatile int break_while = 0;
uint32_t child = 0;
pid_t suspended_pid = 0;
pid_t suspended_pgid = 0;
hashmap_t * job_hash = NULL;
void sig_pass(int sig) {
/* Interrupt handler */
if (child) {
kill(child, sig);
}
break_while = sig;
}
@ -759,6 +755,31 @@ static void handle_status(int ret_code) {
}
}
int wait_for_child(int pgid, char * name) {
int waitee = (shell_interactive == 1 && !is_subshell) ? -pgid : -1;
int outpid;
int ret_code = 0;
set_pgrp(pgid);
do {
outpid = waitpid(waitee, &ret_code, 0);
if (WIFSTOPPED(ret_code)) {
suspended_pgid = pgid;
if (name) {
hashmap_set(job_hash, (void*)pgid, strdup(name));
}
fprintf(stderr, "[%d] Stopped\t\t%s\n", pid, (char*)hashmap_get(job_hash, (void*)pid));
break;
} else {
suspended_pgid = 0;
hashmap_remove(job_hash, (void*)pid);
}
} while (outpid != -1 || (outpid == -1 && errno != ECHILD));
reset_pgrp();
handle_status(ret_code);
return WEXITSTATUS(ret_code);
}
int shell_exec(char * buffer, size_t size, FILE * file, char ** out_buffer) {
*out_buffer = NULL;
@ -1255,29 +1276,15 @@ _nope:
}
}
set_pgrp(pgid);
int ret_code = 0;
if (!nowait) {
child = child_pid;
int pid;
int tmp;
do {
pid = waitpid(-pgid, &tmp, 0);
if (pid == last_child) ret_code = tmp;
if (WIFSTOPPED(tmp)) {
suspended_pid = pgid;
hashmap_set(job_hash, (void*)pgid, strdup(arg_starts[0][0]));
fprintf(stderr, "[%d] Stopped\t\t%s\n", pgid, arg_starts[0][0]);
break;
}
} while (pid != -1 || (pid == -1 && errno != ECHILD));
child = 0;
}
reset_pgrp();
if (nowait) {
free(cmd);
return 0;
}
handle_status(ret_code);
return WEXITSTATUS(ret_code);
int ret = wait_for_child(pgid, arg_starts[0][0]);
free(cmd);
return ret;
}
void add_path_contents(char * path) {
@ -1603,15 +1610,11 @@ uint32_t shell_cmd_if(int argc, char * argv[]) {
}
set_pgrp(child_pid);
child = child_pid;
int pid, ret_code = 0;
do {
pid = waitpid(-1, &ret_code, 0);
} while (pid != -1 || (pid == -1 && errno != ECHILD));
child = 0;
handle_status(ret_code);
if (WEXITSTATUS(ret_code) == 0) {
@ -1630,11 +1633,9 @@ uint32_t shell_cmd_if(int argc, char * argv[]) {
run_cmd(then_args);
}
set_pgrp(child_pid);
child = child_pid;
do {
pid = waitpid(-1, &ret_code, 0);
} while (pid != -1 || (pid == -1 && errno != ECHILD));
child = 0;
reset_pgrp();
handle_status(ret_code);
return WEXITSTATUS(ret_code);
@ -1655,11 +1656,9 @@ uint32_t shell_cmd_if(int argc, char * argv[]) {
run_cmd(else_args);
}
set_pgrp(child_pid);
child = child_pid;
do {
pid = waitpid(-1, &ret_code, 0);
} while (pid != -1 || (pid == -1 && errno != ECHILD));
child = 0;
handle_status(ret_code);
return WEXITSTATUS(ret_code);
}
@ -1696,13 +1695,11 @@ uint32_t shell_cmd_while(int argc, char * argv[]) {
run_cmd(while_args);
}
set_pgrp(child_pid);
child = child_pid;
int pid, ret_code = 0;
do {
pid = waitpid(-1, &ret_code, 0);
} while (pid != -1 || (pid == -1 && errno != ECHILD));
child = 0;
handle_status(ret_code);
if (WEXITSTATUS(ret_code) == 0) {
@ -1712,11 +1709,9 @@ uint32_t shell_cmd_while(int argc, char * argv[]) {
set_pgid(0);
run_cmd(do_args);
}
child = child_pid;
do {
pid = waitpid(-1, &ret_code, 0);
} while (pid != -1 || (pid == -1 && errno != ECHILD));
child = 0;
} else {
reset_pgrp();
return WEXITSTATUS(ret_code);
@ -1826,11 +1821,9 @@ uint32_t shell_cmd_not(int argc, char * argv[]) {
run_cmd(&argv[1]);
}
set_pgrp(child_pid);
child = child_pid;
do {
pid = waitpid(-1, &ret_code, 0);
} while (pid != -1 || (pid == -1 && errno != ECHILD));
child = 0;
reset_pgrp();
handle_status(ret_code);
return !WEXITSTATUS(ret_code);
@ -1892,23 +1885,22 @@ uint32_t shell_cmd_read(int argc, char * argv[]) {
}
uint32_t shell_cmd_fg(int argc, char * argv[]) {
int ret_code;
int pid;
if (argc < 2) {
if (!suspended_pid) {
if (!suspended_pgid) {
list_t * keys = hashmap_keys(job_hash);
foreach(node, keys) {
suspended_pid = (int)node->value;
suspended_pgid = (int)node->value;
break;
}
list_free(keys);
free(keys);
if (!suspended_pid) {
if (!suspended_pgid) {
fprintf(stderr, "no current job\n");
return 1;
}
}
pid = suspended_pid;
pid = suspended_pgid;
} else {
pid = atoi(argv[1]);
}
@ -1924,25 +1916,7 @@ uint32_t shell_cmd_fg(int argc, char * argv[]) {
return 1;
}
set_pgrp(pid);
child = pid;
int outpid;
do {
outpid = waitpid(-pid, &ret_code, 0);
if (WIFSTOPPED(ret_code)) {
suspended_pid = pid;
fprintf(stderr, "[%d] Stopped\t\t%s\n", pid, (char*)hashmap_get(job_hash, (void*)pid));
break;
} else {
suspended_pid = 0;
hashmap_remove(job_hash, (void*)pid);
}
} while (outpid != -1 || (outpid == -1 && errno != ECHILD));
child = 0;
reset_pgrp();
handle_status(ret_code);
return WEXITSTATUS(ret_code);
return wait_for_child(pid, NULL);
}
uint32_t shell_cmd_jobs(int argc, char * argv[]) {