Imported from ../bash-1.14.7.tar.gz.
[platform/upstream/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] [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 }