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
108
109
110
111
// This file is part of yash, an extended POSIX shell.
// Copyright (C) 2021 WATANABE Yuki
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//! Handling traps.
//!
//! _Traps_ are an event-handling mechanism in the shell. The user can prepare a
//! trap by using the trap built-in so that the shell performs a desired action
//! in response to a specific condition that may occur later. This module
//! contains functions to detect the conditions and run trap actions
//! accordingly.
//!
//! # Related items
//!
//! Traps set by the user are stored in a [trap set](TrapSet) implemented in the
//! [`yash_env::trap`] module.
//! The `trap` built-in is implemented in the `yash_builtin` crate.
//!
//! # Signal traps
//!
//! When an [environment](Env) catches a signal with a function like
//! [`wait_for_signals`](Env::wait_for_signals) and
//! [`poll_signals`](Env::poll_signals), the signal is stored as "pending" in
//! the trap set in the environment. The [`run_traps_for_caught_signals`]
//! function consumes those pending signals and runs the corresponding commands
//! specified in the trap set. The function is called periodically as the shell
//! executes main commands; roughly before and after each command.
//!
//! # Non-signal traps
//!
//! The EXIT trap is executed when the shell exits normally, by running the exit
//! built-in or reaching the end of the script. The [`run_exit_trap`] function,
//! which should be called before exiting, runs the trap.
use crateRuntime;
use crateread_eval_loop;
use RefCell;
use Break;
use Rc;
use Env;
use Divert;
use Result;
use Frame;
use Condition;
use TrapSet;
use Lexer;
use Location;
use Source;
/// Helper function for running a trap action.
///
/// This function pushes a temporary frame `Frame::Trap(cond)` to the
/// environment stack and runs the trap action by parsing the `code` with the
/// given `origin`. The exit status of the trap action does not affect the exit
/// status of the current environment except when the trap action is interrupted
/// with `Result::Break(Divert::Interrupt(_))`. In that case, the exit status of
/// the trap action is left as is in the environment.
///
/// Other variants of `Result::Break(Divert::…)` are simply passed on to the
/// caller. (It is unclear whether POSIX intends to require this behavior for
/// `Divert::Break` and `Divert::Continue`, but it is implemented this way for
/// simplicity. The exit status section of the POSIX return built-in
/// specification mentions the intended behavior for the `Divert::Return` case,
/// implying that the diversion should be passed on to the caller.)
async
pub use run_trap_if_caught;
pub use run_traps_for_caught_signals;
pub use run_exit_trap;