1 This file is type.def, from which is created type.c.
2 It implements the builtin "type" in Bash.
4 Copyright (C) 1987-2002 Free Software Foundation, Inc.
6 This file is part of GNU Bash, the Bourne Again SHell.
8 Bash is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License along
19 with Bash; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
25 $FUNCTION type_builtin
26 $SHORT_DOC type [-afptP] name [name ...]
27 For each NAME, indicate how it would be interpreted if used as a
30 If the -t option is used, `type' outputs a single word which is one of
31 `alias', `keyword', `function', `builtin', `file' or `', if NAME is an
32 alias, shell reserved word, shell function, shell builtin, disk file,
33 or unfound, respectively.
35 If the -p flag is used, `type' either returns the name of the disk
36 file that would be executed, or nothing if `type -t NAME' would not
39 If the -a flag is used, `type' displays all of the places that contain
40 an executable named `file'. This includes aliases, builtins, and
41 functions, if and only if the -p flag is not also used.
43 The -f flag suppresses shell function lookup.
45 The -P flag forces a PATH search for each NAME, even if it is an alias,
46 builtin, or function, and returns the name of the disk file that would
52 #include "../bashtypes.h"
53 #include "posixstat.h"
55 #if defined (HAVE_UNISTD_H)
60 #include "../bashansi.h"
61 #include "../bashintl.h"
64 #include "../findcmd.h"
65 #include "../hashcmd.h"
72 #include "bashgetopt.h"
74 extern int find_reserved_word __P((char *));
76 extern char *this_command_name;
77 extern int expand_aliases;
79 /* For each word in LIST, find out what the shell is going to do with
80 it as a simple command. i.e., which file would this shell use to
81 execve, or if it is a builtin command, or an alias. Possible flag
83 -t Returns the "type" of the object, one of
84 `alias', `keyword', `function', `builtin',
87 -p Returns the pathname of the file if -type is
90 -a Returns all occurrences of words, whether they
91 be a filename in the path, alias, function,
94 -f Suppress shell function lookup, like `command'.
96 -P Force a path search even in the presence of other
111 int dflags, successful_finds, opt;
115 return (EXECUTION_SUCCESS);
117 dflags = CDESC_SHORTDESC; /* default */
118 successful_finds = 0;
120 /* Handle the obsolescent `-type', `-path', and `-all' by prescanning
121 the arguments and converting those options to the form that
122 internal_getopt recognizes. Converts `--type', `--path', and `--all'
123 also. THIS SHOULD REALLY GO AWAY. */
124 for (this = list; this && this->word->word[0] == '-'; this = this->next)
126 char *flag = &(this->word->word[1]);
128 if (STREQ (flag, "type") || STREQ (flag, "-type"))
130 this->word->word[1] = 't';
131 this->word->word[2] = '\0';
133 else if (STREQ (flag, "path") || STREQ (flag, "-path"))
135 this->word->word[1] = 'p';
136 this->word->word[2] = '\0';
138 else if (STREQ (flag, "all") || STREQ (flag, "-all"))
140 this->word->word[1] = 'a';
141 this->word->word[2] = '\0';
145 reset_internal_getopt ();
146 while ((opt = internal_getopt (list, "afptP")) != -1)
154 dflags |= CDESC_NOFUNCS;
157 dflags |= CDESC_PATH_ONLY;
158 dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
161 dflags |= CDESC_TYPE;
162 dflags &= ~(CDESC_PATH_ONLY|CDESC_SHORTDESC);
164 case 'P': /* shorthand for type -ap */
165 dflags |= (CDESC_PATH_ONLY|CDESC_FORCE_PATH);
166 dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
179 found = describe_command (list->word->word, dflags);
181 if (!found && (dflags & (CDESC_PATH_ONLY|CDESC_TYPE)) == 0)
182 sh_notfound (list->word->word);
184 successful_finds += found;
190 return ((successful_finds != 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
194 * Describe COMMAND as required by the type and command builtins.
196 * Behavior is controlled by DFLAGS. Flag values are
197 * CDESC_ALL print all descriptions of a command
198 * CDESC_SHORTDESC print the description for type and command -V
199 * CDESC_REUSABLE print in a format that may be reused as input
200 * CDESC_TYPE print the type for type -t
201 * CDESC_PATH_ONLY print the path for type -p
202 * CDESC_FORCE_PATH force a path search for type -P
203 * CDESC_NOFUNCS skip function lookup for type -f
205 * CDESC_ALL says whether or not to look for all occurrences of COMMAND, or
206 * return after finding it once.
209 describe_command (command, dflags)
213 int found, i, found_file, f, all;
220 all = (dflags & CDESC_ALL) != 0;
221 found = found_file = 0;
222 full_path = (char *)NULL;
225 /* Command is an alias? */
226 if (((dflags & CDESC_FORCE_PATH) == 0) && expand_aliases && (alias = find_alias (command)))
228 if (dflags & CDESC_TYPE)
230 else if (dflags & CDESC_SHORTDESC)
231 printf (_("%s is aliased to `%s'\n"), command, alias->value);
232 else if (dflags & CDESC_REUSABLE)
234 x = sh_single_quote (alias->value);
235 printf ("alias %s=%s\n", command, x);
246 /* Command is a shell reserved word? */
247 if (((dflags & CDESC_FORCE_PATH) == 0) && (i = find_reserved_word (command)) >= 0)
249 if (dflags & CDESC_TYPE)
251 else if (dflags & CDESC_SHORTDESC)
252 printf (_("%s is a shell keyword\n"), command);
253 else if (dflags & CDESC_REUSABLE)
254 printf ("%s\n", command);
262 /* Command is a function? */
263 if (((dflags & (CDESC_FORCE_PATH|CDESC_NOFUNCS)) == 0) && (func = find_function (command)))
265 if (dflags & CDESC_TYPE)
267 else if (dflags & CDESC_SHORTDESC)
269 #define PRETTY_PRINT_FUNC 1
272 printf (_("%s is a function\n"), command);
274 /* We're blowing away THE_PRINTED_COMMAND here... */
276 result = named_function_string (command,
277 (COMMAND *) function_cell (func),
279 printf ("%s\n", result);
280 #undef PRETTY_PRINT_FUNC
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)
297 printf (_("%s is a shell builtin\n"), command);
298 else if (dflags & CDESC_REUSABLE)
299 printf ("%s\n", command);
307 /* Command is a disk file? */
308 /* If the command name given is already an absolute command, just
309 check to see if it is executable. */
310 if (absolute_program (command))
312 f = file_status (command);
315 if (dflags & CDESC_TYPE)
317 else if (dflags & CDESC_SHORTDESC)
318 printf (_("%s is %s\n"), command, command);
319 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
320 printf ("%s\n", command);
322 /* There's no use looking in the hash table or in $PATH,
323 because they're not consulted when an absolute program
329 /* If the user isn't doing "-a", then we might care about
330 whether the file is present in our hash table. */
331 if (all == 0 || (dflags & CDESC_FORCE_PATH))
333 if (full_path = phash_search (command))
335 if (dflags & CDESC_TYPE)
337 else if (dflags & CDESC_SHORTDESC)
338 printf (_("%s is hashed (%s)\n"), command, full_path);
339 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
340 printf ("%s\n", full_path);
347 /* Now search through $PATH. */
351 full_path = find_user_command (command);
354 user_command_matches (command, FS_EXEC_ONLY, found_file);
355 /* XXX - should that be FS_EXEC_PREFERRED? */
360 /* If we found the command as itself by looking through $PATH, it
361 probably doesn't exist. Check whether or not the command is an
362 executable file. If it's not, don't report a match. */
363 if (STREQ (full_path, command))
365 f = file_status (full_path);
366 if ((f & FS_EXECABLE) == 0)
369 full_path = (char *)NULL;
373 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY|CDESC_SHORTDESC))
374 full_path = sh_makepath ((char *)NULL, full_path, MP_DOCWD);
380 if (dflags & CDESC_TYPE)
382 else if (dflags & CDESC_SHORTDESC)
383 printf ("%s is %s\n", command, full_path);
384 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
385 printf ("%s\n", full_path);
388 full_path = (char *)NULL;