]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/type.def
Bash-4.3 patch 39
[thirdparty/bash.git] / builtins / type.def
CommitLineData
726f6388
JA
1This file is type.def, from which is created type.c.
2It implements the builtin "type" in Bash.
3
ac50fbac 4Copyright (C) 1987-2011 Free Software Foundation, Inc.
726f6388
JA
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
3185942a
JA
8Bash is free software: you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation, either version 3 of the License, or
11(at your option) any later version.
726f6388 12
3185942a
JA
13Bash is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
726f6388 17
3185942a
JA
18You should have received a copy of the GNU General Public License
19along with Bash. If not, see <http://www.gnu.org/licenses/>.
726f6388
JA
20
21$PRODUCES type.c
22
23$BUILTIN type
24$FUNCTION type_builtin
7117c2d2 25$SHORT_DOC type [-afptP] name [name ...]
3185942a
JA
26Display information about command type.
27
726f6388
JA
28For each NAME, indicate how it would be interpreted if used as a
29command name.
30
3185942a
JA
31Options:
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, shell
43 reserved word, shell function, shell builtin, disk file, or not
44 found, respectively
45
46Arguments:
47 NAME Command name to be interpreted.
48
49Exit Status:
50Returns success if all of the NAMEs are found; fails if any are not found.
726f6388
JA
51$END
52
ccc6cda3
JA
53#include <config.h>
54
55#include "../bashtypes.h"
bb70624e 56#include "posixstat.h"
ccc6cda3
JA
57
58#if defined (HAVE_UNISTD_H)
59# include <unistd.h>
60#endif
61
62#include <stdio.h>
63#include "../bashansi.h"
b80f6443 64#include "../bashintl.h"
ccc6cda3 65
726f6388 66#include "../shell.h"
cce855bc 67#include "../findcmd.h"
d166f048 68#include "../hashcmd.h"
726f6388
JA
69
70#if defined (ALIAS)
71#include "../alias.h"
72#endif /* ALIAS */
73
74#include "common.h"
b72432fd 75#include "bashgetopt.h"
726f6388 76
f73dda09 77extern int find_reserved_word __P((char *));
726f6388 78
bb70624e 79extern char *this_command_name;
95732b49 80extern int expand_aliases, posixly_correct;
bb70624e 81
726f6388
JA
82/* For each word in LIST, find out what the shell is going to do with
83 it as a simple command. i.e., which file would this shell use to
84 execve, or if it is a builtin command, or an alias. Possible flag
85 arguments:
b72432fd 86 -t Returns the "type" of the object, one of
726f6388
JA
87 `alias', `keyword', `function', `builtin',
88 or `file'.
89
b72432fd 90 -p Returns the pathname of the file if -type is
726f6388
JA
91 a file.
92
b72432fd 93 -a Returns all occurrences of words, whether they
726f6388
JA
94 be a filename in the path, alias, function,
95 or builtin.
7117c2d2
JA
96
97 -f Suppress shell function lookup, like `command'.
98
99 -P Force a path search even in the presence of other
100 definitions.
101
726f6388
JA
102 Order of evaluation:
103 alias
104 keyword
105 function
106 builtin
107 file
108 */
b72432fd 109
ccc6cda3 110int
726f6388
JA
111type_builtin (list)
112 WORD_LIST *list;
113{
3185942a 114 int dflags, any_failed, opt;
7117c2d2 115 WORD_LIST *this;
726f6388 116
ccc6cda3
JA
117 if (list == 0)
118 return (EXECUTION_SUCCESS);
119
7117c2d2 120 dflags = CDESC_SHORTDESC; /* default */
3185942a 121 any_failed = 0;
726f6388 122
b72432fd 123 /* Handle the obsolescent `-type', `-path', and `-all' by prescanning
7117c2d2
JA
124 the arguments and converting those options to the form that
125 internal_getopt recognizes. Converts `--type', `--path', and `--all'
126 also. THIS SHOULD REALLY GO AWAY. */
127 for (this = list; this && this->word->word[0] == '-'; this = this->next)
726f6388 128 {
b72432fd 129 char *flag = &(this->word->word[1]);
726f6388 130
b72432fd 131 if (STREQ (flag, "type") || STREQ (flag, "-type"))
726f6388 132 {
7117c2d2
JA
133 this->word->word[1] = 't';
134 this->word->word[2] = '\0';
726f6388 135 }
b72432fd 136 else if (STREQ (flag, "path") || STREQ (flag, "-path"))
726f6388 137 {
7117c2d2
JA
138 this->word->word[1] = 'p';
139 this->word->word[2] = '\0';
726f6388 140 }
b72432fd 141 else if (STREQ (flag, "all") || STREQ (flag, "-all"))
726f6388 142 {
7117c2d2
JA
143 this->word->word[1] = 'a';
144 this->word->word[2] = '\0';
b72432fd
JA
145 }
146 }
147
148 reset_internal_getopt ();
7117c2d2 149 while ((opt = internal_getopt (list, "afptP")) != -1)
b72432fd
JA
150 {
151 switch (opt)
152 {
7117c2d2
JA
153 case 'a':
154 dflags |= CDESC_ALL;
155 break;
156 case 'f':
157 dflags |= CDESC_NOFUNCS;
b72432fd
JA
158 break;
159 case 'p':
7117c2d2
JA
160 dflags |= CDESC_PATH_ONLY;
161 dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
b72432fd 162 break;
7117c2d2
JA
163 case 't':
164 dflags |= CDESC_TYPE;
165 dflags &= ~(CDESC_PATH_ONLY|CDESC_SHORTDESC);
166 break;
167 case 'P': /* shorthand for type -ap */
168 dflags |= (CDESC_PATH_ONLY|CDESC_FORCE_PATH);
169 dflags &= ~(CDESC_TYPE|CDESC_SHORTDESC);
b72432fd
JA
170 break;
171 default:
ccc6cda3 172 builtin_usage ();
726f6388
JA
173 return (EX_USAGE);
174 }
726f6388 175 }
b72432fd 176 list = loptend;
726f6388 177
726f6388
JA
178 while (list)
179 {
180 int found;
181
7117c2d2 182 found = describe_command (list->word->word, dflags);
726f6388 183
7117c2d2
JA
184 if (!found && (dflags & (CDESC_PATH_ONLY|CDESC_TYPE)) == 0)
185 sh_notfound (list->word->word);
726f6388 186
3185942a 187 any_failed += found == 0;
726f6388
JA
188 list = list->next;
189 }
190
3185942a
JA
191 opt = (any_failed == 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE;
192 return (sh_chkwrite (opt));
726f6388
JA
193}
194
195/*
7117c2d2 196 * Describe COMMAND as required by the type and command builtins.
726f6388 197 *
7117c2d2
JA
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
95732b49 206 * CDESC_ABSPATH convert to absolute path, no ./ prefix
726f6388 207 *
7117c2d2 208 * CDESC_ALL says whether or not to look for all occurrences of COMMAND, or
726f6388
JA
209 * return after finding it once.
210 */
ccc6cda3 211int
7117c2d2 212describe_command (command, dflags)
726f6388 213 char *command;
7117c2d2 214 int dflags;
726f6388 215{
7117c2d2 216 int found, i, found_file, f, all;
f73dda09 217 char *full_path, *x;
726f6388 218 SHELL_VAR *func;
ccc6cda3
JA
219#if defined (ALIAS)
220 alias_t *alias;
221#endif
222
7117c2d2 223 all = (dflags & CDESC_ALL) != 0;
ccc6cda3
JA
224 found = found_file = 0;
225 full_path = (char *)NULL;
726f6388
JA
226
227#if defined (ALIAS)
228 /* Command is an alias? */
b80f6443 229 if (((dflags & CDESC_FORCE_PATH) == 0) && expand_aliases && (alias = find_alias (command)))
726f6388 230 {
7117c2d2 231 if (dflags & CDESC_TYPE)
ccc6cda3 232 puts ("alias");
7117c2d2 233 else if (dflags & CDESC_SHORTDESC)
b80f6443 234 printf (_("%s is aliased to `%s'\n"), command, alias->value);
7117c2d2 235 else if (dflags & CDESC_REUSABLE)
726f6388 236 {
28ef6c31 237 x = sh_single_quote (alias->value);
726f6388
JA
238 printf ("alias %s=%s\n", command, x);
239 free (x);
240 }
241
242 found = 1;
243
b72432fd 244 if (all == 0)
726f6388
JA
245 return (1);
246 }
247#endif /* ALIAS */
248
249 /* Command is a shell reserved word? */
7117c2d2 250 if (((dflags & CDESC_FORCE_PATH) == 0) && (i = find_reserved_word (command)) >= 0)
726f6388 251 {
7117c2d2 252 if (dflags & CDESC_TYPE)
ccc6cda3 253 puts ("keyword");
7117c2d2 254 else if (dflags & CDESC_SHORTDESC)
b80f6443 255 printf (_("%s is a shell keyword\n"), command);
7117c2d2 256 else if (dflags & CDESC_REUSABLE)
726f6388
JA
257 printf ("%s\n", command);
258
259 found = 1;
260
b72432fd 261 if (all == 0)
726f6388
JA
262 return (1);
263 }
264
265 /* Command is a function? */
7117c2d2 266 if (((dflags & (CDESC_FORCE_PATH|CDESC_NOFUNCS)) == 0) && (func = find_function (command)))
726f6388 267 {
7117c2d2 268 if (dflags & CDESC_TYPE)
ccc6cda3 269 puts ("function");
7117c2d2 270 else if (dflags & CDESC_SHORTDESC)
726f6388 271 {
726f6388
JA
272 char *result;
273
b80f6443 274 printf (_("%s is a function\n"), command);
726f6388
JA
275
276 /* We're blowing away THE_PRINTED_COMMAND here... */
277
3185942a 278 result = named_function_string (command, function_cell (func), FUNC_MULTILINE|FUNC_EXTERNAL);
726f6388 279 printf ("%s\n", result);
726f6388 280 }
7117c2d2 281 else if (dflags & CDESC_REUSABLE)
726f6388
JA
282 printf ("%s\n", command);
283
284 found = 1;
285
b72432fd 286 if (all == 0)
726f6388
JA
287 return (1);
288 }
289
290 /* Command is a builtin? */
7117c2d2 291 if (((dflags & CDESC_FORCE_PATH) == 0) && find_shell_builtin (command))
726f6388 292 {
7117c2d2 293 if (dflags & CDESC_TYPE)
ccc6cda3 294 puts ("builtin");
7117c2d2 295 else if (dflags & CDESC_SHORTDESC)
b80f6443 296 printf (_("%s is a shell builtin\n"), command);
7117c2d2 297 else if (dflags & CDESC_REUSABLE)
726f6388
JA
298 printf ("%s\n", command);
299
300 found = 1;
301
b72432fd 302 if (all == 0)
726f6388
JA
303 return (1);
304 }
305
306 /* Command is a disk file? */
307 /* If the command name given is already an absolute command, just
308 check to see if it is executable. */
309 if (absolute_program (command))
310 {
bb70624e 311 f = file_status (command);
726f6388 312 if (f & FS_EXECABLE)
28ef6c31 313 {
7117c2d2 314 if (dflags & CDESC_TYPE)
ccc6cda3 315 puts ("file");
7117c2d2 316 else if (dflags & CDESC_SHORTDESC)
b80f6443 317 printf (_("%s is %s\n"), command, command);
7117c2d2 318 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
726f6388
JA
319 printf ("%s\n", command);
320
321 /* There's no use looking in the hash table or in $PATH,
322 because they're not consulted when an absolute program
323 name is supplied. */
324 return (1);
28ef6c31 325 }
726f6388
JA
326 }
327
b72432fd 328 /* If the user isn't doing "-a", then we might care about
726f6388 329 whether the file is present in our hash table. */
7117c2d2 330 if (all == 0 || (dflags & CDESC_FORCE_PATH))
726f6388 331 {
7117c2d2 332 if (full_path = phash_search (command))
726f6388 333 {
7117c2d2 334 if (dflags & CDESC_TYPE)
ccc6cda3 335 puts ("file");
7117c2d2 336 else if (dflags & CDESC_SHORTDESC)
b80f6443 337 printf (_("%s is hashed (%s)\n"), command, full_path);
7117c2d2 338 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
726f6388
JA
339 printf ("%s\n", full_path);
340
d166f048 341 free (full_path);
726f6388
JA
342 return (1);
343 }
344 }
345
346 /* Now search through $PATH. */
347 while (1)
348 {
b72432fd 349 if (all == 0)
726f6388
JA
350 full_path = find_user_command (command);
351 else
352 full_path =
353 user_command_matches (command, FS_EXEC_ONLY, found_file);
354 /* XXX - should that be FS_EXEC_PREFERRED? */
355
ac50fbac 356 if (full_path == 0)
726f6388
JA
357 break;
358
bb70624e
JA
359 /* If we found the command as itself by looking through $PATH, it
360 probably doesn't exist. Check whether or not the command is an
95732b49
JA
361 executable file. If it's not, don't report a match. This is
362 the default posix mode behavior */
363 if (STREQ (full_path, command) || posixly_correct)
bb70624e
JA
364 {
365 f = file_status (full_path);
366 if ((f & FS_EXECABLE) == 0)
367 {
368 free (full_path);
369 full_path = (char *)NULL;
370 if (all == 0)
371 break;
372 }
95732b49
JA
373 else if (ABSPATH (full_path))
374 ; /* placeholder; don't need to do anything yet */
7117c2d2 375 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY|CDESC_SHORTDESC))
95732b49
JA
376 {
377 f = MP_DOCWD | ((dflags & CDESC_ABSPATH) ? MP_RMDOT : 0);
ac50fbac
CR
378 x = sh_makepath ((char *)NULL, full_path, f);
379 free (full_path);
380 full_path = x;
95732b49 381 }
bb70624e 382 }
95732b49
JA
383 /* If we require a full path and don't have one, make one */
384 else if ((dflags & CDESC_ABSPATH) && ABSPATH (full_path) == 0)
385 full_path = sh_makepath ((char *)NULL, full_path, MP_DOCWD|MP_RMDOT);
bb70624e 386
726f6388
JA
387 found_file++;
388 found = 1;
389
7117c2d2 390 if (dflags & CDESC_TYPE)
ccc6cda3 391 puts ("file");
7117c2d2 392 else if (dflags & CDESC_SHORTDESC)
3185942a 393 printf (_("%s is %s\n"), command, full_path);
7117c2d2 394 else if (dflags & (CDESC_REUSABLE|CDESC_PATH_ONLY))
726f6388
JA
395 printf ("%s\n", full_path);
396
397 free (full_path);
398 full_path = (char *)NULL;
399
b72432fd 400 if (all == 0)
726f6388
JA
401 break;
402 }
403
404 return (found);
405}