]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
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 | |
ccc6cda3 | 26 | $SHORT_DOC type [-apt] name [name ...] |
726f6388 JA |
27 | For each NAME, indicate how it would be interpreted if used as a |
28 | command name. | |
29 | ||
ccc6cda3 | 30 | If the -t option is used, returns a single word which is one of |
726f6388 JA |
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 | ||
ccc6cda3 JA |
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'. | |
726f6388 | 37 | |
ccc6cda3 | 38 | If the -a flag is used, displays all of the places that contain an |
726f6388 | 39 | executable named `file'. This includes aliases and functions, if and |
ccc6cda3 JA |
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. | |
726f6388 JA |
44 | $END |
45 | ||
ccc6cda3 JA |
46 | #include <config.h> |
47 | ||
48 | #include "../bashtypes.h" | |
726f6388 | 49 | #include "../posixstat.h" |
ccc6cda3 JA |
50 | |
51 | #if defined (HAVE_UNISTD_H) | |
52 | # include <unistd.h> | |
53 | #endif | |
54 | ||
55 | #include <stdio.h> | |
56 | #include "../bashansi.h" | |
57 | ||
726f6388 JA |
58 | #include "../shell.h" |
59 | #include "../execute_cmd.h" | |
d166f048 | 60 | #include "../hashcmd.h" |
726f6388 JA |
61 | |
62 | #if defined (ALIAS) | |
63 | #include "../alias.h" | |
64 | #endif /* ALIAS */ | |
65 | ||
66 | #include "common.h" | |
67 | ||
ccc6cda3 | 68 | extern int find_reserved_word (); |
726f6388 JA |
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 | */ | |
ccc6cda3 | 91 | int |
726f6388 JA |
92 | type_builtin (list) |
93 | WORD_LIST *list; | |
94 | { | |
95 | int path_only, type_only, all, verbose; | |
96 | int successful_finds; | |
97 | ||
ccc6cda3 JA |
98 | if (list == 0) |
99 | return (EXECUTION_SUCCESS); | |
100 | ||
726f6388 JA |
101 | path_only = type_only = all = 0; |
102 | successful_finds = 0; | |
103 | ||
726f6388 JA |
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); | |
ccc6cda3 | 125 | builtin_usage (); |
726f6388 JA |
126 | return (EX_USAGE); |
127 | } | |
128 | list = list->next; | |
129 | } | |
130 | ||
131 | if (type_only) | |
132 | verbose = 1; | |
ccc6cda3 | 133 | else if (path_only == 0) |
726f6388 JA |
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 | */ | |
ccc6cda3 | 173 | int |
726f6388 JA |
174 | describe_command (command, verbose, all) |
175 | char *command; | |
176 | int verbose, all; | |
177 | { | |
ccc6cda3 JA |
178 | int found, i, found_file; |
179 | char *full_path; | |
726f6388 | 180 | SHELL_VAR *func; |
ccc6cda3 JA |
181 | #if defined (ALIAS) |
182 | alias_t *alias; | |
183 | #endif | |
184 | ||
185 | found = found_file = 0; | |
186 | full_path = (char *)NULL; | |
726f6388 JA |
187 | |
188 | #if defined (ALIAS) | |
189 | /* Command is an alias? */ | |
ccc6cda3 | 190 | alias = find_alias (command); |
726f6388 JA |
191 | |
192 | if (alias) | |
193 | { | |
194 | if (verbose == 1) | |
ccc6cda3 | 195 | puts ("alias"); |
726f6388 JA |
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) | |
ccc6cda3 | 217 | puts ("keyword"); |
726f6388 JA |
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) | |
ccc6cda3 | 235 | puts ("function"); |
726f6388 JA |
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) | |
ccc6cda3 | 264 | puts ("builtin"); |
726f6388 JA |
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) | |
ccc6cda3 | 285 | puts ("file"); |
726f6388 JA |
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) | |
ccc6cda3 | 305 | puts ("file"); |
726f6388 JA |
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 | ||
d166f048 | 311 | free (full_path); |
726f6388 JA |
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) | |
ccc6cda3 | 333 | puts ("file"); |
726f6388 JA |
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 | } |