]> git.ipfire.org Git - thirdparty/bash.git/blob - builtins/hash.def
Imported from ../bash-2.0.tar.gz.
[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, 1989, 1991 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 hash.c
23
24 $BUILTIN hash
25 $FUNCTION hash_builtin
26 $SHORT_DOC hash [-r] [-p pathname] [name ...]
27 For each NAME, the full pathname of the command is determined and
28 remembered. If the -p option is supplied, PATHNAME is used as the
29 full pathname of NAME, and no path search is performed. The -r
30 option causes the shell to forget all remembered locations. If no
31 arguments are given, information about remembered commands is displayed.
32 $END
33
34 #include <config.h>
35
36 #include <sys/types.h>
37 #include "../posixstat.h"
38
39 #include <stdio.h>
40
41 #if defined (HAVE_UNISTD_H)
42 # include <unistd.h>
43 #endif
44
45 #include "../bashansi.h"
46
47 #include "../shell.h"
48 #include "../builtins.h"
49 #include "../flags.h"
50 #include "../execute_cmd.h"
51 #include "hashcom.h"
52 #include "common.h"
53 #include "bashgetopt.h"
54
55 extern int dot_found_in_search;
56 extern char *this_command_name;
57
58 static int add_hashed_command ();
59 static int print_hashed_commands ();
60
61 static int hashing_initialized = 0;
62
63 HASH_TABLE *hashed_filenames;
64
65 void
66 initialize_filename_hashing ()
67 {
68 if (hashing_initialized == 0)
69 {
70 hashed_filenames = make_hash_table (FILENAME_HASH_BUCKETS);
71 hashing_initialized = 1;
72 }
73 }
74
75 static void
76 free_filename_data (data)
77 char *data;
78 {
79 free (((PATH_DATA *)data)->path);
80 free (data);
81 }
82
83 void
84 flush_hashed_filenames ()
85 {
86 flush_hash_table (hashed_filenames, free_filename_data);
87 }
88
89 /* Remove FILENAME from the table of hashed commands. */
90 void
91 remove_hashed_filename (filename)
92 char *filename;
93 {
94 register BUCKET_CONTENTS *item;
95
96 if (hashing_enabled == 0)
97 return;
98
99 item = remove_hash_item (filename, hashed_filenames);
100 if (item)
101 {
102 if (item->data)
103 free_filename_data (item->data);
104 free (item->key);
105 free (item);
106 }
107 }
108
109 /* Print statistics on the current state of hashed commands. If LIST is
110 not empty, then rehash (or hash in the first place) the specified
111 commands. */
112 int
113 hash_builtin (list)
114 WORD_LIST *list;
115 {
116 int expunge_hash_table, opt;
117 char *word, *pathname;
118
119 if (hashing_enabled == 0)
120 {
121 builtin_error ("hashing disabled");
122 return (EXECUTION_FAILURE);
123 }
124
125 expunge_hash_table = 0;
126 pathname = (char *)NULL;
127 reset_internal_getopt ();
128 while ((opt = internal_getopt (list, "rp:")) != -1)
129 {
130 switch (opt)
131 {
132 case 'r':
133 expunge_hash_table = 1;
134 break;
135 case 'p':
136 pathname = list_optarg;
137 break;
138 default:
139 builtin_usage ();
140 return (EX_USAGE);
141 }
142 }
143 list = loptend;
144
145 /* We want hash -r to be silent, but hash -- to print hashing info. That
146 is the reason for the test of expunge_hash_table. */
147 if (list == 0 && expunge_hash_table == 0)
148 {
149 if (print_hashed_commands () == 0)
150 printf ("%s: hash table empty\n", this_command_name);
151
152 return (EXECUTION_SUCCESS);
153 }
154
155 if (expunge_hash_table)
156 flush_hashed_filenames ();
157
158 for (opt = EXECUTION_SUCCESS; list; list = list->next)
159 {
160 /* Add or rehash the specified commands. */
161 word = list->word->word;
162 if (pathname)
163 remember_filename (word, pathname, 0, 0);
164 else
165 {
166 if (absolute_program (word))
167 {
168 list = list->next;
169 continue;
170 }
171
172 if (add_hashed_command (word))
173 opt = EXECUTION_FAILURE;
174 }
175 }
176
177 fflush (stdout);
178
179 return (opt);
180 }
181
182 /* Place FILENAME (key) and FULL_PATHNAME (data->path) into the
183 hash table. CHECK_DOT if non-null is for future calls to
184 find_hashed_filename (); it means that this file was found
185 in a directory in $PATH that is not an absolute pathname.
186 FOUND is the initial value for times_found. */
187 void
188 remember_filename (filename, full_pathname, check_dot, found)
189 char *filename, *full_pathname;
190 int check_dot, found;
191 {
192 register BUCKET_CONTENTS *item;
193
194 if (hashing_enabled == 0)
195 return;
196
197 item = add_hash_item (filename, hashed_filenames);
198 if (item->data)
199 free (pathdata(item)->path);
200 else
201 {
202 item->key = savestring (filename);
203 item->data = xmalloc (sizeof (PATH_DATA));
204 }
205 pathdata(item)->path = savestring (full_pathname);
206 pathdata(item)->flags = 0;
207 if (check_dot)
208 pathdata(item)->flags |= HASH_CHKDOT;
209 if (*full_pathname != '/')
210 pathdata(item)->flags |= HASH_RELPATH;
211 item->times_found = found;
212 }
213
214 static int
215 add_hashed_command (word, quiet)
216 char *word;
217 int quiet;
218 {
219 int rv;
220 char *full_path;
221
222 rv = 0;
223 if (find_function (word) == 0 && find_shell_builtin (word) == 0)
224 {
225 full_path = find_user_command (word);
226 if (full_path && executable_file (full_path))
227 remember_filename (word, full_path, dot_found_in_search, 0);
228 else
229 {
230 if (quiet == 0)
231 builtin_error ("%s: not found", word);
232 rv++;
233 }
234 if (full_path)
235 free (full_path);
236 }
237 return (rv);
238 }
239
240 /* Print information about current hashed info. */
241 static int
242 print_hashed_commands ()
243 {
244 BUCKET_CONTENTS *item_list;
245 int bucket, any_printed;
246
247 for (bucket = any_printed = 0; bucket < hashed_filenames->nbuckets; bucket++)
248 {
249 item_list = get_hash_bucket (bucket, hashed_filenames);
250 if (item_list == 0)
251 continue;
252
253 if (any_printed == 0)
254 {
255 printf ("hits\tcommand\n");
256 any_printed++;
257 }
258
259 for ( ; item_list; item_list = item_list->next)
260 printf ("%4d\t%s\n", item_list->times_found, pathdata(item_list)->path);
261
262 }
263 return (any_printed);
264 }