use crate::CommandGlobalOpts;
use clap::Args;
use colorful::Colorful;
use ockam_api::{fmt_log, fmt_warn};
use std::io;
use std::io::Read;
use tracing::{debug, info};
#[derive(Clone, Debug, Args, Default)]
pub struct ForegroundArgs {
#[arg(long, short)]
pub foreground: bool,
#[arg(long, short, requires = "foreground")]
pub exit_on_eof: bool,
#[arg(hide = true, long, requires = "foreground")]
pub child_process: bool,
}
pub async fn wait_for_exit_signal(
args: &ForegroundArgs,
opts: &CommandGlobalOpts,
msg: &str,
) -> miette::Result<()> {
let (tx, mut rx) = tokio::sync::mpsc::channel(2);
{
let tx = tx.clone();
let terminal = opts.terminal.clone();
let mut processed = false;
let is_child_process = args.child_process;
ctrlc::set_handler(move || {
if !processed {
let _ = tx.blocking_send(());
info!("Exit signal received");
if !is_child_process {
let _ =
terminal.write_line("\n".to_string() + &fmt_warn!("Exit signal received"));
}
processed = true
}
})
.expect("Error setting exit signal handler");
}
if args.exit_on_eof {
{
let tx = tx.clone();
let terminal = opts.terminal.clone();
std::thread::spawn(move || {
let mut buffer = Vec::new();
let mut handle = io::stdin().lock();
if handle.read_to_end(&mut buffer).is_ok() {
let _ = tx.blocking_send(());
info!("EOF received");
let _ = terminal.write_line(fmt_warn!("EOF received"));
}
});
}
}
debug!("waiting for exit signal");
if !args.child_process && opts.terminal.is_tty() {
opts.terminal.write_line("")?;
opts.terminal.write(fmt_log!("{}", msg))?;
}
rx.recv().await;
Ok(())
}