~emersion/mrsh

49bb38d619e7ab0e06b7d0fc09169b0fd0a9f7b2 — Simon Ser 1 year, 1 month ago 2ee0faf
Introduce job_set_foreground
5 files changed, 32 insertions(+), 7 deletions(-)

M include/mrsh/shell.h
M include/shell/job.h
M shell/job.c
M shell/task/command_process.c
M shell/task/task.c
M include/mrsh/shell.h => include/mrsh/shell.h +1 -0
@@ 98,6 98,7 @@ struct mrsh_state {
	pid_t pgid;
	struct termios term_modes;
	struct mrsh_array jobs; // struct mrsh_job *
	struct mrsh_job *foreground_job;
};

void mrsh_function_destroy(struct mrsh_function *fn);

M include/shell/job.h => include/shell/job.h +3 -0
@@ 4,6 4,7 @@
#include <mrsh/array.h>
#include <stdbool.h>
#include <sys/types.h>
#include <termios.h>

struct mrsh_state;
struct process;


@@ 14,6 15,7 @@ struct process;
 */
struct mrsh_job {
	pid_t pgid;
	struct termios term_modes;
	struct mrsh_state *state;
	struct mrsh_array processes; // struct process *
};


@@ 22,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);
void job_set_foreground(struct mrsh_job *job, bool foreground);

bool init_job_child_process(struct mrsh_state *state);
void update_job(struct mrsh_state *state, pid_t pid, int stat);

M shell/job.c => shell/job.c +23 -0
@@ 94,6 94,10 @@ void job_destroy(struct mrsh_job *job) {
		return;
	}

	if (job->state->foreground_job == job) {
		job_set_foreground(job, false);
	}

	struct mrsh_state *state = job->state;
	for (size_t i = 0; i < state->jobs.len; ++i) {
		if (state->jobs.data[i] == job) {


@@ 123,6 127,25 @@ bool job_terminated(struct mrsh_job *job) {
	return true;
}

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

	if (foreground && state->foreground_job != job) {
		assert(state->foreground_job == NULL);
		tcsetpgrp(state->fd, job->pgid);
		state->foreground_job = job;
	}

	if (!foreground && state->foreground_job == job) {
		// Put the shell back in the foreground
		tcsetpgrp(state->fd, state->pgid);
		// Restore the shell’s terminal modes
		tcgetattr(state->fd, &job->term_modes);
		tcsetattr(state->fd, TCSADRAIN, &state->term_modes);
		state->foreground_job = NULL;
	}
}

bool init_job_child_process(struct mrsh_state *state) {
	if (!state->job_control) {
		return true;

M shell/task/command_process.c => shell/task/command_process.c +2 -2
@@ 43,7 43,7 @@ static bool task_process_start(struct task_command *tc, struct context *ctx) {
	} else if (pid == 0) {
		struct mrsh_job *job = put_into_process_group(ctx, getpid());
		if (ctx->state->interactive && !ctx->background) {
			tcsetpgrp(ctx->state->fd, job->pgid);
			job_set_foreground(job, true);
		}
		init_job_child_process(ctx->state);



@@ 95,7 95,7 @@ static bool task_process_start(struct task_command *tc, struct context *ctx) {

	struct mrsh_job *job = put_into_process_group(ctx, pid);
	if (ctx->state->interactive && !ctx->background) {
		tcsetpgrp(ctx->state->fd, job->pgid);
		job_set_foreground(job, true);
	}

	tc->process = process_create(ctx->state, pid);

M shell/task/task.c => shell/task/task.c +3 -5
@@ 53,11 53,9 @@ int task_run(struct task *task, struct context *ctx) {
				ctx->state->exit = ret;
			}

			// Put the shell back in the foreground
			tcsetpgrp(ctx->state->fd, ctx->state->pgid);
			// Restore the shell’s terminal modes
			// tcgetattr(ctx->state->fd, &job->term_modes); // TODO
			tcsetattr(ctx->state->fd, TCSADRAIN, &ctx->state->term_modes);
			if (ctx->state->foreground_job != NULL) {
				job_set_foreground(ctx->state->foreground_job, false);
			}

			destroy_finished_jobs(ctx->state);