]>
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 | ||
cce855bc | 30 | If the -t option is used, `type' outputs 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 | ||
cce855bc JA |
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'. | |
726f6388 | 38 | |
cce855bc JA |
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. | |
726f6388 JA |
42 | $END |
43 | ||
ccc6cda3 JA |
44 | #include <config.h> |
45 | ||
46 | #include "../bashtypes.h" | |
726f6388 | 47 | #include "../posixstat.h" |
ccc6cda3 JA |
48 | |
49 | #if defined (HAVE_UNISTD_H) | |
50 | # include <unistd.h> | |
51 | #endif | |
52 | ||
53 | #include <stdio.h> | |
54 | #include "../bashansi.h" | |
55 | ||
726f6388 | 56 | #include "../shell.h" |
cce855bc | 57 | #include "../findcmd.h" |
d166f048 | 58 | #include "../hashcmd.h" |
726f6388 JA |
59 | |
60 | #if defined (ALIAS) | |
61 | #include "../alias.h" | |
62 | #endif /* ALIAS */ | |
63 | ||
64 | #include "common.h" | |
65 | ||
ccc6cda3 | 66 | extern int find_reserved_word (); |
726f6388 JA |
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 | */ | |
ccc6cda3 | 89 | int |
726f6388 JA |
90 | type_builtin (list) |
91 | WORD_LIST *list; | |
92 | { | |
93 | int path_only, type_only, all, verbose; | |
94 | int successful_finds; | |
95 | ||
ccc6cda3 JA |
96 | if (list == 0) |
97 | return (EXECUTION_SUCCESS); | |
98 | ||
726f6388 JA |
99 | path_only = type_only = all = 0; |
100 | successful_finds = 0; | |
101 | ||
726f6388 JA |
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); | |
ccc6cda3 | 123 | builtin_usage (); |
726f6388 JA |
124 | return (EX_USAGE); |
125 | } | |
126 | list = list->next; | |
127 | } | |
128 | ||
129 | if (type_only) | |
130 | verbose = 1; | |
ccc6cda3 | 131 | else if (path_only == 0) |
726f6388 JA |
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 | */ | |
ccc6cda3 | 171 | int |
726f6388 JA |
172 | describe_command (command, verbose, all) |
173 | char *command; | |
174 | int verbose, all; | |
175 | { | |
ccc6cda3 JA |
176 | int found, i, found_file; |
177 | char *full_path; | |
726f6388 | 178 | SHELL_VAR *func; |
ccc6cda3 JA |
179 | #if defined (ALIAS) |
180 | alias_t *alias; | |
181 | #endif | |
182 | ||
183 | found = found_file = 0; | |
184 | full_path = (char *)NULL; | |
726f6388 JA |
185 | |
186 | #if defined (ALIAS) | |
187 | /* Command is an alias? */ | |
ccc6cda3 | 188 | alias = find_alias (command); |
726f6388 JA |
189 | |
190 | if (alias) | |
191 | { | |
192 | if (verbose == 1) | |
ccc6cda3 | 193 | puts ("alias"); |
726f6388 JA |
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) | |
ccc6cda3 | 215 | puts ("keyword"); |
726f6388 JA |
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) | |
ccc6cda3 | 233 | puts ("function"); |
726f6388 JA |
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) | |
ccc6cda3 | 262 | puts ("builtin"); |
726f6388 JA |
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) | |
ccc6cda3 | 283 | puts ("file"); |
726f6388 JA |
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) | |
ccc6cda3 | 303 | puts ("file"); |
726f6388 JA |
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 | ||
d166f048 | 309 | free (full_path); |
726f6388 JA |
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) | |
ccc6cda3 | 331 | puts ("file"); |
726f6388 JA |
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 | } |