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