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