]>
Commit | Line | Data |
---|---|---|
726f6388 JA |
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] [name ...] | |
27 | For each NAME, the full pathname of the command is determined and | |
28 | remembered. The -r option causes the shell to forget all remembered | |
29 | locations. If no arguments are given, information about remembered | |
30 | commands is presented. | |
31 | $END | |
32 | ||
33 | #include <sys/types.h> | |
34 | #include "../posixstat.h" | |
35 | ||
36 | #include <stdio.h> | |
37 | ||
38 | #if defined (HAVE_STRING_H) | |
39 | # include <string.h> | |
40 | #else /* !HAVE_STRING_H */ | |
41 | # include <strings.h> | |
42 | #endif /* !HAVE_STRING_H */ | |
43 | ||
44 | #include "../shell.h" | |
45 | #include "../builtins.h" | |
46 | #include "../flags.h" | |
47 | #include "hashcom.h" | |
48 | #include "common.h" | |
49 | #include "../execute_cmd.h" | |
50 | ||
51 | extern int dot_found_in_search; | |
52 | ||
53 | void | |
54 | initialize_filename_hashing () | |
55 | { | |
56 | hashed_filenames = make_hash_table (FILENAME_HASH_BUCKETS); | |
57 | } | |
58 | ||
59 | /* Print statistics on the current state of hashed commands. If LIST is | |
60 | not empty, then rehash (or hash in the first place) the specified | |
61 | commands. */ | |
62 | hash_builtin (list) | |
63 | WORD_LIST *list; | |
64 | { | |
65 | int expunge_hash_table = 0; | |
66 | int any_failed = 0; | |
67 | ||
68 | if (hashing_disabled) | |
69 | { | |
70 | builtin_error ("hashing disabled"); | |
71 | return (EXECUTION_FAILURE); | |
72 | } | |
73 | ||
74 | while (list) | |
75 | { | |
76 | char *arg = list->word->word; | |
77 | ||
78 | if (ISOPTION (arg, 'r')) | |
79 | { | |
80 | expunge_hash_table = 1; | |
81 | list = list->next; | |
82 | } | |
83 | else if (ISOPTION (arg, '-')) | |
84 | { | |
85 | list = list->next; | |
86 | break; | |
87 | } | |
88 | else if (*arg == '-') | |
89 | { | |
90 | bad_option (list->word->word); | |
91 | builtin_error ("usage: hash [-r] [command ...]"); | |
92 | return (EX_USAGE); | |
93 | } | |
94 | else | |
95 | break; | |
96 | } | |
97 | ||
98 | /* We want hash -r to be silent, but hash -- to print hashing info. That | |
99 | is the reason for the !expunge_hash_table. */ | |
100 | if (!list && !expunge_hash_table) | |
101 | { | |
102 | /* Print information about current hashed info. */ | |
103 | int any_printed = 0; | |
104 | int bucket = 0; | |
105 | register BUCKET_CONTENTS *item_list; | |
106 | ||
107 | while (bucket < hashed_filenames->nbuckets) | |
108 | { | |
109 | item_list = get_hash_bucket (bucket, hashed_filenames); | |
110 | if (item_list) | |
111 | { | |
112 | if (!any_printed) | |
113 | { | |
114 | printf ("hits\tcommand\n"); | |
115 | any_printed++; | |
116 | } | |
117 | while (item_list) | |
118 | { | |
119 | printf ("%4d\t%s\n", | |
120 | item_list->times_found, pathdata(item_list)->path); | |
121 | item_list = item_list->next; | |
122 | } | |
123 | } | |
124 | bucket++; | |
125 | } | |
126 | ||
127 | if (!any_printed) | |
128 | printf ("No commands in hash table.\n"); | |
129 | ||
130 | return (EXECUTION_SUCCESS); | |
131 | } | |
132 | ||
133 | if (expunge_hash_table) | |
134 | { | |
135 | int bucket = 0; | |
136 | register BUCKET_CONTENTS *item_list, *prev; | |
137 | ||
138 | while (bucket < hashed_filenames->nbuckets) | |
139 | { | |
140 | item_list = get_hash_bucket (bucket, hashed_filenames); | |
141 | if (item_list) | |
142 | { | |
143 | while (item_list) | |
144 | { | |
145 | prev = item_list; | |
146 | free (item_list->key); | |
147 | free (pathdata(item_list)->path); | |
148 | free (item_list->data); | |
149 | item_list = item_list->next; | |
150 | free (prev); | |
151 | } | |
152 | hashed_filenames->bucket_array[bucket] = (BUCKET_CONTENTS *)NULL; | |
153 | } | |
154 | bucket++; | |
155 | } | |
156 | } | |
157 | ||
158 | while (list) | |
159 | { | |
160 | /* Add or rehash the specified commands. */ | |
161 | char *word; | |
162 | char *full_path; | |
163 | SHELL_VAR *var; | |
164 | ||
165 | word = list->word->word; | |
166 | if (absolute_program (word)) | |
167 | { | |
168 | list = list->next; | |
169 | continue; | |
170 | } | |
171 | full_path = find_user_command (word); | |
172 | var = find_function (word); | |
173 | ||
174 | if (!find_shell_builtin (word) && (!var)) | |
175 | { | |
176 | if (full_path && executable_file (full_path)) | |
177 | remember_filename (word, full_path, dot_found_in_search, 0); | |
178 | else | |
179 | { | |
180 | builtin_error ("%s: not found", word); | |
181 | any_failed++; | |
182 | } | |
183 | } | |
184 | if (full_path) | |
185 | free (full_path); | |
186 | ||
187 | list = list->next; | |
188 | } | |
189 | ||
190 | fflush (stdout); | |
191 | ||
192 | if (any_failed) | |
193 | return (EXECUTION_FAILURE); | |
194 | else | |
195 | return (EXECUTION_SUCCESS); | |
196 | } | |
197 | ||
198 | /* Place FILENAME (key) and FULL_PATHNAME (data->path) into the | |
199 | hash table. CHECK_DOT if non-null is for future calls to | |
200 | find_hashed_filename (). FOUND is the initial value for | |
201 | times_found. */ | |
202 | void | |
203 | remember_filename (filename, full_pathname, check_dot, found) | |
204 | char *filename, *full_pathname; | |
205 | int check_dot, found; | |
206 | { | |
207 | register BUCKET_CONTENTS *item; | |
208 | ||
209 | if (hashing_disabled) | |
210 | return; | |
211 | item = add_hash_item (filename, hashed_filenames); | |
212 | if (item->data) | |
213 | free (pathdata(item)->path); | |
214 | else | |
215 | { | |
216 | item->key = savestring (filename); | |
217 | item->data = (char *)xmalloc (sizeof (PATH_DATA)); | |
218 | } | |
219 | pathdata(item)->path = savestring (full_pathname); | |
220 | pathdata(item)->check_dot = check_dot; | |
221 | item->times_found = found; | |
222 | } |