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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
// This file is part of yash, an extended POSIX shell.
// Copyright (C) 2024 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/>.
//! Command built-in
//!
//! The **`command`** built-in executes a utility bypassing shell functions.
//! This is useful when you want to execute a utility that has the same name as
//! a shell function. The built-in also has options to search for the location
//! of the utility.
//!
//! # Synopsis
//!
//! ```sh
//! command [-p] name [arguments…]
//! ```
//!
//! ```sh
//! command -v|-V [-p] name
//! ```
//!
//! # Description
//!
//! Without the `-v` or `-V` option, the `command` built-in executes the utility
//! specified by the *name* with the given *arguments*. This is similar to the
//! execution of a simple command, but the shell functions are not searched for
//! the *name*.
//!
//! With the `-v` or `-V` option, the built-in identifies the type of the *name*
//! and, optionally, the location of the utility. The `-v` option prints the
//! pathname of the utility, if found, and the `-V` option prints a more
//! detailed description of the utility.
//!
//! # Options
//!
//! The **`-p`** option causes the built-in to search for the utility in the
//! standard search path instead of the current `$PATH`.
//!
//! The **`-v`** option identifies the type of the command name and prints the
//! pathname of the utility, if found.
//!
//! The **`-V`** option identifies the type of the command name and prints a
//! more detailed description of the utility.
//!
//! # Operands
//!
//! The ***name*** operand specifies the name of the utility to execute or
//! identify. The ***arguments*** are passed to the utility when executing it.
//!
//! # Standard output
//!
//! When the `-v` option is given, the built-in prints the following:
//!
//! - The absolute pathname of the utility, if found in the search path.
//! - The utility name itself, if it is a non-substitutive built-in, function,
//! or shell reserved word, hence not subject to search.
//! - A command line that would redefine the alias, if the name is an alias.
//!
//! When the `-V` option is given, the built-in describes the utility in a more
//! descriptive, human-readable format. The exact format is not specified here
//! as it is subject to change.
//!
//! Nothing is printed if the utility is not found.
//!
//! # Errors
//!
//! It is an error if the specified utility is not found or cannot be executed.
//!
//! With the `-v` option, no error message is printed for the utility not found.
//!
//! # Exit status
//!
//! Without the `-v` or `-V` option, the exit status is that of the utility
//! executed. If the utility is not found, the exit status is 127. If the
//! utility is found but cannot be executed, the exit status is 126.
//!
//! With the `-v` or `-V` option, the exit status is 0 if the utility is found
//! and 1 if not found.
//!
//! # Portability
//!
//! POSIX requires that the `name` operand be specified, but many
//! implementations allow it to be omitted, in which case the built-in does
//! nothing.
//!
//! When the utility is not found with the `-v` or `-V` option, some
//! implementations return a non-zero exit status other than 1, especially 127.
//!
//! When the utility is not found with the `-V` option, some implementations
//! print an error message to the standard output while others to the standard
//! error.
//!
//! # Implementation notes
//!
//! The `-p` option depends on [`System::confstr_path`] to obtain the standard
//! search path. See the source code of [`RealSystem::confstr_path`] for the
//! platforms supported on the real system.
//!
//! The [`type`] built-in is equivalent to the `command` built-in with the `-V`
//! option.
//!
//! [`type`]: crate::type
use cratereport_error;
use EnumSet;
use EnumSetType;
use Field;
use RealSystem;
use System;
use Env;
/// Category of command name resolution
///
/// Used to specify the acceptable categories in [`Search`].
/// Set of parameters that specify how to resolve a command name
///
/// Used in [`Invoke`] and [`Identify`].
/// Parameters to invoke a utility
/// Parameters to identify a utility
/// Parsed command line arguments of the `command` built-in
/// Entry point of the `command` built-in
///
/// This function parses the arguments into [`Command`] and executes it.
pub async