35d50864eb9407252b1e1f6a6098c7664ebd994c
[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 2, 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, 59 Temple Place, Suite 330, Boston, MA 02111 USA.
21
22 $PRODUCES hash.c
23
24 $BUILTIN hash
25 $FUNCTION hash_builtin
26 $SHORT_DOC hash [-r] [-p pathname] [-t] [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.
31 If the -t option is supplied the full pathname to which each NAME
32 corresponds is printed.  If multiple NAME arguments are supplied with
33 -t, the NAME is printed before the hashed full pathname.  If no arguments
34 are given, information about remembered commands is displayed.
35 $END
36
37 #include <config.h>
38
39 #include <stdio.h>
40
41 #include "../bashtypes.h"
42
43 #if defined (HAVE_UNISTD_H)
44 #  include <unistd.h>
45 #endif
46
47 #include <errno.h>
48
49 #include "../bashansi.h"
50
51 #include "../shell.h"
52 #include "../builtins.h"
53 #include "../flags.h"
54 #include "../findcmd.h"
55 #include "../hashcmd.h"
56 #include "common.h"
57 #include "bashgetopt.h"
58
59 extern int dot_found_in_search;
60 extern char *this_command_name;
61
62 static int add_hashed_command __P((char *, int));
63 static int print_hashed_commands __P((void));
64 static int list_hashed_filename_targets __P((WORD_LIST *));
65
66 /* Print statistics on the current state of hashed commands.  If LIST is
67    not empty, then rehash (or hash in the first place) the specified
68    commands. */
69 int
70 hash_builtin (list)
71      WORD_LIST *list;
72 {
73   int expunge_hash_table, list_targets, opt;
74   char *w, *pathname;
75
76   if (hashing_enabled == 0)
77     {
78       builtin_error ("hashing disabled");
79       return (EXECUTION_FAILURE);
80     }
81
82   expunge_hash_table = list_targets = 0;
83   pathname = (char *)NULL;
84   reset_internal_getopt ();
85   while ((opt = internal_getopt (list, "rp:t")) != -1)
86     {
87       switch (opt)
88         {
89         case 'r':
90           expunge_hash_table = 1;
91           break;
92         case 'p':
93           pathname = list_optarg;
94           break;
95         case 't':
96           list_targets = 1;
97           break;
98         default:
99           builtin_usage ();
100           return (EX_USAGE);
101         }
102     }
103   list = loptend;
104
105   /* hash -t requires at least one argument. */
106   if (list == 0 && list_targets)
107     {
108       builtin_error("-t: argument required");
109       return (EXECUTION_FAILURE);
110     }
111
112   /* We want hash -r to be silent, but hash -- to print hashing info.  That
113      is the reason for the test of expunge_hash_table. */
114   if (list == 0 && expunge_hash_table == 0)
115     {
116       if (print_hashed_commands () == 0)
117         printf ("%s: hash table empty\n", this_command_name);
118
119       return (EXECUTION_SUCCESS);
120     }
121
122   if (expunge_hash_table)
123     flush_hashed_filenames ();
124
125   /* If someone runs `hash -r -t xyz' he will be disappointed. */
126   if (list_targets)
127     {
128       return (list_hashed_filename_targets (list));
129     }
130       
131 #if defined (RESTRICTED_SHELL)
132   if (restricted && pathname && strchr (pathname, '/'))
133     {
134       builtin_error ("%s: restricted", pathname);
135       return (EXECUTION_FAILURE);
136     }
137 #endif
138
139   for (opt = EXECUTION_SUCCESS; list; list = list->next)
140     {
141       /* Add or rehash the specified commands. */
142       w = list->word->word;
143       if (pathname)
144         {
145           if (is_directory (pathname))
146             {
147 #ifdef EISDIR
148               builtin_error ("%s: %s", pathname, strerror (EISDIR));
149 #else
150               builtin_error ("%s: is a directory", pathname);
151 #endif
152               opt = EXECUTION_FAILURE;
153             }
154           else
155             remember_filename (w, pathname, 0, 0);
156         }
157       else if (absolute_program (w))
158         continue;
159       else if (add_hashed_command (w, 0))
160         opt = EXECUTION_FAILURE;
161     }
162
163   fflush (stdout);
164   return (opt);
165 }
166
167 static int
168 add_hashed_command (w, quiet)
169      char *w;
170      int quiet;
171 {
172   int rv;
173   char *full_path;
174
175   rv = 0;
176   if (find_function (w) == 0 && find_shell_builtin (w) == 0)
177     {
178       full_path = find_user_command (w);
179       if (full_path && executable_file (full_path))
180         remember_filename (w, full_path, dot_found_in_search, 0);
181       else
182         {
183           if (quiet == 0)
184             builtin_error ("%s: not found", w);
185           rv++;
186         }
187       if (full_path)
188         free (full_path);
189     }
190   return (rv);
191 }
192
193 /* Print information about current hashed info. */
194 static int
195 print_hashed_commands ()
196 {
197   BUCKET_CONTENTS *item_list;
198   int bucket, any_printed;
199
200   if (hashed_filenames == 0)
201     return (0);
202
203   for (bucket = any_printed = 0; bucket < hashed_filenames->nbuckets; bucket++)
204     {
205       item_list = get_hash_bucket (bucket, hashed_filenames);
206       if (item_list == 0)
207         continue;
208
209       if (any_printed == 0)
210         {
211           printf ("hits\tcommand\n");
212           any_printed++;
213         }
214
215       for ( ; item_list; item_list = item_list->next)
216         printf ("%4d\t%s\n", item_list->times_found, pathdata(item_list)->path);
217
218     }
219   return (any_printed);
220 }
221
222 static int
223 list_hashed_filename_targets (list)
224      WORD_LIST *list;
225 {
226   int all_found, multiple;
227   char *target;
228   WORD_LIST *l;
229
230   all_found = 1;
231   multiple = list->next != 0;
232
233   for (l = list; l; l = l->next)
234     {
235       target = find_hashed_filename (l->word->word);
236       if (target == 0)
237         {
238           all_found = 0;
239           builtin_error ("%s: not found", l->word->word);
240           continue;
241         }
242       if (multiple)
243         printf ("%s\t", l->word->word);
244       printf ("%s\n", target);
245     }
246
247   return (all_found ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
248 }