]> git.ipfire.org Git - thirdparty/bash.git/blame - builtins/type.def
Imported from ../bash-2.05.tar.gz.
[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
4Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
5
6This file is part of GNU Bash, the Bourne Again SHell.
7
8Bash is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
bb70624e 10Software Foundation; either version 2, or (at your option) any later
726f6388
JA
11version.
12
13Bash is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License along
19with Bash; see the file COPYING. If not, write to the Free Software
bb70624e 20Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
726f6388
JA
21
22$PRODUCES type.c
23
24$BUILTIN type
25$FUNCTION type_builtin
ccc6cda3 26$SHORT_DOC type [-apt] name [name ...]
726f6388
JA
27For each NAME, indicate how it would be interpreted if used as a
28command name.
29
cce855bc 30If the -t option is used, `type' outputs a single word which is one of
726f6388
JA
31`alias', `keyword', `function', `builtin', `file' or `', if NAME is an
32alias, shell reserved word, shell function, shell builtin, disk file,
33or unfound, respectively.
34
cce855bc
JA
35If the -p flag is used, `type' either returns the name of the disk
36file that would be executed, or nothing if `type -t NAME' would not
37return `file'.
726f6388 38
cce855bc
JA
39If the -a flag is used, `type' displays all of the places that contain
40an executable named `file'. This includes aliases and functions, if
41and only if the -p flag is not also used.
726f6388
JA
42$END
43
ccc6cda3
JA
44#include <config.h>
45
46#include "../bashtypes.h"
bb70624e 47#include "posixstat.h"
ccc6cda3
JA
48
49#if defined (HAVE_UNISTD_H)
50# include <unistd.h>
51#endif
52
53#include <stdio.h>
54#include "../bashansi.h"
55
726f6388 56#include "../shell.h"
cce855bc 57#include "../findcmd.h"
d166f048 58#include "../hashcmd.h"
726f6388
JA
59
60#if defined (ALIAS)
61#include "../alias.h"
62#endif /* ALIAS */
63
64#include "common.h"
b72432fd 65#include "bashgetopt.h"
726f6388 66
ccc6cda3 67extern int find_reserved_word ();
726f6388 68
bb70624e
JA
69extern char *this_command_name;
70
726f6388
JA
71/* For each word in LIST, find out what the shell is going to do with
72 it as a simple command. i.e., which file would this shell use to
73 execve, or if it is a builtin command, or an alias. Possible flag
74 arguments:
b72432fd 75 -t Returns the "type" of the object, one of
726f6388
JA
76 `alias', `keyword', `function', `builtin',
77 or `file'.
78
b72432fd 79 -p Returns the pathname of the file if -type is
726f6388
JA
80 a file.
81
b72432fd 82 -a Returns all occurrences of words, whether they
726f6388
JA
83 be a filename in the path, alias, function,
84 or builtin.
85 Order of evaluation:
86 alias
87 keyword
88 function
89 builtin
90 file
91 */
b72432fd 92
ccc6cda3 93int
726f6388
JA
94type_builtin (list)
95 WORD_LIST *list;
96{
97 int path_only, type_only, all, verbose;
b72432fd
JA
98 int successful_finds, opt;
99 WORD_LIST *prev, *this;
726f6388 100
ccc6cda3
JA
101 if (list == 0)
102 return (EXECUTION_SUCCESS);
103
726f6388
JA
104 path_only = type_only = all = 0;
105 successful_finds = 0;
106
b72432fd
JA
107 /* Handle the obsolescent `-type', `-path', and `-all' by prescanning
108 the arguments and removing those options from the list before calling
109 internal_getopt. Recognize `--type', `--path', and `--all' also.
110 THIS SHOULD REALLY GO AWAY. */
111 for (this = list; this && this->word->word[0] == '-'; )
726f6388 112 {
b72432fd 113 char *flag = &(this->word->word[1]);
726f6388 114
b72432fd 115 if (STREQ (flag, "type") || STREQ (flag, "-type"))
726f6388
JA
116 {
117 type_only = 1;
118 path_only = 0;
119 }
b72432fd 120 else if (STREQ (flag, "path") || STREQ (flag, "-path"))
726f6388
JA
121 {
122 path_only = 1;
123 type_only = 0;
124 }
b72432fd 125 else if (STREQ (flag, "all") || STREQ (flag, "-all"))
28ef6c31 126 all = 1;
b72432fd 127 else
726f6388 128 {
28ef6c31
JA
129 prev = this;
130 this = this->next;
131 continue;
726f6388 132 }
b72432fd
JA
133
134 /* We found a long option; remove it from the argument list. Don't
135 free it if it's the head of the argument list, though -- the
136 argument list will be freed by the caller. */
137 if (this == list)
138 this = list = list->next;
726f6388
JA
139 else
140 {
b72432fd
JA
141 prev->next = this->next;
142 this->next = (WORD_LIST *)NULL;
143 dispose_words (this);
144 this = prev->next;
145 }
146 }
147
148 reset_internal_getopt ();
149 while ((opt = internal_getopt (list, "apt")) != -1)
150 {
151 switch (opt)
152 {
153 case 't':
154 type_only = 1;
155 path_only = 0;
156 break;
157 case 'p':
158 path_only = 1;
159 type_only = 0;
160 break;
161 case 'a':
162 all = 1;
163 break;
164 default:
ccc6cda3 165 builtin_usage ();
726f6388
JA
166 return (EX_USAGE);
167 }
726f6388 168 }
b72432fd 169 list = loptend;
726f6388
JA
170
171 if (type_only)
172 verbose = 1;
ccc6cda3 173 else if (path_only == 0)
726f6388
JA
174 verbose = 2;
175 else if (path_only)
176 verbose = 3;
177 else
178 verbose = 0;
179
180 while (list)
181 {
182 int found;
183
184 found = describe_command (list->word->word, verbose, all);
185
186 if (!found && !path_only && !type_only)
187 builtin_error ("%s: not found", list->word->word);
188
189 successful_finds += found;
190 list = list->next;
191 }
192
193 fflush (stdout);
194
b72432fd 195 return ((successful_finds != 0) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
726f6388
JA
196}
197
198/*
199 * Describe COMMAND as required by the type builtin.
200 *
201 * If VERBOSE == 0, don't print anything
202 * If VERBOSE == 1, print short description as for `type -t'
203 * If VERBOSE == 2, print long description as for `type' and `command -V'
204 * If VERBOSE == 3, print path name only for disk files
205 * If VERBOSE == 4, print string used to invoke COMMAND, for `command -v'
206 *
207 * ALL says whether or not to look for all occurrences of COMMAND, or
208 * return after finding it once.
209 */
ccc6cda3 210int
726f6388
JA
211describe_command (command, verbose, all)
212 char *command;
213 int verbose, all;
214{
bb70624e
JA
215 int found, i, found_file, f;
216 char *full_path, *x, *cwd;
726f6388 217 SHELL_VAR *func;
ccc6cda3
JA
218#if defined (ALIAS)
219 alias_t *alias;
220#endif
221
222 found = found_file = 0;
223 full_path = (char *)NULL;
726f6388
JA
224
225#if defined (ALIAS)
226 /* Command is an alias? */
ccc6cda3 227 alias = find_alias (command);
726f6388
JA
228
229 if (alias)
230 {
231 if (verbose == 1)
ccc6cda3 232 puts ("alias");
726f6388
JA
233 else if (verbose == 2)
234 printf ("%s is aliased to `%s'\n", command, alias->value);
235 else if (verbose == 4)
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? */
250 i = find_reserved_word (command);
251 if (i >= 0)
252 {
253 if (verbose == 1)
ccc6cda3 254 puts ("keyword");
726f6388
JA
255 else if (verbose == 2)
256 printf ("%s is a shell keyword\n", command);
257 else if (verbose == 4)
258 printf ("%s\n", command);
259
260 found = 1;
261
b72432fd 262 if (all == 0)
726f6388
JA
263 return (1);
264 }
265
266 /* Command is a function? */
267 func = find_function (command);
268
269 if (func)
270 {
271 if (verbose == 1)
ccc6cda3 272 puts ("function");
726f6388
JA
273 else if (verbose == 2)
274 {
275#define PRETTY_PRINT_FUNC 1
276 char *result;
277
278 printf ("%s is a function\n", command);
279
280 /* We're blowing away THE_PRINTED_COMMAND here... */
281
282 result = named_function_string (command,
283 (COMMAND *) function_cell (func),
284 PRETTY_PRINT_FUNC);
285 printf ("%s\n", result);
286#undef PRETTY_PRINT_FUNC
287 }
288 else if (verbose == 4)
289 printf ("%s\n", command);
290
291 found = 1;
292
b72432fd 293 if (all == 0)
726f6388
JA
294 return (1);
295 }
296
297 /* Command is a builtin? */
298 if (find_shell_builtin (command))
299 {
300 if (verbose == 1)
ccc6cda3 301 puts ("builtin");
726f6388
JA
302 else if (verbose == 2)
303 printf ("%s is a shell builtin\n", command);
304 else if (verbose == 4)
305 printf ("%s\n", command);
306
307 found = 1;
308
b72432fd 309 if (all == 0)
726f6388
JA
310 return (1);
311 }
312
313 /* Command is a disk file? */
314 /* If the command name given is already an absolute command, just
315 check to see if it is executable. */
316 if (absolute_program (command))
317 {
bb70624e 318 f = file_status (command);
726f6388 319 if (f & FS_EXECABLE)
28ef6c31 320 {
726f6388 321 if (verbose == 1)
ccc6cda3 322 puts ("file");
726f6388
JA
323 else if (verbose == 2)
324 printf ("%s is %s\n", command, command);
325 else if (verbose == 3 || verbose == 4)
326 printf ("%s\n", command);
327
328 /* There's no use looking in the hash table or in $PATH,
329 because they're not consulted when an absolute program
330 name is supplied. */
331 return (1);
28ef6c31 332 }
726f6388
JA
333 }
334
b72432fd 335 /* If the user isn't doing "-a", then we might care about
726f6388 336 whether the file is present in our hash table. */
b72432fd 337 if (all == 0)
726f6388
JA
338 {
339 if ((full_path = find_hashed_filename (command)) != (char *)NULL)
340 {
341 if (verbose == 1)
ccc6cda3 342 puts ("file");
726f6388
JA
343 else if (verbose == 2)
344 printf ("%s is hashed (%s)\n", command, full_path);
345 else if (verbose == 3 || verbose == 4)
346 printf ("%s\n", full_path);
347
d166f048 348 free (full_path);
726f6388
JA
349 return (1);
350 }
351 }
352
353 /* Now search through $PATH. */
354 while (1)
355 {
b72432fd 356 if (all == 0)
726f6388
JA
357 full_path = find_user_command (command);
358 else
359 full_path =
360 user_command_matches (command, FS_EXEC_ONLY, found_file);
361 /* XXX - should that be FS_EXEC_PREFERRED? */
362
363 if (!full_path)
364 break;
365
bb70624e
JA
366 /* If we found the command as itself by looking through $PATH, it
367 probably doesn't exist. Check whether or not the command is an
368 executable file. If it's not, don't report a match. */
369 if (STREQ (full_path, command))
370 {
371 f = file_status (full_path);
372 if ((f & FS_EXECABLE) == 0)
373 {
374 free (full_path);
375 full_path = (char *)NULL;
376 if (all == 0)
377 break;
378 }
379 else if (verbose >= 2)
380 full_path = sh_makepath ((char *)NULL, full_path, MP_DOCWD);
381 }
382
726f6388
JA
383 found_file++;
384 found = 1;
385
386 if (verbose == 1)
ccc6cda3 387 puts ("file");
726f6388
JA
388 else if (verbose == 2)
389 printf ("%s is %s\n", command, full_path);
390 else if (verbose == 3 || verbose == 4)
391 printf ("%s\n", full_path);
392
393 free (full_path);
394 full_path = (char *)NULL;
395
b72432fd 396 if (all == 0)
726f6388
JA
397 break;
398 }
399
400 return (found);
401}