1use self::args::{Run, Source, Work};
20use std::str::FromStr as _;
21use yash_builtin::BUILTINS;
22use yash_env::Env;
23use yash_env::System;
24use yash_env::io::Fd;
25use yash_env::option::Option::{Interactive, Monitor, Stdin};
26use yash_env::option::State::On;
27use yash_env::parser::IsKeyword;
28use yash_env::prompt::GetPrompt;
29use yash_env::semantics::command::RunFunction;
30use yash_env::trap::RunSignalTrapIfCaught;
31use yash_semantics::RunReadEvalLoop;
32
33pub mod args;
34pub mod init_file;
35pub mod input;
36
37pub fn auto_interactive<S: System>(system: &S, run: &Run) -> bool {
46 if run.work.source != Source::Stdin {
47 return false;
48 }
49 if run.options.iter().any(|&(o, _)| o == Interactive) {
50 return false;
51 }
52 system.isatty(Fd::STDIN) && system.isatty(Fd::STDERR)
53}
54
55pub fn configure_environment(env: &mut Env, run: Run) -> Work {
65 if auto_interactive(&env.system, &run) {
67 env.options.set(Interactive, On);
68 }
69 if run.work.source == self::args::Source::Stdin {
70 env.options.set(Stdin, On);
71 }
72 for &(option, state) in &run.options {
73 env.options.set(option, state);
74 }
75 if env.options.get(Interactive) == On && !run.options.iter().any(|&(o, _)| o == Monitor) {
76 env.options.set(Monitor, On);
77 }
78
79 env.arg0 = run.arg0;
81 env.variables.positional_params_mut().values = run.positional_params;
82
83 if env.options.get(Interactive) == On {
85 env.traps
86 .enable_internal_dispositions_for_terminators(&mut env.system)
87 .ok();
88 if env.options.get(Monitor) == On {
89 env.traps
90 .enable_internal_dispositions_for_stoppers(&mut env.system)
91 .ok();
92 }
93 }
94
95 if env.options.get(Monitor) == On {
97 env.ensure_foreground().ok();
99 }
100
101 env.builtins.extend(BUILTINS.iter().cloned());
103
104 env.init_variables();
106
107 inject_dependencies(env);
109
110 run.work
111}
112
113fn inject_dependencies(env: &mut Env) {
115 env.any.insert(Box::new(IsKeyword(|_env, word| {
116 yash_syntax::parser::lex::Keyword::from_str(word).is_ok()
117 })));
118
119 env.any.insert(Box::new(RunReadEvalLoop(|env, config| {
120 Box::pin(async move {
121 let mut lexer = config.into_lexer();
122 yash_semantics::read_eval_loop(env, &mut lexer).await
123 })
124 })));
125
126 env.any.insert(Box::new(RunFunction(
127 |env, function, fields, env_prep_hook| {
128 Box::pin(async move {
129 yash_semantics::command::simple_command::execute_function_body(
130 env,
131 function,
132 fields,
133 env_prep_hook,
134 )
135 .await
136 })
137 },
138 )));
139
140 env.any
141 .insert(Box::new(RunSignalTrapIfCaught(|env, signal| {
142 Box::pin(async move { yash_semantics::trap::run_trap_if_caught(env, signal).await })
143 })));
144
145 env.any.insert(Box::new(GetPrompt(|env, context| {
146 Box::pin(async move {
147 let prompt = yash_prompt::fetch_posix(&env.variables, context);
148 yash_prompt::expand_posix(env, &prompt, false).await
149 })
150 })));
151}