blob: d28cb610a9186c3a9e4d2d31ba29e0c0921e9b3a [file] [log] [blame]
Dan Pasanenc6e37862014-10-02 14:08:59 -05001/* hash.c, created from hash.def. */
2#line 22 "./hash.def"
3
4#line 46 "./hash.def"
5
6#include <config.h>
7
8#include <stdio.h>
9
10#include "../bashtypes.h"
11
12#if defined (HAVE_UNISTD_H)
13# include <unistd.h>
14#endif
15
16#include <errno.h>
17
18#include "../bashansi.h"
19#include "../bashintl.h"
20
21#include "../shell.h"
22#include "../builtins.h"
23#include "../flags.h"
24#include "../findcmd.h"
25#include "../hashcmd.h"
26#include "common.h"
27#include "bashgetopt.h"
28
29extern int posixly_correct;
30extern int dot_found_in_search;
31extern char *this_command_name;
32
33static int add_hashed_command __P((char *, int));
34static int print_hash_info __P((BUCKET_CONTENTS *));
35static int print_portable_hash_info __P((BUCKET_CONTENTS *));
36static int print_hashed_commands __P((int));
37static int list_hashed_filename_targets __P((WORD_LIST *, int));
38
39/* Print statistics on the current state of hashed commands. If LIST is
40 not empty, then rehash (or hash in the first place) the specified
41 commands. */
42int
43hash_builtin (list)
44 WORD_LIST *list;
45{
46 int expunge_hash_table, list_targets, list_portably, delete, opt;
47 char *w, *pathname;
48
49 if (hashing_enabled == 0)
50 {
51 builtin_error (_("hashing disabled"));
52 return (EXECUTION_FAILURE);
53 }
54
55 expunge_hash_table = list_targets = list_portably = delete = 0;
56 pathname = (char *)NULL;
57 reset_internal_getopt ();
58 while ((opt = internal_getopt (list, "dlp:rt")) != -1)
59 {
60 switch (opt)
61 {
62 case 'd':
63 delete = 1;
64 break;
65 case 'l':
66 list_portably = 1;
67 break;
68 case 'p':
69 pathname = list_optarg;
70 break;
71 case 'r':
72 expunge_hash_table = 1;
73 break;
74 case 't':
75 list_targets = 1;
76 break;
77 default:
78 builtin_usage ();
79 return (EX_USAGE);
80 }
81 }
82 list = loptend;
83
84 /* hash -t requires at least one argument. */
85 if (list == 0 && list_targets)
86 {
87 sh_needarg ("-t");
88 return (EXECUTION_FAILURE);
89 }
90
91 /* We want hash -r to be silent, but hash -- to print hashing info, so
92 we test expunge_hash_table. */
93 if (list == 0 && expunge_hash_table == 0)
94 {
95 opt = print_hashed_commands (list_portably);
96 if (opt == 0 && posixly_correct == 0)
97 printf (_("%s: hash table empty\n"), this_command_name);
98
99 return (EXECUTION_SUCCESS);
100 }
101
102 if (expunge_hash_table)
103 phash_flush ();
104
105 /* If someone runs `hash -r -t xyz' he will be disappointed. */
106 if (list_targets)
107 return (list_hashed_filename_targets (list, list_portably));
108
109#if defined (RESTRICTED_SHELL)
110 if (restricted && pathname && strchr (pathname, '/'))
111 {
112 sh_restricted (pathname);
113 return (EXECUTION_FAILURE);
114 }
115#endif
116
117 for (opt = EXECUTION_SUCCESS; list; list = list->next)
118 {
119 /* Add, remove or rehash the specified commands. */
120 w = list->word->word;
121 if (absolute_program (w))
122 continue;
123 else if (pathname)
124 {
125 if (is_directory (pathname))
126 {
127#ifdef EISDIR
128 builtin_error ("%s: %s", pathname, strerror (EISDIR));
129#else
130 builtin_error (_("%s: is a directory"), pathname);
131#endif
132 opt = EXECUTION_FAILURE;
133 }
134 else
135 phash_insert (w, pathname, 0, 0);
136 }
137 else if (delete)
138 {
139 if (phash_remove (w))
140 {
141 sh_notfound (w);
142 opt = EXECUTION_FAILURE;
143 }
144 }
145 else if (add_hashed_command (w, 0))
146 opt = EXECUTION_FAILURE;
147 }
148
149 fflush (stdout);
150 return (opt);
151}
152
153static int
154add_hashed_command (w, quiet)
155 char *w;
156 int quiet;
157{
158 int rv;
159 char *full_path;
160
161 rv = 0;
162 if (find_function (w) == 0 && find_shell_builtin (w) == 0)
163 {
164 phash_remove (w);
165 full_path = find_user_command (w);
166 if (full_path && executable_file (full_path))
167 phash_insert (w, full_path, dot_found_in_search, 0);
168 else
169 {
170 if (quiet == 0)
171 sh_notfound (w);
172 rv++;
173 }
174 FREE (full_path);
175 }
176 return (rv);
177}
178
179/* Print information about current hashed info. */
180static int
181print_hash_info (item)
182 BUCKET_CONTENTS *item;
183{
184 printf ("%4d\t%s\n", item->times_found, pathdata(item)->path);
185 return 0;
186}
187
188static int
189print_portable_hash_info (item)
190 BUCKET_CONTENTS *item;
191{
192 printf ("builtin hash -p %s %s\n", pathdata(item)->path, item->key);
193 return 0;
194}
195
196static int
197print_hashed_commands (fmt)
198 int fmt;
199{
200 if (hashed_filenames == 0 || HASH_ENTRIES (hashed_filenames) == 0)
201 return (0);
202
203 if (fmt == 0)
204 printf (_("hits\tcommand\n"));
205 hash_walk (hashed_filenames, fmt ? print_portable_hash_info : print_hash_info);
206 return (1);
207}
208
209static int
210list_hashed_filename_targets (list, fmt)
211 WORD_LIST *list;
212 int fmt;
213{
214 int all_found, multiple;
215 char *target;
216 WORD_LIST *l;
217
218 all_found = 1;
219 multiple = list->next != 0;
220
221 for (l = list; l; l = l->next)
222 {
223 target = phash_search (l->word->word);
224 if (target == 0)
225 {
226 all_found = 0;
227 sh_notfound (l->word->word);
228 continue;
229 }
230 if (fmt)
231 printf ("builtin hash -p %s %s\n", target, l->word->word);
232 else
233 {
234 if (multiple)
235 printf ("%s\t", l->word->word);
236 printf ("%s\n", target);
237 }
238 free (target);
239 }
240
241 return (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
242}