~emersion/mrsh

18a516b153f72788ac73ad1e63c21c1fe8b9764f — Simon Ser 1 year, 2 months ago b8aa6b8
Improve docs
3 files changed, 46 insertions(+), 3 deletions(-)

M include/shell/job.h
M include/shell/process.h
M shell/job.c
M include/shell/job.h => include/shell/job.h +28 -1
@@ 12,19 12,40 @@ struct process;
/**
 * A job is a set of processes, comprising a shell pipeline, and any processes
 * descended from it, that are all in the same process group.
 *
 * In practice, a single job is also created when executing an asynchronous
 * command list.
 *
 * This object is guaranteed to be valid until either:
 * - The job terminates
 * - The shell is destroyed
 */
struct mrsh_job {
	pid_t pgid;
	struct termios term_modes;
	struct termios term_modes; // only valid if stopped
	struct mrsh_state *state;
	struct mrsh_array processes; // struct process *
};

/**
 * Create a new job with the provided process group ID.
 */
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);
/**
 * Check whether all child processes have terminated. If there are no child
 * processes in this job, returns true.
 */
bool job_terminated(struct mrsh_job *job);
/**
 * Check whether there is at least one stopped child process and all others
 * have terminated.
 */
bool job_stopped(struct mrsh_job *job);
/**
 * Wait for the completion of the job.
 */
int job_wait(struct mrsh_job *job);
/**
 * Put the job in the foreground or in the background. If the job is stopped and


@@ 32,7 53,13 @@ int job_wait(struct mrsh_job *job);
 */
bool job_set_foreground(struct mrsh_job *job, bool foreground, bool cont);

/**
 * Initialize a child process state.
 */
bool init_job_child_process(struct mrsh_state *state);
/**
 * Update the shell's state with a child process status.
 */
void update_job(struct mrsh_state *state, pid_t pid, int stat);

#endif

M include/shell/process.h => include/shell/process.h +13 -1
@@ 17,13 17,25 @@ struct process {
	struct mrsh_state *state;
	bool stopped;
	bool terminated;
	int stat;
	int stat; // only valid if terminated
};

/**
 * Register a new process.
 */
struct process *process_create(struct mrsh_state *state, pid_t pid);
void process_destroy(struct process *process);
/**
 * Polls the process' current status without blocking. Returns:
 * - An integer >= 0 if the process has terminated
 * - TASK_STATUS_STOPPED if the process is stopped
 * - TASK_STATUS_WAIT if the process is running
 */
int process_poll(struct process *process);

/**
 * Update the shell's state with a child process status.
 */
void update_process(struct mrsh_state *state, pid_t pid, int stat);

#endif

M shell/job.c => shell/job.c +5 -1
@@ 149,8 149,10 @@ bool job_set_foreground(struct mrsh_job *job, bool foreground, bool cont) {

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


@@ 159,8 161,10 @@ bool job_set_foreground(struct mrsh_job *job, bool foreground, bool cont) {
	if (!foreground && state->foreground_job == job) {
		// Put the shell back in the foreground
		tcsetpgrp(state->fd, state->pgid);
		// Restore the shell’s terminal modes
		// Save the job's terminal modes, to restore them if it's put in the
		// foreground again
		tcgetattr(state->fd, &job->term_modes);
		// Restore the shell’s terminal modes
		tcsetattr(state->fd, TCSADRAIN, &state->term_modes);
		state->foreground_job = NULL;
	}