]>
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 | |
bb70624e | 10 | Software Foundation; either version 2, or (at your option) any later |
726f6388 JA |
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 | |
bb70624e | 20 | Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. |
726f6388 JA |
21 | |
22 | $PRODUCES hash.c | |
23 | ||
24 | $BUILTIN hash | |
25 | $FUNCTION hash_builtin | |
ccc6cda3 | 26 | $SHORT_DOC hash [-r] [-p pathname] [name ...] |
726f6388 | 27 | For each NAME, the full pathname of the command is determined and |
ccc6cda3 JA |
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. | |
726f6388 JA |
32 | $END |
33 | ||
ccc6cda3 JA |
34 | #include <config.h> |
35 | ||
726f6388 JA |
36 | #include <stdio.h> |
37 | ||
cce855bc JA |
38 | #include "../bashtypes.h" |
39 | ||
ccc6cda3 JA |
40 | #if defined (HAVE_UNISTD_H) |
41 | # include <unistd.h> | |
42 | #endif | |
43 | ||
28ef6c31 JA |
44 | #include <errno.h> |
45 | ||
ccc6cda3 | 46 | #include "../bashansi.h" |
726f6388 JA |
47 | |
48 | #include "../shell.h" | |
49 | #include "../builtins.h" | |
d166f048 | 50 | #include "../flags.h" |
cce855bc | 51 | #include "../findcmd.h" |
d166f048 | 52 | #include "../hashcmd.h" |
726f6388 | 53 | #include "common.h" |
ccc6cda3 | 54 | #include "bashgetopt.h" |
726f6388 JA |
55 | |
56 | extern int dot_found_in_search; | |
ccc6cda3 JA |
57 | extern char *this_command_name; |
58 | ||
59 | static int add_hashed_command (); | |
60 | static int print_hashed_commands (); | |
61 | ||
726f6388 JA |
62 | /* Print statistics on the current state of hashed commands. If LIST is |
63 | not empty, then rehash (or hash in the first place) the specified | |
64 | commands. */ | |
ccc6cda3 | 65 | int |
726f6388 JA |
66 | hash_builtin (list) |
67 | WORD_LIST *list; | |
68 | { | |
ccc6cda3 | 69 | int expunge_hash_table, opt; |
cce855bc | 70 | char *w, *pathname; |
726f6388 | 71 | |
ccc6cda3 | 72 | if (hashing_enabled == 0) |
726f6388 JA |
73 | { |
74 | builtin_error ("hashing disabled"); | |
75 | return (EXECUTION_FAILURE); | |
76 | } | |
77 | ||
ccc6cda3 JA |
78 | expunge_hash_table = 0; |
79 | pathname = (char *)NULL; | |
80 | reset_internal_getopt (); | |
81 | while ((opt = internal_getopt (list, "rp:")) != -1) | |
726f6388 | 82 | { |
ccc6cda3 | 83 | switch (opt) |
726f6388 | 84 | { |
ccc6cda3 | 85 | case 'r': |
726f6388 | 86 | expunge_hash_table = 1; |
726f6388 | 87 | break; |
ccc6cda3 JA |
88 | case 'p': |
89 | pathname = list_optarg; | |
90 | break; | |
91 | default: | |
92 | builtin_usage (); | |
726f6388 JA |
93 | return (EX_USAGE); |
94 | } | |
726f6388 | 95 | } |
ccc6cda3 | 96 | list = loptend; |
726f6388 JA |
97 | |
98 | /* We want hash -r to be silent, but hash -- to print hashing info. That | |
ccc6cda3 JA |
99 | is the reason for the test of expunge_hash_table. */ |
100 | if (list == 0 && expunge_hash_table == 0) | |
726f6388 | 101 | { |
ccc6cda3 JA |
102 | if (print_hashed_commands () == 0) |
103 | printf ("%s: hash table empty\n", this_command_name); | |
726f6388 JA |
104 | |
105 | return (EXECUTION_SUCCESS); | |
106 | } | |
107 | ||
108 | if (expunge_hash_table) | |
ccc6cda3 | 109 | flush_hashed_filenames (); |
726f6388 | 110 | |
bb70624e JA |
111 | #if defined (RESTRICTED_SHELL) |
112 | if (restricted && pathname && strchr (pathname, '/')) | |
113 | { | |
114 | builtin_error ("%s: restricted", pathname); | |
115 | return (EXECUTION_FAILURE); | |
116 | } | |
117 | #endif | |
118 | ||
ccc6cda3 | 119 | for (opt = EXECUTION_SUCCESS; list; list = list->next) |
726f6388 JA |
120 | { |
121 | /* Add or rehash the specified commands. */ | |
cce855bc | 122 | w = list->word->word; |
ccc6cda3 | 123 | if (pathname) |
28ef6c31 JA |
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 | remember_filename (w, pathname, 0, 0); | |
136 | } | |
cce855bc | 137 | else if (absolute_program (w)) |
d166f048 | 138 | continue; |
cce855bc | 139 | else if (add_hashed_command (w, 0)) |
d166f048 | 140 | opt = EXECUTION_FAILURE; |
726f6388 JA |
141 | } |
142 | ||
143 | fflush (stdout); | |
ccc6cda3 | 144 | return (opt); |
726f6388 JA |
145 | } |
146 | ||
ccc6cda3 | 147 | static int |
cce855bc JA |
148 | add_hashed_command (w, quiet) |
149 | char *w; | |
ccc6cda3 JA |
150 | int quiet; |
151 | { | |
152 | int rv; | |
153 | char *full_path; | |
154 | ||
155 | rv = 0; | |
cce855bc | 156 | if (find_function (w) == 0 && find_shell_builtin (w) == 0) |
ccc6cda3 | 157 | { |
cce855bc | 158 | full_path = find_user_command (w); |
ccc6cda3 | 159 | if (full_path && executable_file (full_path)) |
cce855bc | 160 | remember_filename (w, full_path, dot_found_in_search, 0); |
ccc6cda3 JA |
161 | else |
162 | { | |
163 | if (quiet == 0) | |
cce855bc | 164 | builtin_error ("%s: not found", w); |
ccc6cda3 JA |
165 | rv++; |
166 | } | |
167 | if (full_path) | |
168 | free (full_path); | |
169 | } | |
170 | return (rv); | |
171 | } | |
172 | ||
173 | /* Print information about current hashed info. */ | |
174 | static int | |
175 | print_hashed_commands () | |
176 | { | |
177 | BUCKET_CONTENTS *item_list; | |
178 | int bucket, any_printed; | |
179 | ||
d166f048 JA |
180 | if (hashed_filenames == 0) |
181 | return (0); | |
182 | ||
ccc6cda3 JA |
183 | for (bucket = any_printed = 0; bucket < hashed_filenames->nbuckets; bucket++) |
184 | { | |
185 | item_list = get_hash_bucket (bucket, hashed_filenames); | |
186 | if (item_list == 0) | |
187 | continue; | |
188 | ||
189 | if (any_printed == 0) | |
190 | { | |
191 | printf ("hits\tcommand\n"); | |
192 | any_printed++; | |
193 | } | |
194 | ||
195 | for ( ; item_list; item_list = item_list->next) | |
196 | printf ("%4d\t%s\n", item_list->times_found, pathdata(item_list)->path); | |
197 | ||
198 | } | |
199 | return (any_printed); | |
200 | } |