1 This file is type.def
, from which is created type.c.
2 It implements the builtin
"type" in Bush.
4 Copyright (C
) 1987-2020 Free Software Foundation
, Inc.
6 This file is part of GNU Bush
, the Bourne Again SHell.
8 Bush is free software
: you can redistribute it and
/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation
, either version
3 of the License
, or
11 (at your option
) any later version.
13 Bush is distributed in the hope that it will be useful
,
14 but WITHOUT ANY WARRANTY
; without even the implied warranty of
15 MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with Bush. If not
, see
<http
://www.gnu.org
/licenses
/>.
24 $FUNCTION type_builtin
25 $SHORT_DOC type
[-afptP
] name
[name ...
]
26 Display information about command type.
28 For each NAME
, indicate how it would be interpreted if used as a
32 -a display all locations containing an executable named NAME
;
33 includes aliases
, builtins
, and functions
, if and only if
34 the `
-p
' option is not also used
35 -f suppress shell function lookup
36 -P force a PATH search for each NAME, even if it is an alias,
37 builtin, or function, and returns the name of the disk file
38 that would be executed
39 -p returns either the name of the disk file that would be executed,
40 or nothing if `type -t NAME' would not return `file
'
41 -t output a single word which is one of `alias', `keyword
',
42 `function', `builtin
', `file' or `
', if NAME is an alias,
43 shell reserved word, shell function, shell builtin, disk file,
44 or not found, respectively
47 NAME Command name to be interpreted.
50 Returns success if all of the NAMEs are found; fails if any are not found.
55 #include "../src/bushtypes.h"
56 #include "posixstat.h"
58 #if defined (HAVE_UNISTD_H)
63 #include "../src/bushansi.h"
64 #include "../src/bushintl.h"
66 #include "../src/shell.h"
67 #include "../src/lxrgmr/parser.h"
68 #include "../src/runner/execute_cmd.h"
69 #include "../src/impl/findcmd.h"
70 #include "../src/hashcmd.h"
73 #include "../src/impl/alias.h"
77 #include "bushgetopt.h"
79 extern int find_reserved_word PARAMS((char *));
81 /* For each word in LIST, find out what the shell is going to do with
82 it as a simple command. i.e., which file would this shell use to
83 execve, or if it is a builtin command, or an alias. Possible flag
85 -t Returns the "type" of the object, one of
86 `alias', `keyword
', `function', `builtin
',
89 -p Returns the pathname of the file if
-type is
92 -a Returns all occurrences of words
, whether they
93 be a filename in the path
, alias
, function
,
96 -f Suppress shell function lookup
, like `command
'.
98 -P Force a path search even in the presence of other
113 int dflags, any_failed, opt;
117 return (EXECUTION_SUCCESS);
119 dflags = CDESC_SHORTDESC; /* default */
122 /* Handle the obsolescent `-type', `
-path
', and `-all' by prescanning
123 the arguments and converting those options to the form that
124 internal_getopt recognizes. Converts `
--type
', `--path', and `
--all
'
125 also. THIS SHOULD REALLY GO AWAY. */
126 for (this = list; this && this->word->word[0] == '-'; this = this->next)
128 char *flag = &(this->word->word[1]);
130 if (STREQ (flag, "type") || STREQ (flag, "-type"))
132 this->word->word[1] = 't
';
133 this->word->word[2] = '\
0';
135 else if (STREQ (flag, "path") || STREQ (flag, "-path"))
137 this->word->word[1] = 'p
';
138 this->word->word[2] = '\
0';
140 else if (STREQ (flag, "all") || STREQ (flag, "-all"))
142 this->word->word[1] = 'a
';
143 this->word->word[2] = '\
0';
147 reset_internal_getopt ();
148 while ((opt = internal_getopt (list, "afptP")) != -1)
156 dflags |= CDESC_NOFUNCS;
159 dflags |= CDESC_PATH_ONLY;
160 dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
163 dflags |= CDESC_TYPE;
164 dflags &= ~(CDESC_PATH_ONLY|CDESC_SHORTDESC);
166 case 'P
': /* shorthand for type -ap */
167 dflags |= (CDESC_PATH_ONLY|CDESC_FORCE_PATH);
168 dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
182 found = describe_command (list->word->word, dflags);
184 if (!found && (dflags & (CDESC_PATH_ONLY|CDESC_TYPE)) == 0)
185 sh_notfound (list->word->word);
187 any_failed += found == 0;
191 opt = (any_failed == 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
192 return (sh_chkwrite (opt));
196 * Describe COMMAND as required by the type and command builtins.
198 * Behavior is controlled by DFLAGS. Flag values are
199 * CDESC_ALL print all descriptions of a command
200 * CDESC_SHORTDESC print the description for type and command -V
201 * CDESC_REUSABLE print in a format that may be reused as input
202 * CDESC_TYPE print the type for type -t
203 * CDESC_PATH_ONLY print the path for type -p
204 * CDESC_FORCE_PATH force a path search for type -P
205 * CDESC_NOFUNCS skip function lookup for type -f
206 * CDESC_ABSPATH convert to absolute path, no ./ prefix
207 * CDESC_STDPATH command -p standard path list
209 * CDESC_ALL says whether or not to look for all occurrences of COMMAND, or
210 * return after finding it once.
213 describe_command (command, dflags)
217 int found, i, found_file, f, all;
218 char *full_path, *x, *pathlist;
224 all = (dflags & CDESC_ALL) != 0;
225 found = found_file = 0;
226 full_path = (char *)NULL;
229 /* Command is an alias? */
230 if (((dflags & CDESC_FORCE_PATH) == 0) && expand_aliases && (alias = find_alias (command)))
232 if (dflags & CDESC_TYPE)
234 else if (dflags & CDESC_SHORTDESC)
235 printf (_("%s is aliased to `%s'\n"), command, alias->value);
236 else if (dflags & CDESC_REUSABLE)
238 x = sh_single_quote (alias->value);
239 printf ("alias
%s
=%s
\n", command, x);
250 /* Command is a shell reserved word? */
251 if (((dflags & CDESC_FORCE_PATH) == 0) && (i = find_reserved_word (command)) >= 0)
253 if (dflags & CDESC_TYPE)
255 else if (dflags & CDESC_SHORTDESC)
256 printf (_("%s is a shell keyword
\n"), command);
257 else if (dflags & CDESC_REUSABLE)
258 printf ("%s
\n", command);
266 /* Command is a function? */
267 if (((dflags & (CDESC_FORCE_PATH|CDESC_NOFUNCS)) == 0) && (func = find_function (command)))
269 if (dflags & CDESC_TYPE)
271 else if (dflags & CDESC_SHORTDESC)
275 printf (_("%s is a function
\n"), command);
277 /* We're blowing away THE_PRINTED_COMMAND here... */
279 result = named_function_string (command, function_cell (func), FUNC_MULTILINE|FUNC_EXTERNAL);
280 printf ("%s
\n", result);
282 else if (dflags & CDESC_REUSABLE)
283 printf ("%s
\n", command);
291 /* Command is a builtin? */
292 if (((dflags & CDESC_FORCE_PATH) == 0) && find_shell_builtin (command))
294 if (dflags & CDESC_TYPE)
296 else if (dflags & CDESC_SHORTDESC)
298 if (posixly_correct && find_special_builtin (command) != 0)
299 printf (_("%s is a special shell builtin
\n"), command);
301 printf (_("%s is a shell builtin
\n"), command);
303 else if (dflags & CDESC_REUSABLE)
304 printf ("%s
\n", command);
312 /* Command is a disk file? */
313 /* If the command name given is already an absolute command, just
314 check to see if it is executable. */
315 if (absolute_program (command))
317 f = file_status (command);
320 if (dflags & CDESC_TYPE)
322 else if (dflags & CDESC_SHORTDESC)
323 printf (_("%s is
%s
\n"), command, command);
324 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
325 printf ("%s
\n", command);
327 /* There's no use looking in the hash table or in $PATH,
328 because they're not consulted when an absolute program
334 /* If the user isn't doing "-a
", then we might care about
335 whether the file is present in our hash table. */
336 if (all == 0 || (dflags & CDESC_FORCE_PATH))
338 if (full_path = phash_search (command))
340 if (dflags & CDESC_TYPE)
342 else if (dflags & CDESC_SHORTDESC)
343 printf (_("%s is
hashed (%s
)\n"), command, full_path);
344 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
345 printf ("%s
\n", full_path);
352 /* Now search through $PATH. */
355 if (dflags & CDESC_STDPATH) /* command -p, all cannot be non-zero */
357 pathlist = conf_standard_path ();
358 full_path = find_in_path (command, pathlist, FS_EXEC_PREFERRED|FS_NODIRS);
360 /* Will only go through this once, since all == 0 if STDPATH set */
363 full_path = find_user_command (command);
365 full_path = user_command_matches (command, FS_EXEC_ONLY, found_file); /* XXX - should that be FS_EXEC_PREFERRED? */
370 /* If we found the command as itself by looking through $PATH, it
371 probably doesn't exist. Check whether or not the command is an
372 executable file. If it's not, don't report a match. This is
373 the default posix mode behavior */
374 if (STREQ (full_path, command) || posixly_correct)
376 f = file_status (full_path);
377 if ((f & FS_EXECABLE) == 0)
380 full_path = (char *)NULL;
384 else if (ABSPATH (full_path))
385 ; /* placeholder; don't need to do anything yet */
386 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY|CDESC_SHORTDESC))
388 f = MP_DOCWD | ((dflags & CDESC_ABSPATH) ? MP_RMDOT : 0);
389 x = sh_makepath ((char *)NULL, full_path, f);
394 /* If we require a full path and don't have one, make one */
395 else if ((dflags & CDESC_ABSPATH) && ABSPATH (full_path) == 0)
397 x = sh_makepath ((char *)NULL, full_path, MP_DOCWD|MP_RMDOT);
405 if (dflags & CDESC_TYPE)
407 else if (dflags & CDESC_SHORTDESC)
408 printf (_("%s is
%s
\n"), command, full_path);
409 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
410 printf ("%s
\n", full_path);
413 full_path = (char *)NULL;