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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// This file is part of yash, an extended POSIX shell.
// Copyright (C) 2023 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/>.
//! Source (`.`) built-in
//!
//! The **`source`** (**`.`**) built-in reads and executes commands from a file.
//!
//! # Synopsis
//!
//! ```sh
//! . file [arguments…]
//! ```
//!
//! ```sh
//! source file [arguments…]
//! ```
//!
//! # Description
//!
//! The `.` built-in reads and executes commands from the specified file in the
//! current shell environment.
//!
//! If the filename does not contain a slash, the shell searches the directories
//! in the `$PATH` variable for the file. The file does not need to be
//! executable; any readable file found first is used. (TODO: If no file is
//! found, the built-in falls back to the file in the current working
//! directory.)
//!
//! If there are any operands after the filename, they are assigned to the
//! positional parameters (`$1`, `$2`, etc.) during the execution of the file.
//! In this case, a regular [variable context](yash_env::variable::Context) is
//! pushed to secure the positional parameters. The context will also affect
//! local variables possibly defined in the file. The context is popped when the
//! execution of the file is finished. No context is pushed if there are no
//! operands other than the filename.
//!
//! # Options
//!
//! None.
//!
//! (TODO: non-portable options)
//!
//! # Operands
//!
//! The first operand ***file*** must be given and is the pathname of the file
//! to be executed. If it does not contain a slash, it is subject to the search
//! described above.
//!
//! Any remaining ***arguments*** are passed to the executed file as positional
//! parameters.
//!
//! # Errors
//!
//! It is an error if the file cannot be found or read.
//! During parsing and execution, any syntax error or runtime error may occur.
//!
//! # Exit status
//!
//! The exit status of the source built-in is the exit status of the last
//! command executed in the file.
//! If there is no command in the file, the exit status is zero.
//!
//! If the file cannot be found or read, the exit status is 1
//! ([`ExitStatus::FAILURE`]).
//! In case of a syntax error in the file, the exit status is 2
//! ([`ExitStatus::ERROR`]).
//!
//! # Portability
//!
//! The `.` built-in is specified in the POSIX standard. The built-in name
//! `source` is a non-portable extension that is also available in some other
//! shells.
//!
//! POSIX does not require the `.` built-in to conform to the Utility Syntax
//! Guidelines, which means portable scripts cannot use any options or the `--`
//! separator for the built-in.
//!
//! Falling back to the file in the current working directory when the file is
//! not found in the `$PATH` is a non-portable extension. This behavior is
//! disabled if the TBD shell option is set. The result of the `$PATH` search
//! may be unpredictable depending on the environment. Prefix the filename with
//! `./` to avoid the search and make sure the file in the current working
//! directory is used.
//!
//! Setting the positional parameters with additional operands is a non-portable
//! extension that is supported by some other shells. The behavior about the
//! local variable context may differ in other shells.
//!
//! Other implementations may return a different non-zero exit status for an
//! error.
use crateResult;
use ExitStatus;
use Field;
use Env;
/// Set of information that defines the behavior of a single invocation of the
/// `.` built-in
///
/// The [`syntax::parse`] function parses the command line arguments and
/// constructs a `Command` value. The [`execute`](Self::execute) method
/// executes the command.
/// Entry point of the `.` built-in execution
pub async