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
use clap::Parser;
use std::io::Write;
use brush_core::{ExecutionExitCode, ExecutionResult, builtins, error};
/// Wait for jobs to terminate.
#[derive(Parser)]
pub(crate) struct WaitCommand {
/// Wait for specified job to terminate (instead of change status).
#[arg(short = 'f')]
wait_for_terminate: bool,
/// Wait for a single job to change status; if jobs are specified, waits for
/// the first to change status, and otherwise waits for the next change.
#[arg(short = 'n')]
wait_for_first_or_next: bool,
/// Name of variable to receive the job ID of the job whose status is indicated.
#[arg(short = 'p', value_name = "VAR_NAME")]
variable_to_receive_id: Option<String>,
/// Process IDs or job specs to wait for.
ids: Vec<String>,
}
impl builtins::Command for WaitCommand {
type Error = brush_core::Error;
async fn execute<SE: brush_core::ShellExtensions>(
&self,
context: brush_core::ExecutionContext<'_, SE>,
) -> Result<ExecutionResult, Self::Error> {
if self.wait_for_terminate {
return error::unimp("wait -f");
}
if self.wait_for_first_or_next {
return error::unimp("wait -n");
}
if self.variable_to_receive_id.is_some() {
return error::unimp("wait -p");
}
let mut result = ExecutionResult::success();
if !self.ids.is_empty() {
for id in &self.ids {
if id.starts_with('%') {
// It's a job spec.
if let Some(job) = context.shell.jobs_mut().resolve_job_spec(id) {
job.wait().await?;
} else {
writeln!(
context.stderr(),
"{}: no such job: {}",
context.command_name,
id
)?;
result = ExecutionExitCode::GeneralError.into();
}
} else {
// It's a process ID.
return error::unimp("wait with process IDs");
}
}
} else {
// Wait for all jobs.
let jobs = context.shell.jobs_mut().wait_all().await?;
if context.shell.options().enable_job_control {
for job in jobs {
writeln!(context.stdout(), "{job}")?;
}
}
}
Ok(result)
}
}