]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/hash.def
Bash-4.2 patch 34
[thirdparty/bash.git] / builtins / hash.def
1 This file is hash.def, from which is created hash.c.
2 It implements the builtin "hash" in Bash.
3
4 Copyright (C) 1987-2010 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
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Bash is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Bash. If not, see <http://www.gnu.org/licenses/>.
20
21 $PRODUCES hash.c
22
23 $BUILTIN hash
24 $FUNCTION hash_builtin
25 $SHORT_DOC hash [-lr] [-p pathname] [-dt] [name ...]
26 Remember or display program locations.
27
28 Determine and remember the full pathname of each command NAME. If
29 no arguments are given, information about remembered commands is displayed.
30
31 Options:
32 -d forget the remembered location of each NAME
33 -l display in a format that may be reused as input
34 -p pathname use PATHNAME is the full pathname of NAME
35 -r forget all remembered locations
36 -t print the remembered location of each NAME, preceding
37 each location with the corresponding NAME if multiple
38 NAMEs are given
39 Arguments:
40 NAME Each NAME is searched for in $PATH and added to the list
41 of remembered commands.
42
43 Exit Status:
44 Returns success unless NAME is not found or an invalid option is given.
45 $END
46
47 #include <config.h>
48
49 #include <stdio.h>
50
51 #include "../bashtypes.h"
52
53 #if defined (HAVE_UNISTD_H)
54 # include <unistd.h>
55 #endif
56
57 #include <errno.h>
58
59 #include "../bashansi.h"
60 #include "../bashintl.h"
61
62 #include "../shell.h"
63 #include "../builtins.h"
64 #include "../flags.h"
65 #include "../findcmd.h"
66 #include "../hashcmd.h"
67 #include "common.h"
68 #include "bashgetopt.h"
69
70 extern int posixly_correct;
71 extern int dot_found_in_search;
72 extern char *this_command_name;
73
74 static int add_hashed_command __P((char *, int));
75 static int print_hash_info __P((BUCKET_CONTENTS *));
76 static int print_portable_hash_info __P((BUCKET_CONTENTS *));
77 static int print_hashed_commands __P((int));
78 static int list_hashed_filename_targets __P((WORD_LIST *, int));
79
80 /* Print statistics on the current state of hashed commands. If LIST is
81 not empty, then rehash (or hash in the first place) the specified
82 commands. */
83 int
84 hash_builtin (list)
85 WORD_LIST *list;
86 {
87 int expunge_hash_table, list_targets, list_portably, delete, opt;
88 char *w, *pathname;
89
90 if (hashing_enabled == 0)
91 {
92 builtin_error (_("hashing disabled"));
93 return (EXECUTION_FAILURE);
94 }
95
96 expunge_hash_table = list_targets = list_portably = delete = 0;
97 pathname = (char *)NULL;
98 reset_internal_getopt ();
99 while ((opt = internal_getopt (list, "dlp:rt")) != -1)
100 {
101 switch (opt)
102 {
103 case 'd':
104 delete = 1;
105 break;
106 case 'l':
107 list_portably = 1;
108 break;
109 case 'p':
110 pathname = list_optarg;
111 break;
112 case 'r':
113 expunge_hash_table = 1;
114 break;
115 case 't':
116 list_targets = 1;
117 break;
118 default:
119 builtin_usage ();
120 return (EX_USAGE);
121 }
122 }
123 list = loptend;
124
125 /* hash -t requires at least one argument. */
126 if (list == 0 && list_targets)
127 {
128 sh_needarg ("-t");
129 return (EXECUTION_FAILURE);
130 }
131
132 /* We want hash -r to be silent, but hash -- to print hashing info, so
133 we test expunge_hash_table. */
134 if (list == 0 && expunge_hash_table == 0)
135 {
136 opt = print_hashed_commands (list_portably);
137 if (opt == 0 && posixly_correct == 0)
138 printf (_("%s: hash table empty\n"), this_command_name);
139
140 return (EXECUTION_SUCCESS);
141 }
142
143 if (expunge_hash_table)
144 phash_flush ();
145
146 /* If someone runs `hash -r -t xyz' he will be disappointed. */
147 if (list_targets)
148 return (list_hashed_filename_targets (list, list_portably));
149
150 #if defined (RESTRICTED_SHELL)
151 if (restricted && pathname && strchr (pathname, '/'))
152 {
153 sh_restricted (pathname);
154 return (EXECUTION_FAILURE);
155 }
156 #endif
157
158 for (opt = EXECUTION_SUCCESS; list; list = list->next)
159 {
160 /* Add, remove or rehash the specified commands. */
161 w = list->word->word;
162 if (absolute_program (w))
163 continue;
164 else if (pathname)
165 {
166 if (is_directory (pathname))
167 {
168 #ifdef EISDIR
169 builtin_error ("%s: %s", pathname, strerror (EISDIR));
170 #else
171 builtin_error (_("%s: is a directory"), pathname);
172 #endif
173 opt = EXECUTION_FAILURE;
174 }
175 else
176 phash_insert (w, pathname, 0, 0);
177 }
178 else if (delete)
179 {
180 if (phash_remove (w))
181 {
182 sh_notfound (w);
183 opt = EXECUTION_FAILURE;
184 }
185 }
186 else if (add_hashed_command (w, 0))
187 opt = EXECUTION_FAILURE;
188 }
189
190 fflush (stdout);
191 return (opt);
192 }
193
194 static int
195 add_hashed_command (w, quiet)
196 char *w;
197 int quiet;
198 {
199 int rv;
200 char *full_path;
201
202 rv = 0;
203 if (find_function (w) == 0 && find_shell_builtin (w) == 0)
204 {
205 phash_remove (w);
206 full_path = find_user_command (w);
207 if (full_path && executable_file (full_path))
208 phash_insert (w, full_path, dot_found_in_search, 0);
209 else
210 {
211 if (quiet == 0)
212 sh_notfound (w);
213 rv++;
214 }
215 FREE (full_path);
216 }
217 return (rv);
218 }
219
220 /* Print information about current hashed info. */
221 static int
222 print_hash_info (item)
223 BUCKET_CONTENTS *item;
224 {
225 printf ("%4d\t%s\n", item->times_found, pathdata(item)->path);
226 return 0;
227 }
228
229 static int
230 print_portable_hash_info (item)
231 BUCKET_CONTENTS *item;
232 {
233 printf ("builtin hash -p %s %s\n", pathdata(item)->path, item->key);
234 return 0;
235 }
236
237 static int
238 print_hashed_commands (fmt)
239 int fmt;
240 {
241 if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
242 return (0);
243
244 if (fmt == 0)
245 printf (_("hits\tcommand\n"));
246 hash_walk (hashed_filenames, fmt ? print_portable_hash_info : print_hash_info);
247 return (1);
248 }
249
250 static int
251 list_hashed_filename_targets (list, fmt)
252 WORD_LIST *list;
253 int fmt;
254 {
255 int all_found, multiple;
256 char *target;
257 WORD_LIST *l;
258
259 all_found = 1;
260 multiple = list->next != 0;
261
262 for (l = list; l; l = l->next)
263 {
264 target = phash_search (l->word->word);
265 if (target == 0)
266 {
267 all_found = 0;
268 sh_notfound (l->word->word);
269 continue;
270 }
271 if (fmt)
272 printf ("builtin hash -p %s %s\n", target, l->word->word);
273 else
274 {
275 if (multiple)
276 printf ("%s\t", l->word->word);
277 printf ("%s\n", target);
278 }
279 }
280
281 return (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
282 }