93c8ff808409119594320fee34fc958f292faeb6
[platform/upstream/bash.git] / builtins / type.def
1 This file is type.def, from which is created type.c.
2 It implements the builtin "type" in Bash.
3
4 Copyright (C) 1987, 1989, 1991, 1992 Free Software Foundation, Inc.
5
6 This file is part of GNU Bash, the Bourne Again SHell.
7
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 1, or (at your option) any later
11 version.
12
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
16 for more details.
17
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, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 $PRODUCES type.c
23
24 $BUILTIN type
25 $FUNCTION type_builtin
26 $SHORT_DOC type [-apt] name [name ...]
27 For each NAME, indicate how it would be interpreted if used as a
28 command name.
29
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.
34
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
37 return `file'.
38
39 If the -a flag is used, `type' displays all of the places that contain
40 an executable named `file'.  This includes aliases and functions, if
41 and only if the -p flag is not also used.
42 $END
43
44 #include <config.h>
45
46 #include "../bashtypes.h"
47 #include "../posixstat.h"
48
49 #if defined (HAVE_UNISTD_H)
50 #  include <unistd.h>
51 #endif
52
53 #include <stdio.h>
54 #include "../bashansi.h"
55
56 #include "../shell.h"
57 #include "../findcmd.h"
58 #include "../hashcmd.h"
59
60 #if defined (ALIAS)
61 #include "../alias.h"
62 #endif /* ALIAS */
63
64 #include "common.h"
65
66 extern int find_reserved_word ();
67
68 /* For each word in LIST, find out what the shell is going to do with
69    it as a simple command. i.e., which file would this shell use to
70    execve, or if it is a builtin command, or an alias.  Possible flag
71    arguments:
72         -type           Returns the "type" of the object, one of
73                         `alias', `keyword', `function', `builtin',
74                         or `file'.
75
76         -path           Returns the pathname of the file if -type is
77                         a file.
78
79         -all            Returns all occurrences of words, whether they
80                         be a filename in the path, alias, function,
81                         or builtin.
82    Order of evaluation:
83         alias
84         keyword
85         function
86         builtin
87         file
88  */
89 int
90 type_builtin (list)
91      WORD_LIST *list;
92 {
93   int path_only, type_only, all, verbose;
94   int successful_finds;
95
96   if (list == 0)
97     return (EXECUTION_SUCCESS);
98
99   path_only = type_only = all = 0;
100   successful_finds = 0;
101
102   while (list && *(list->word->word) == '-')
103     {
104       char *flag = &(list->word->word[1]);
105
106       if (flag[0] == 't' && (!flag[1] || strcmp (flag + 1, "ype") == 0))
107         {
108           type_only = 1;
109           path_only = 0;
110         }
111       else if (flag[0] == 'p' && (!flag[1] || strcmp (flag + 1, "ath") == 0))
112         {
113           path_only = 1;
114           type_only = 0;
115         }
116       else if (flag[0] == 'a' && (!flag[1] || strcmp (flag + 1, "ll") == 0))
117         {
118           all = 1;
119         }
120       else
121         {
122           bad_option (flag);
123           builtin_usage ();
124           return (EX_USAGE);
125         }
126       list = list->next;
127     }
128
129   if (type_only)
130     verbose = 1;
131   else if (path_only == 0)
132     verbose = 2;
133   else if (path_only)
134     verbose = 3;
135   else
136     verbose = 0;
137
138   while (list)
139     {
140       int found;
141
142       found = describe_command (list->word->word, verbose, all);
143
144       if (!found && !path_only && !type_only)
145         builtin_error ("%s: not found", list->word->word);
146
147       successful_finds += found;
148       list = list->next;
149     }
150
151   fflush (stdout);
152
153   if (successful_finds != 0)
154     return (EXECUTION_SUCCESS);
155   else
156     return (EXECUTION_FAILURE);
157 }
158
159 /*
160  * Describe COMMAND as required by the type builtin.
161  *
162  * If VERBOSE == 0, don't print anything
163  * If VERBOSE == 1, print short description as for `type -t'
164  * If VERBOSE == 2, print long description as for `type' and `command -V'
165  * If VERBOSE == 3, print path name only for disk files
166  * If VERBOSE == 4, print string used to invoke COMMAND, for `command -v'
167  *
168  * ALL says whether or not to look for all occurrences of COMMAND, or
169  * return after finding it once.
170  */
171 int
172 describe_command (command, verbose, all)
173      char *command;
174      int verbose, all;
175 {
176   int found, i, found_file;
177   char *full_path;
178   SHELL_VAR *func;
179 #if defined (ALIAS)
180   alias_t *alias;
181 #endif
182
183   found = found_file = 0;
184   full_path = (char *)NULL;
185
186 #if defined (ALIAS)
187   /* Command is an alias? */
188   alias = find_alias (command);
189
190   if (alias)
191     {
192       if (verbose == 1)
193         puts ("alias");
194       else if (verbose == 2)
195         printf ("%s is aliased to `%s'\n", command, alias->value);
196       else if (verbose == 4)
197         {
198           char *x = single_quote (alias->value);
199           printf ("alias %s=%s\n", command, x);
200           free (x);
201         }
202
203       found = 1;
204
205       if (!all)
206         return (1);
207     }
208 #endif /* ALIAS */
209
210   /* Command is a shell reserved word? */
211   i = find_reserved_word (command);
212   if (i >= 0)
213     {
214       if (verbose == 1)
215         puts ("keyword");
216       else if (verbose == 2)
217         printf ("%s is a shell keyword\n", command);
218       else if (verbose == 4)
219         printf ("%s\n", command);
220
221       found = 1;
222
223       if (!all)
224         return (1);
225     }
226
227   /* Command is a function? */
228   func = find_function (command);
229
230   if (func)
231     {
232       if (verbose == 1)
233         puts ("function");
234       else if (verbose == 2)
235         {
236 #define PRETTY_PRINT_FUNC 1
237           char *result;
238
239           printf ("%s is a function\n", command);
240
241           /* We're blowing away THE_PRINTED_COMMAND here... */
242
243           result = named_function_string (command,
244                                           (COMMAND *) function_cell (func),
245                                           PRETTY_PRINT_FUNC);
246           printf ("%s\n", result);
247 #undef PRETTY_PRINT_FUNC
248         }
249       else if (verbose == 4)
250         printf ("%s\n", command);
251
252       found = 1;
253
254       if (!all)
255         return (1);
256     }
257
258   /* Command is a builtin? */
259   if (find_shell_builtin (command))
260     {
261       if (verbose == 1)
262         puts ("builtin");
263       else if (verbose == 2)
264         printf ("%s is a shell builtin\n", command);
265       else if (verbose == 4)
266         printf ("%s\n", command);
267
268       found = 1;
269
270       if (!all)
271         return (1);
272     }
273
274   /* Command is a disk file? */
275   /* If the command name given is already an absolute command, just
276      check to see if it is executable. */
277   if (absolute_program (command))
278     {
279       int f = file_status (command);
280       if (f & FS_EXECABLE)
281         {
282           if (verbose == 1)
283             puts ("file");
284           else if (verbose == 2)
285             printf ("%s is %s\n", command, command);
286           else if (verbose == 3 || verbose == 4)
287             printf ("%s\n", command);
288
289           /* There's no use looking in the hash table or in $PATH,
290              because they're not consulted when an absolute program
291              name is supplied. */
292           return (1);
293         }
294     }
295
296   /* If the user isn't doing "-all", then we might care about
297      whether the file is present in our hash table. */
298   if (!all)
299     {
300       if ((full_path = find_hashed_filename (command)) != (char *)NULL)
301         {
302           if (verbose == 1)
303             puts ("file");
304           else if (verbose == 2)
305             printf ("%s is hashed (%s)\n", command, full_path);
306           else if (verbose == 3 || verbose == 4)
307             printf ("%s\n", full_path);
308
309           free (full_path);
310           return (1);
311         }
312     }
313
314   /* Now search through $PATH. */
315   while (1)
316     {
317       if (!all)
318         full_path = find_user_command (command);
319       else
320         full_path =
321           user_command_matches (command, FS_EXEC_ONLY, found_file);
322           /* XXX - should that be FS_EXEC_PREFERRED? */
323
324       if (!full_path)
325         break;
326
327       found_file++;
328       found = 1;
329
330       if (verbose == 1)
331         puts ("file");
332       else if (verbose == 2)
333         printf ("%s is %s\n", command, full_path);
334       else if (verbose == 3 || verbose == 4)
335         printf ("%s\n", full_path);
336
337       free (full_path);
338       full_path = (char *)NULL;
339
340       if (!all)
341         break;
342     }
343
344   return (found);
345 }