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