~emersion/mrsh

6d5e003446292f20c769c2a32674f9f2f4b41389 — Simon Ser 1 year, 1 month ago 49bb38d
Handle stopped jobs
M include/shell/job.h => include/shell/job.h +1 -0
@@ 24,6 24,7 @@ struct mrsh_job *job_create(struct mrsh_state *state, pid_t pgid);
void job_destroy(struct mrsh_job *job);
void job_add_process(struct mrsh_job *job, struct process *proc);
bool job_terminated(struct mrsh_job *job);
bool job_stopped(struct mrsh_job *job);
void job_set_foreground(struct mrsh_job *job, bool foreground);

bool init_job_child_process(struct mrsh_state *state);

M include/shell/process.h => include/shell/process.h +1 -0
@@ 15,6 15,7 @@
struct process {
	pid_t pid;
	struct mrsh_state *state;
	bool stopped;
	bool terminated;
	int stat;
};

M include/shell/task.h => include/shell/task.h +4 -0
@@ 12,6 12,10 @@
 * A fatal error occured, the task should be destroyed.
 */
#define TASK_STATUS_ERROR -2
/**
 * The task has been stopped and the job has been put in the background.
 */
#define TASK_STATUS_STOPPED -3

struct task_interface;


M shell/job.c => shell/job.c +10 -0
@@ 127,6 127,16 @@ bool job_terminated(struct mrsh_job *job) {
	return true;
}

bool job_stopped(struct mrsh_job *job) {
	for (size_t j = 0; j < job->processes.len; ++j) {
		struct process *proc = job->processes.data[j];
		if (!proc->terminated && !proc->stopped) {
			return false;
		}
	}
	return true;
}

void job_set_foreground(struct mrsh_job *job, bool foreground) {
	struct mrsh_state *state = job->state;


M shell/process.c => shell/process.c +8 -2
@@ 5,6 5,7 @@
#include <string.h>
#include <sys/wait.h>
#include "shell/process.h"
#include "shell/task.h"

struct process *process_create(struct mrsh_state *state, pid_t pid) {
	struct process *proc = calloc(1, sizeof(struct process));


@@ 33,9 34,12 @@ void process_destroy(struct process *proc) {
}

int process_poll(struct process *proc) {
	if (!proc->terminated) {
		return -1;
	if (proc->stopped) {
		return TASK_STATUS_STOPPED;
	} else if (!proc->terminated) {
		return TASK_STATUS_WAIT;
	}

	if (WIFEXITED(proc->stat)) {
		return WEXITSTATUS(proc->stat);
	} else if (WIFSIGNALED(proc->stat)) {


@@ 62,6 66,8 @@ void update_process(struct mrsh_state *state, pid_t pid, int stat) {
	if (WIFEXITED(stat) || WIFSIGNALED(stat)) {
		proc->terminated = true;
		proc->stat = stat;
	} else if (WIFSTOPPED(stat)) {
		proc->stopped = true;
	} else {
		assert(false);
	}

M shell/task/task.c => shell/task/task.c +10 -4
@@ 47,10 47,16 @@ int task_run(struct task *task, struct context *ctx) {
	while (true) {
		int ret = task_poll(task, ctx);
		if (ret != TASK_STATUS_WAIT) {
			ctx->state->last_status = ret;
			if (ret != 0
			int status = ret;
			if (ret == TASK_STATUS_STOPPED) {
				status = 148;
			}
			if (ret != TASK_STATUS_ERROR) {
				ctx->state->last_status = status;
				if (status != 0
					&& (ctx->state->options & MRSH_OPT_ERREXIT)) {
				ctx->state->exit = ret;
					ctx->state->exit = status;
				}
			}

			if (ctx->state->foreground_job != NULL) {


@@ 66,7 72,7 @@ int task_run(struct task *task, struct context *ctx) {

		errno = 0;
		int stat;
		pid_t pid = waitpid(-1, &stat, 0);
		pid_t pid = waitpid(-1, &stat, WUNTRACED);
		if (pid == -1) {
			if (errno == EINTR) {
				continue;