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