~emersion/mrsh

mrsh/builtin/jobs.c -rw-r--r-- 2.4 KiB View raw
7105405aBenjamin Lowry Makefile: remove getopt.h from public_includes a day ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "builtin.h"
#include "mrsh_getopt.h"
#include "shell/job.h"
#include "shell/process.h"
#include "shell/shell.h"
#include "shell/task.h"

static const char jobs_usage[] = "usage: jobs [-l|-p] [job_id...]\n";

struct jobs_context {
	struct mrsh_job *current, *previous;
	bool pids;
	bool pgids;
	bool r;
};

static void show_job(struct mrsh_job *job, const struct jobs_context *ctx) {
	if (job_poll(job) >= 0) {
		return;
	}
	char curprev = ' ';
	if (job == ctx->current) {
		curprev = '+';
	} else if (job == ctx->previous) {
		curprev = '-';
	}
	if (ctx->pids) {
		for (size_t i = 0; i < job->processes.len; ++i) {
			struct mrsh_process *proc = job->processes.data[i];
			printf("%d\n", proc->pid);
		}
	} else if (ctx->pgids) {
		char *cmd = mrsh_node_format(job->node);
		printf("[%d] %c %d %s %s\n", job->job_id, curprev, job->pgid,
				job_state_str(job, ctx->r), cmd);
		free(cmd);
	} else {
		char *cmd = mrsh_node_format(job->node);
		printf("[%d] %c %s %s\n", job->job_id, curprev,
				job_state_str(job, ctx->r), cmd);
		free(cmd);
	}
}

int builtin_jobs(struct mrsh_state *state, int argc, char *argv[]) {
	struct mrsh_state_priv *priv = state_get_priv(state);

	struct mrsh_job *current = job_by_id(state, "%+", false),
		*previous = job_by_id(state, "%-", false);

	struct jobs_context ctx = {
		.current = current,
		.previous = previous,
		.pids = false,
		.pgids = false,
		.r = rand() % 2 == 0,
	};

	_mrsh_optind = 0;
	int opt;
	while ((opt = _mrsh_getopt(argc, argv, ":lp")) != -1) {
		switch (opt) {
		case 'l':
			if (ctx.pids) {
				fprintf(stderr, "jobs: the -p and -l options are "
						"mutually exclusive\n");
				return EXIT_FAILURE;
			}
			ctx.pgids = true;
			break;
		case 'p':
			if (ctx.pgids) {
				fprintf(stderr, "jobs: the -p and -l options are "
						"mutually exclusive\n");
				return EXIT_FAILURE;
			}
			ctx.pids = true;
			break;
		default:
			fprintf(stderr, "jobs: unknown option -- %c\n", _mrsh_optopt);
			fprintf(stderr, jobs_usage);
			return EXIT_FAILURE;
		}
	}

	if (_mrsh_optind == argc) {
		for (size_t i = 0; i < priv->jobs.len; i++) {
			struct mrsh_job *job = priv->jobs.data[i];
			show_job(job, &ctx);
		}
	} else {
		for (int i = _mrsh_optind; i < argc; i++) {
			struct mrsh_job *job = job_by_id(state, argv[i], true);
			if (!job) {
				return 1;
			}
			show_job(job, &ctx);
		}
	}

	return EXIT_SUCCESS;
}