1.5.1
by Matthias Klose
Import upstream version 4.3~rc1 |
1 |
/* bashline.c -- Bash's interface to the readline library. */
|
2 |
||
3 |
/* Copyright (C) 1987-2013 Free Software Foundation, Inc.
|
|
4 |
||
5 |
This file is part of GNU Bash, the Bourne Again SHell.
|
|
6 |
||
7 |
Bash is free software: you can redistribute it and/or modify
|
|
8 |
it under the terms of the GNU General Public License as published by
|
|
9 |
the Free Software Foundation, either version 3 of the License, or
|
|
10 |
(at your option) any later version.
|
|
11 |
||
12 |
Bash is distributed in the hope that it will be useful,
|
|
13 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15 |
GNU General Public License for more details.
|
|
16 |
||
17 |
You should have received a copy of the GNU General Public License
|
|
18 |
along with Bash. If not, see <http://www.gnu.org/licenses/>.
|
|
19 |
*/
|
|
20 |
||
21 |
#include "config.h" |
|
22 |
||
23 |
#if defined (READLINE)
|
|
24 |
||
25 |
#include "bashtypes.h" |
|
26 |
#include "posixstat.h" |
|
27 |
||
28 |
#if defined (HAVE_UNISTD_H)
|
|
29 |
# include <unistd.h>
|
|
30 |
#endif
|
|
31 |
||
32 |
#if defined (HAVE_GRP_H)
|
|
33 |
# include <grp.h>
|
|
34 |
#endif
|
|
35 |
||
36 |
#if defined (HAVE_NETDB_H)
|
|
37 |
# include <netdb.h>
|
|
38 |
#endif
|
|
39 |
||
40 |
#include <signal.h> |
|
41 |
||
42 |
#include <stdio.h> |
|
43 |
#include "chartypes.h" |
|
44 |
#include "bashansi.h" |
|
45 |
#include "bashintl.h" |
|
46 |
||
47 |
#include "shell.h" |
|
48 |
#include "input.h" |
|
49 |
#include "builtins.h" |
|
50 |
#include "bashhist.h" |
|
51 |
#include "bashline.h" |
|
52 |
#include "execute_cmd.h" |
|
53 |
#include "findcmd.h" |
|
54 |
#include "pathexp.h" |
|
55 |
#include "shmbutil.h" |
|
56 |
#include "trap.h" |
|
57 |
||
58 |
#include "builtins/common.h" |
|
59 |
||
60 |
#include <readline/rlconf.h> |
|
61 |
#include <readline/readline.h> |
|
62 |
#include <readline/history.h> |
|
63 |
||
64 |
#include <glob/glob.h> |
|
65 |
||
66 |
#if defined (ALIAS)
|
|
67 |
# include "alias.h"
|
|
68 |
#endif
|
|
69 |
||
70 |
#if defined (PROGRAMMABLE_COMPLETION)
|
|
71 |
# include "pcomplete.h"
|
|
72 |
#endif
|
|
73 |
||
74 |
/* These should agree with the defines for emacs_mode and vi_mode in
|
|
75 |
rldefs.h, even though that's not a public readline header file. */
|
|
76 |
#ifndef EMACS_EDITING_MODE
|
|
77 |
# define NO_EDITING_MODE -1
|
|
78 |
# define EMACS_EDITING_MODE 1
|
|
79 |
# define VI_EDITING_MODE 0
|
|
80 |
#endif
|
|
81 |
||
82 |
#define RL_BOOLEAN_VARIABLE_VALUE(s) ((s)[0] == 'o' && (s)[1] == 'n' && (s)[2] == '\0')
|
|
83 |
||
84 |
#if defined (BRACE_COMPLETION)
|
|
85 |
extern int bash_brace_completion __P((int, int)); |
|
86 |
#endif /* BRACE_COMPLETION */ |
|
87 |
||
88 |
/* To avoid including curses.h/term.h/termcap.h and that whole mess. */
|
|
89 |
#ifdef _MINIX
|
|
90 |
extern int tputs __P((const char *string, int nlines, void (*outx)(int))); |
|
91 |
#else
|
|
92 |
extern int tputs __P((const char *string, int nlines, int (*outx)(int))); |
|
93 |
#endif
|
|
94 |
||
95 |
/* Forward declarations */
|
|
96 |
||
97 |
/* Functions bound to keys in Readline for Bash users. */
|
|
98 |
static int shell_expand_line __P((int, int)); |
|
99 |
static int display_shell_version __P((int, int)); |
|
100 |
static int operate_and_get_next __P((int, int)); |
|
101 |
||
102 |
static int bash_ignore_filenames __P((char **)); |
|
103 |
static int bash_ignore_everything __P((char **)); |
|
104 |
||
105 |
#if defined (BANG_HISTORY)
|
|
106 |
static char *history_expand_line_internal __P((char *)); |
|
107 |
static int history_expand_line __P((int, int)); |
|
108 |
static int tcsh_magic_space __P((int, int)); |
|
109 |
#endif /* BANG_HISTORY */ |
|
110 |
#ifdef ALIAS
|
|
111 |
static int alias_expand_line __P((int, int)); |
|
112 |
#endif
|
|
113 |
#if defined (BANG_HISTORY) && defined (ALIAS)
|
|
114 |
static int history_and_alias_expand_line __P((int, int)); |
|
115 |
#endif
|
|
116 |
||
117 |
static int bash_forward_shellword __P((int, int)); |
|
118 |
static int bash_backward_shellword __P((int, int)); |
|
119 |
static int bash_kill_shellword __P((int, int)); |
|
120 |
static int bash_backward_kill_shellword __P((int, int)); |
|
121 |
||
122 |
/* Helper functions for Readline. */
|
|
123 |
static char *restore_tilde __P((char *, char *)); |
|
124 |
static char *maybe_restore_tilde __P((char *, char *)); |
|
125 |
||
126 |
static char *bash_filename_rewrite_hook __P((char *, int)); |
|
127 |
||
128 |
static void bash_directory_expansion __P((char **)); |
|
129 |
static int bash_filename_stat_hook __P((char **)); |
|
130 |
static int bash_command_name_stat_hook __P((char **)); |
|
131 |
static int bash_directory_completion_hook __P((char **)); |
|
132 |
static int filename_completion_ignore __P((char **)); |
|
133 |
static int bash_push_line __P((void)); |
|
134 |
||
135 |
static int executable_completion __P((const char *, int)); |
|
136 |
||
137 |
static rl_icppfunc_t *save_directory_hook __P((void)); |
|
138 |
static void restore_directory_hook __P((rl_icppfunc_t)); |
|
139 |
||
140 |
static void cleanup_expansion_error __P((void)); |
|
141 |
static void maybe_make_readline_line __P((char *)); |
|
142 |
static void set_up_new_line __P((char *)); |
|
143 |
||
144 |
static int check_redir __P((int)); |
|
145 |
static char **attempt_shell_completion __P((const char *, int, int)); |
|
146 |
static char *variable_completion_function __P((const char *, int)); |
|
147 |
static char *hostname_completion_function __P((const char *, int)); |
|
148 |
static char *command_subst_completion_function __P((const char *, int)); |
|
149 |
||
150 |
static void build_history_completion_array __P((void)); |
|
151 |
static char *history_completion_generator __P((const char *, int)); |
|
152 |
static int dynamic_complete_history __P((int, int)); |
|
153 |
static int bash_dabbrev_expand __P((int, int)); |
|
154 |
||
155 |
static void initialize_hostname_list __P((void)); |
|
156 |
static void add_host_name __P((char *)); |
|
157 |
static void snarf_hosts_from_file __P((char *)); |
|
158 |
static char **hostnames_matching __P((char *)); |
|
159 |
||
160 |
static void _ignore_completion_names __P((char **, sh_ignore_func_t *)); |
|
161 |
static int name_is_acceptable __P((const char *)); |
|
162 |
static int test_for_directory __P((const char *)); |
|
163 |
static int return_zero __P((const char *)); |
|
164 |
||
165 |
static char *bash_dequote_filename __P((char *, int)); |
|
166 |
static char *quote_word_break_chars __P((char *)); |
|
167 |
static void set_filename_bstab __P((const char *)); |
|
168 |
static char *bash_quote_filename __P((char *, int, char *)); |
|
169 |
||
170 |
#ifdef _MINIX
|
|
171 |
static void putx __P((int)); |
|
172 |
#else
|
|
173 |
static int putx __P((int)); |
|
174 |
#endif
|
|
175 |
static int bash_execute_unix_command __P((int, int)); |
|
176 |
static void init_unix_command_map __P((void)); |
|
177 |
static int isolate_sequence __P((char *, int, int, int *)); |
|
178 |
||
179 |
static int set_saved_history __P((void)); |
|
180 |
||
181 |
#if defined (ALIAS)
|
|
182 |
static int posix_edit_macros __P((int, int)); |
|
183 |
#endif
|
|
184 |
||
185 |
static int bash_event_hook __P((void)); |
|
186 |
||
187 |
#if defined (PROGRAMMABLE_COMPLETION)
|
|
188 |
static int find_cmd_start __P((int)); |
|
189 |
static int find_cmd_end __P((int)); |
|
190 |
static char *find_cmd_name __P((int, int *, int *)); |
|
191 |
static char *prog_complete_return __P((const char *, int)); |
|
192 |
||
193 |
static char **prog_complete_matches; |
|
194 |
#endif
|
|
195 |
||
196 |
/* Variables used here but defined in other files. */
|
|
197 |
#if defined (BANG_HISTORY)
|
|
198 |
extern int hist_verify; |
|
199 |
#endif
|
|
200 |
||
201 |
extern int current_command_line_count, saved_command_line_count; |
|
202 |
extern int last_command_exit_value; |
|
203 |
extern int array_needs_making; |
|
204 |
extern int posixly_correct, no_symbolic_links; |
|
205 |
extern char *current_prompt_string, *ps1_prompt; |
|
206 |
extern STRING_INT_ALIST word_token_alist[]; |
|
207 |
extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin; |
|
208 |
||
209 |
/* SPECIFIC_COMPLETION_FUNCTIONS specifies that we have individual
|
|
210 |
completion functions which indicate what type of completion should be
|
|
211 |
done (at or before point) that can be bound to key sequences with
|
|
212 |
the readline library. */
|
|
213 |
#define SPECIFIC_COMPLETION_FUNCTIONS
|
|
214 |
||
215 |
#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
|
|
216 |
static int bash_specific_completion __P((int, rl_compentry_func_t *)); |
|
217 |
||
218 |
static int bash_complete_filename_internal __P((int)); |
|
219 |
static int bash_complete_username_internal __P((int)); |
|
220 |
static int bash_complete_hostname_internal __P((int)); |
|
221 |
static int bash_complete_variable_internal __P((int)); |
|
222 |
static int bash_complete_command_internal __P((int)); |
|
223 |
||
224 |
static int bash_complete_filename __P((int, int)); |
|
225 |
static int bash_possible_filename_completions __P((int, int)); |
|
226 |
static int bash_complete_username __P((int, int)); |
|
227 |
static int bash_possible_username_completions __P((int, int)); |
|
228 |
static int bash_complete_hostname __P((int, int)); |
|
229 |
static int bash_possible_hostname_completions __P((int, int)); |
|
230 |
static int bash_complete_variable __P((int, int)); |
|
231 |
static int bash_possible_variable_completions __P((int, int)); |
|
232 |
static int bash_complete_command __P((int, int)); |
|
233 |
static int bash_possible_command_completions __P((int, int)); |
|
234 |
||
235 |
static char *glob_complete_word __P((const char *, int)); |
|
236 |
static int bash_glob_completion_internal __P((int)); |
|
237 |
static int bash_glob_complete_word __P((int, int)); |
|
238 |
static int bash_glob_expand_word __P((int, int)); |
|
239 |
static int bash_glob_list_expansions __P((int, int)); |
|
240 |
||
241 |
#endif /* SPECIFIC_COMPLETION_FUNCTIONS */ |
|
242 |
||
243 |
static int edit_and_execute_command __P((int, int, int, char *)); |
|
244 |
#if defined (VI_MODE)
|
|
245 |
static int vi_edit_and_execute_command __P((int, int)); |
|
246 |
static int bash_vi_complete __P((int, int)); |
|
247 |
#endif
|
|
248 |
static int emacs_edit_and_execute_command __P((int, int)); |
|
249 |
||
250 |
/* Non-zero once initalize_readline () has been called. */
|
|
251 |
int bash_readline_initialized = 0; |
|
252 |
||
253 |
/* If non-zero, we do hostname completion, breaking words at `@' and
|
|
254 |
trying to complete the stuff after the `@' from our own internal
|
|
255 |
host list. */
|
|
256 |
int perform_hostname_completion = 1; |
|
257 |
||
258 |
/* If non-zero, we don't do command completion on an empty line. */
|
|
259 |
int no_empty_command_completion; |
|
260 |
||
261 |
/* Set FORCE_FIGNORE if you want to honor FIGNORE even if it ignores the
|
|
262 |
only possible matches. Set to 0 if you want to match filenames if they
|
|
263 |
are the only possible matches, even if FIGNORE says to. */
|
|
264 |
int force_fignore = 1; |
|
265 |
||
266 |
/* Perform spelling correction on directory names during word completion */
|
|
267 |
int dircomplete_spelling = 0; |
|
268 |
||
269 |
/* Expand directory names during word/filename completion. */
|
|
270 |
#if DIRCOMPLETE_EXPAND_DEFAULT
|
|
271 |
int dircomplete_expand = 1; |
|
272 |
int dircomplete_expand_relpath = 1; |
|
273 |
#else
|
|
274 |
int dircomplete_expand = 0; |
|
275 |
int dircomplete_expand_relpath = 0; |
|
276 |
#endif
|
|
277 |
||
278 |
/* When non-zero, perform `normal' shell quoting on completed filenames
|
|
279 |
even when the completed name contains a directory name with a shell
|
|
280 |
variable referene, so dollar signs in a filename get quoted appropriately.
|
|
281 |
Set to zero to remove dollar sign (and braces or parens as needed) from
|
|
282 |
the set of characters that will be quoted. */
|
|
283 |
int complete_fullquote = 1; |
|
284 |
||
285 |
static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:"; |
|
286 |
static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:"; |
|
287 |
/* )) */
|
|
288 |
||
289 |
static const char *default_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/ |
|
290 |
static char *custom_filename_quote_characters = 0; |
|
291 |
static char filename_bstab[256]; |
|
292 |
||
293 |
static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL; |
|
294 |
||
295 |
static int dot_in_path = 0; |
|
296 |
||
297 |
/* Set to non-zero when dabbrev-expand is running */
|
|
298 |
static int dabbrev_expand_active = 0; |
|
299 |
||
300 |
/* What kind of quoting is performed by bash_quote_filename:
|
|
301 |
COMPLETE_DQUOTE = double-quoting the filename
|
|
302 |
COMPLETE_SQUOTE = single_quoting the filename
|
|
303 |
COMPLETE_BSQUOTE = backslash-quoting special chars in the filename
|
|
304 |
*/
|
|
305 |
#define COMPLETE_DQUOTE 1
|
|
306 |
#define COMPLETE_SQUOTE 2
|
|
307 |
#define COMPLETE_BSQUOTE 3
|
|
308 |
static int completion_quoting_style = COMPLETE_BSQUOTE; |
|
309 |
||
310 |
/* Flag values for the final argument to bash_default_completion */
|
|
311 |
#define DEFCOMP_CMDPOS 1
|
|
312 |
||
313 |
/* Change the readline VI-mode keymaps into or out of Posix.2 compliance.
|
|
314 |
Called when the shell is put into or out of `posix' mode. */
|
|
315 |
void
|
|
316 |
posix_readline_initialize (on_or_off) |
|
317 |
int on_or_off; |
|
318 |
{
|
|
319 |
if (on_or_off) |
|
320 |
rl_variable_bind ("comment-begin", "#"); |
|
321 |
#if defined (VI_MODE)
|
|
322 |
rl_bind_key_in_map (CTRL ('I'), on_or_off ? rl_insert : rl_complete, vi_insertion_keymap); |
|
323 |
#endif
|
|
324 |
}
|
|
325 |
||
326 |
void
|
|
327 |
reset_completer_word_break_chars () |
|
328 |
{
|
|
329 |
rl_completer_word_break_characters = perform_hostname_completion ? savestring (bash_completer_word_break_characters) : savestring (bash_nohostname_word_break_characters); |
|
330 |
}
|
|
331 |
||
332 |
/* When this function returns, rl_completer_word_break_characters points to
|
|
333 |
dynamically allocated memory. */
|
|
334 |
int
|
|
335 |
enable_hostname_completion (on_or_off) |
|
336 |
int on_or_off; |
|
337 |
{
|
|
338 |
int old_value; |
|
339 |
char *at, *nv, *nval; |
|
340 |
||
341 |
old_value = perform_hostname_completion; |
|
342 |
||
343 |
if (on_or_off) |
|
344 |
{
|
|
345 |
perform_hostname_completion = 1; |
|
346 |
rl_special_prefixes = "$@"; |
|
347 |
}
|
|
348 |
else
|
|
349 |
{
|
|
350 |
perform_hostname_completion = 0; |
|
351 |
rl_special_prefixes = "$"; |
|
352 |
}
|
|
353 |
||
354 |
/* Now we need to figure out how to appropriately modify and assign
|
|
355 |
rl_completer_word_break_characters depending on whether we want
|
|
356 |
hostname completion on or off. */
|
|
357 |
||
358 |
/* If this is the first time this has been called
|
|
359 |
(bash_readline_initialized == 0), use the sames values as before, but
|
|
360 |
allocate new memory for rl_completer_word_break_characters. */
|
|
361 |
||
362 |
if (bash_readline_initialized == 0 && |
|
363 |
(rl_completer_word_break_characters == 0 || |
|
364 |
rl_completer_word_break_characters == rl_basic_word_break_characters)) |
|
365 |
{
|
|
366 |
if (on_or_off) |
|
367 |
rl_completer_word_break_characters = savestring (bash_completer_word_break_characters); |
|
368 |
else
|
|
369 |
rl_completer_word_break_characters = savestring (bash_nohostname_word_break_characters); |
|
370 |
}
|
|
371 |
else
|
|
372 |
{
|
|
373 |
/* See if we have anything to do. */
|
|
374 |
at = strchr (rl_completer_word_break_characters, '@'); |
|
375 |
if ((at == 0 && on_or_off == 0) || (at != 0 && on_or_off != 0)) |
|
376 |
return old_value; |
|
377 |
||
378 |
/* We have something to do. Do it. */
|
|
379 |
nval = (char *)xmalloc (strlen (rl_completer_word_break_characters) + 1 + on_or_off); |
|
380 |
||
381 |
if (on_or_off == 0) |
|
382 |
{
|
|
383 |
/* Turn it off -- just remove `@' from word break chars. We want
|
|
384 |
to remove all occurrences of `@' from the char list, so we loop
|
|
385 |
rather than just copy the rest of the list over AT. */
|
|
386 |
for (nv = nval, at = rl_completer_word_break_characters; *at; ) |
|
387 |
if (*at != '@') |
|
388 |
*nv++ = *at++; |
|
389 |
else
|
|
390 |
at++; |
|
391 |
*nv = '\0'; |
|
392 |
}
|
|
393 |
else
|
|
394 |
{
|
|
395 |
nval[0] = '@'; |
|
396 |
strcpy (nval + 1, rl_completer_word_break_characters); |
|
397 |
}
|
|
398 |
||
399 |
free (rl_completer_word_break_characters); |
|
400 |
rl_completer_word_break_characters = nval; |
|
401 |
}
|
|
402 |
||
403 |
return (old_value); |
|
404 |
}
|
|
405 |
||
406 |
/* Called once from parse.y if we are going to use readline. */
|
|
407 |
void
|
|
408 |
initialize_readline () |
|
409 |
{
|
|
410 |
rl_command_func_t *func; |
|
411 |
char kseq[2]; |
|
412 |
||
413 |
if (bash_readline_initialized) |
|
414 |
return; |
|
415 |
||
416 |
rl_terminal_name = get_string_value ("TERM"); |
|
417 |
rl_instream = stdin; |
|
418 |
rl_outstream = stderr; |
|
419 |
||
420 |
/* Allow conditional parsing of the ~/.inputrc file. */
|
|
421 |
rl_readline_name = "Bash"; |
|
422 |
||
423 |
/* Add bindable names before calling rl_initialize so they may be
|
|
424 |
referenced in the various inputrc files. */
|
|
425 |
rl_add_defun ("shell-expand-line", shell_expand_line, -1); |
|
426 |
#ifdef BANG_HISTORY
|
|
427 |
rl_add_defun ("history-expand-line", history_expand_line, -1); |
|
428 |
rl_add_defun ("magic-space", tcsh_magic_space, -1); |
|
429 |
#endif
|
|
430 |
||
431 |
rl_add_defun ("shell-forward-word", bash_forward_shellword, -1); |
|
432 |
rl_add_defun ("shell-backward-word", bash_backward_shellword, -1); |
|
433 |
rl_add_defun ("shell-kill-word", bash_kill_shellword, -1); |
|
434 |
rl_add_defun ("shell-backward-kill-word", bash_backward_kill_shellword, -1); |
|
435 |
||
436 |
#ifdef ALIAS
|
|
437 |
rl_add_defun ("alias-expand-line", alias_expand_line, -1); |
|
438 |
# ifdef BANG_HISTORY
|
|
439 |
rl_add_defun ("history-and-alias-expand-line", history_and_alias_expand_line, -1); |
|
440 |
# endif
|
|
441 |
#endif
|
|
442 |
||
443 |
/* Backwards compatibility. */
|
|
444 |
rl_add_defun ("insert-last-argument", rl_yank_last_arg, -1); |
|
445 |
||
446 |
rl_add_defun ("operate-and-get-next", operate_and_get_next, -1); |
|
447 |
rl_add_defun ("display-shell-version", display_shell_version, -1); |
|
448 |
rl_add_defun ("edit-and-execute-command", emacs_edit_and_execute_command, -1); |
|
449 |
||
450 |
#if defined (BRACE_COMPLETION)
|
|
451 |
rl_add_defun ("complete-into-braces", bash_brace_completion, -1); |
|
452 |
#endif
|
|
453 |
||
454 |
#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
|
|
455 |
rl_add_defun ("complete-filename", bash_complete_filename, -1); |
|
456 |
rl_add_defun ("possible-filename-completions", bash_possible_filename_completions, -1); |
|
457 |
rl_add_defun ("complete-username", bash_complete_username, -1); |
|
458 |
rl_add_defun ("possible-username-completions", bash_possible_username_completions, -1); |
|
459 |
rl_add_defun ("complete-hostname", bash_complete_hostname, -1); |
|
460 |
rl_add_defun ("possible-hostname-completions", bash_possible_hostname_completions, -1); |
|
461 |
rl_add_defun ("complete-variable", bash_complete_variable, -1); |
|
462 |
rl_add_defun ("possible-variable-completions", bash_possible_variable_completions, -1); |
|
463 |
rl_add_defun ("complete-command", bash_complete_command, -1); |
|
464 |
rl_add_defun ("possible-command-completions", bash_possible_command_completions, -1); |
|
465 |
rl_add_defun ("glob-complete-word", bash_glob_complete_word, -1); |
|
466 |
rl_add_defun ("glob-expand-word", bash_glob_expand_word, -1); |
|
467 |
rl_add_defun ("glob-list-expansions", bash_glob_list_expansions, -1); |
|
468 |
#endif
|
|
469 |
||
470 |
rl_add_defun ("dynamic-complete-history", dynamic_complete_history, -1); |
|
471 |
rl_add_defun ("dabbrev-expand", bash_dabbrev_expand, -1); |
|
472 |
||
473 |
/* Bind defaults before binding our custom shell keybindings. */
|
|
474 |
if (RL_ISSTATE(RL_STATE_INITIALIZED) == 0) |
|
475 |
rl_initialize (); |
|
476 |
||
477 |
/* Bind up our special shell functions. */
|
|
478 |
rl_bind_key_if_unbound_in_map (CTRL('E'), shell_expand_line, emacs_meta_keymap); |
|
479 |
||
480 |
#ifdef BANG_HISTORY
|
|
481 |
rl_bind_key_if_unbound_in_map ('^', history_expand_line, emacs_meta_keymap); |
|
482 |
#endif
|
|
483 |
||
484 |
rl_bind_key_if_unbound_in_map (CTRL ('O'), operate_and_get_next, emacs_standard_keymap); |
|
485 |
rl_bind_key_if_unbound_in_map (CTRL ('V'), display_shell_version, emacs_ctlx_keymap); |
|
486 |
||
487 |
/* In Bash, the user can switch editing modes with "set -o [vi emacs]",
|
|
488 |
so it is not necessary to allow C-M-j for context switching. Turn
|
|
489 |
off this occasionally confusing behaviour. */
|
|
490 |
kseq[0] = CTRL('J'); |
|
491 |
kseq[1] = '\0'; |
|
492 |
func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL); |
|
493 |
if (func == rl_vi_editing_mode) |
|
494 |
rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap); |
|
495 |
kseq[0] = CTRL('M'); |
|
496 |
func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL); |
|
497 |
if (func == rl_vi_editing_mode) |
|
498 |
rl_unbind_key_in_map (CTRL('M'), emacs_meta_keymap); |
|
499 |
#if defined (VI_MODE)
|
|
500 |
rl_unbind_key_in_map (CTRL('E'), vi_movement_keymap); |
|
501 |
#endif
|
|
502 |
||
503 |
#if defined (BRACE_COMPLETION)
|
|
504 |
rl_bind_key_if_unbound_in_map ('{', bash_brace_completion, emacs_meta_keymap); /*}*/ |
|
505 |
#endif /* BRACE_COMPLETION */ |
|
506 |
||
507 |
#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
|
|
508 |
rl_bind_key_if_unbound_in_map ('/', bash_complete_filename, emacs_meta_keymap); |
|
509 |
rl_bind_key_if_unbound_in_map ('/', bash_possible_filename_completions, emacs_ctlx_keymap); |
|
510 |
||
511 |
/* Have to jump through hoops here because there is a default binding for
|
|
512 |
M-~ (rl_tilde_expand) */
|
|
513 |
kseq[0] = '~'; |
|
514 |
kseq[1] = '\0'; |
|
515 |
func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL); |
|
516 |
if (func == 0 || func == rl_tilde_expand) |
|
517 |
rl_bind_keyseq_in_map (kseq, bash_complete_username, emacs_meta_keymap); |
|
518 |
||
519 |
rl_bind_key_if_unbound_in_map ('~', bash_possible_username_completions, emacs_ctlx_keymap); |
|
520 |
||
521 |
rl_bind_key_if_unbound_in_map ('@', bash_complete_hostname, emacs_meta_keymap); |
|
522 |
rl_bind_key_if_unbound_in_map ('@', bash_possible_hostname_completions, emacs_ctlx_keymap); |
|
523 |
||
524 |
rl_bind_key_if_unbound_in_map ('$', bash_complete_variable, emacs_meta_keymap); |
|
525 |
rl_bind_key_if_unbound_in_map ('$', bash_possible_variable_completions, emacs_ctlx_keymap); |
|
526 |
||
527 |
rl_bind_key_if_unbound_in_map ('!', bash_complete_command, emacs_meta_keymap); |
|
528 |
rl_bind_key_if_unbound_in_map ('!', bash_possible_command_completions, emacs_ctlx_keymap); |
|
529 |
||
530 |
rl_bind_key_if_unbound_in_map ('g', bash_glob_complete_word, emacs_meta_keymap); |
|
531 |
rl_bind_key_if_unbound_in_map ('*', bash_glob_expand_word, emacs_ctlx_keymap); |
|
532 |
rl_bind_key_if_unbound_in_map ('g', bash_glob_list_expansions, emacs_ctlx_keymap); |
|
533 |
||
534 |
#endif /* SPECIFIC_COMPLETION_FUNCTIONS */ |
|
535 |
||
536 |
kseq[0] = TAB; |
|
537 |
kseq[1] = '\0'; |
|
538 |
func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL); |
|
539 |
if (func == 0 || func == rl_tab_insert) |
|
540 |
rl_bind_key_in_map (TAB, dynamic_complete_history, emacs_meta_keymap); |
|
541 |
||
542 |
/* Tell the completer that we want a crack first. */
|
|
543 |
rl_attempted_completion_function = attempt_shell_completion; |
|
544 |
||
545 |
/* Tell the completer that we might want to follow symbolic links or
|
|
546 |
do other expansion on directory names. */
|
|
547 |
set_directory_hook (); |
|
548 |
||
549 |
rl_filename_rewrite_hook = bash_filename_rewrite_hook; |
|
550 |
||
551 |
rl_filename_stat_hook = bash_filename_stat_hook; |
|
552 |
||
553 |
/* Tell the filename completer we want a chance to ignore some names. */
|
|
554 |
rl_ignore_some_completions_function = filename_completion_ignore; |
|
555 |
||
556 |
/* Bind C-xC-e to invoke emacs and run result as commands. */
|
|
557 |
rl_bind_key_if_unbound_in_map (CTRL ('E'), emacs_edit_and_execute_command, emacs_ctlx_keymap); |
|
558 |
#if defined (VI_MODE)
|
|
559 |
rl_bind_key_if_unbound_in_map ('v', vi_edit_and_execute_command, vi_movement_keymap); |
|
560 |
# if defined (ALIAS)
|
|
561 |
rl_bind_key_if_unbound_in_map ('@', posix_edit_macros, vi_movement_keymap); |
|
562 |
# endif
|
|
563 |
||
564 |
rl_bind_key_in_map ('\\', bash_vi_complete, vi_movement_keymap); |
|
565 |
rl_bind_key_in_map ('*', bash_vi_complete, vi_movement_keymap); |
|
566 |
rl_bind_key_in_map ('=', bash_vi_complete, vi_movement_keymap); |
|
567 |
#endif
|
|
568 |
||
569 |
rl_completer_quote_characters = "'\""; |
|
570 |
||
571 |
/* This sets rl_completer_word_break_characters and rl_special_prefixes
|
|
572 |
to the appropriate values, depending on whether or not hostname
|
|
573 |
completion is enabled. */
|
|
574 |
enable_hostname_completion (perform_hostname_completion); |
|
575 |
||
576 |
/* characters that need to be quoted when appearing in filenames. */
|
|
577 |
rl_filename_quote_characters = default_filename_quote_characters; |
|
578 |
set_filename_bstab (rl_filename_quote_characters); |
|
579 |
||
580 |
rl_filename_quoting_function = bash_quote_filename; |
|
581 |
rl_filename_dequoting_function = bash_dequote_filename; |
|
582 |
rl_char_is_quoted_p = char_is_quoted; |
|
583 |
||
584 |
#if 0
|
|
585 |
/* This is superfluous and makes it impossible to use tab completion in
|
|
586 |
vi mode even when explicitly binding it in ~/.inputrc. sv_strict_posix()
|
|
587 |
should already have called posix_readline_initialize() when
|
|
588 |
posixly_correct was set. */
|
|
589 |
if (posixly_correct)
|
|
590 |
posix_readline_initialize (1);
|
|
591 |
#endif
|
|
592 |
||
593 |
bash_readline_initialized = 1; |
|
594 |
}
|
|
595 |
||
596 |
void
|
|
597 |
bashline_reinitialize () |
|
598 |
{
|
|
599 |
bash_readline_initialized = 0; |
|
600 |
}
|
|
601 |
||
602 |
void
|
|
603 |
bashline_set_event_hook () |
|
604 |
{
|
|
605 |
rl_signal_event_hook = bash_event_hook; |
|
606 |
}
|
|
607 |
||
608 |
void
|
|
609 |
bashline_reset_event_hook () |
|
610 |
{
|
|
611 |
rl_signal_event_hook = 0; |
|
612 |
}
|
|
613 |
||
614 |
/* On Sun systems at least, rl_attempted_completion_function can end up
|
|
615 |
getting set to NULL, and rl_completion_entry_function set to do command
|
|
616 |
word completion if Bash is interrupted while trying to complete a command
|
|
617 |
word. This just resets all the completion functions to the right thing.
|
|
618 |
It's called from throw_to_top_level(). */
|
|
619 |
void
|
|
620 |
bashline_reset () |
|
621 |
{
|
|
622 |
tilde_initialize (); |
|
623 |
rl_attempted_completion_function = attempt_shell_completion; |
|
624 |
rl_completion_entry_function = NULL; |
|
625 |
rl_ignore_some_completions_function = filename_completion_ignore; |
|
626 |
rl_filename_quote_characters = default_filename_quote_characters; |
|
627 |
set_filename_bstab (rl_filename_quote_characters); |
|
628 |
||
629 |
set_directory_hook (); |
|
630 |
rl_filename_stat_hook = bash_filename_stat_hook; |
|
631 |
||
632 |
bashline_reset_event_hook (); |
|
633 |
}
|
|
634 |
||
635 |
/* Contains the line to push into readline. */
|
|
636 |
static char *push_to_readline = (char *)NULL; |
|
637 |
||
638 |
/* Push the contents of push_to_readline into the
|
|
639 |
readline buffer. */
|
|
640 |
static int |
|
641 |
bash_push_line () |
|
642 |
{
|
|
643 |
if (push_to_readline) |
|
644 |
{
|
|
645 |
rl_insert_text (push_to_readline); |
|
646 |
free (push_to_readline); |
|
647 |
push_to_readline = (char *)NULL; |
|
648 |
rl_startup_hook = old_rl_startup_hook; |
|
649 |
}
|
|
650 |
return 0; |
|
651 |
}
|
|
652 |
||
653 |
/* Call this to set the initial text for the next line to read
|
|
654 |
from readline. */
|
|
655 |
int
|
|
656 |
bash_re_edit (line) |
|
657 |
char *line; |
|
658 |
{
|
|
659 |
FREE (push_to_readline); |
|
660 |
||
661 |
push_to_readline = savestring (line); |
|
662 |
old_rl_startup_hook = rl_startup_hook; |
|
663 |
rl_startup_hook = bash_push_line; |
|
664 |
||
665 |
return (0); |
|
666 |
}
|
|
667 |
||
668 |
static int |
|
669 |
display_shell_version (count, c) |
|
670 |
int count, c; |
|
671 |
{
|
|
672 |
rl_crlf (); |
|
673 |
show_shell_version (0); |
|
674 |
putc ('\r', rl_outstream); |
|
675 |
fflush (rl_outstream); |
|
676 |
rl_on_new_line (); |
|
677 |
rl_redisplay (); |
|
678 |
return 0; |
|
679 |
}
|
|
680 |
||
681 |
/* **************************************************************** */
|
|
682 |
/* */
|
|
683 |
/* Readline Stuff */
|
|
684 |
/* */
|
|
685 |
/* **************************************************************** */
|
|
686 |
||
687 |
/* If the user requests hostname completion, then simply build a list
|
|
688 |
of hosts, and complete from that forever more, or at least until
|
|
689 |
HOSTFILE is unset. */
|
|
690 |
||
691 |
/* THIS SHOULD BE A STRINGLIST. */
|
|
692 |
/* The kept list of hostnames. */
|
|
693 |
static char **hostname_list = (char **)NULL; |
|
694 |
||
695 |
/* The physical size of the above list. */
|
|
696 |
static int hostname_list_size; |
|
697 |
||
698 |
/* The number of hostnames in the above list. */
|
|
699 |
static int hostname_list_length; |
|
700 |
||
701 |
/* Whether or not HOSTNAME_LIST has been initialized. */
|
|
702 |
int hostname_list_initialized = 0; |
|
703 |
||
704 |
/* Initialize the hostname completion table. */
|
|
705 |
static void |
|
706 |
initialize_hostname_list () |
|
707 |
{
|
|
708 |
char *temp; |
|
709 |
||
710 |
temp = get_string_value ("HOSTFILE"); |
|
711 |
if (temp == 0) |
|
712 |
temp = get_string_value ("hostname_completion_file"); |
|
713 |
if (temp == 0) |
|
714 |
temp = DEFAULT_HOSTS_FILE; |
|
715 |
||
716 |
snarf_hosts_from_file (temp); |
|
717 |
||
718 |
if (hostname_list) |
|
719 |
hostname_list_initialized++; |
|
720 |
}
|
|
721 |
||
722 |
/* Add NAME to the list of hosts. */
|
|
723 |
static void |
|
724 |
add_host_name (name) |
|
725 |
char *name; |
|
726 |
{
|
|
727 |
if (hostname_list_length + 2 > hostname_list_size) |
|
728 |
{
|
|
729 |
hostname_list_size = (hostname_list_size + 32) - (hostname_list_size % 32); |
|
730 |
hostname_list = strvec_resize (hostname_list, hostname_list_size); |
|
731 |
}
|
|
732 |
||
733 |
hostname_list[hostname_list_length++] = savestring (name); |
|
734 |
hostname_list[hostname_list_length] = (char *)NULL; |
|
735 |
}
|
|
736 |
||
737 |
#define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
|
|
738 |
||
739 |
static void |
|
740 |
snarf_hosts_from_file (filename) |
|
741 |
char *filename; |
|
742 |
{
|
|
743 |
FILE *file; |
|
744 |
char *temp, buffer[256], name[256]; |
|
745 |
register int i, start; |
|
746 |
||
747 |
file = fopen (filename, "r"); |
|
748 |
if (file == 0) |
|
749 |
return; |
|
750 |
||
751 |
while (temp = fgets (buffer, 255, file)) |
|
752 |
{
|
|
753 |
/* Skip to first character. */
|
|
754 |
for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++) |
|
755 |
;
|
|
756 |
||
757 |
/* If comment or blank line, ignore. */
|
|
758 |
if (buffer[i] == '\0' || buffer[i] == '#') |
|
759 |
continue; |
|
760 |
||
761 |
/* If `preprocessor' directive, do the include. */
|
|
762 |
if (strncmp (buffer + i, "$include ", 9) == 0) |
|
763 |
{
|
|
764 |
char *incfile, *t; |
|
765 |
||
766 |
/* Find start of filename. */
|
|
767 |
for (incfile = buffer + i + 9; *incfile && whitespace (*incfile); incfile++) |
|
768 |
;
|
|
769 |
||
770 |
/* Find end of filename. */
|
|
771 |
for (t = incfile; *t && cr_whitespace (*t) == 0; t++) |
|
772 |
;
|
|
773 |
||
774 |
*t = '\0'; |
|
775 |
||
776 |
snarf_hosts_from_file (incfile); |
|
777 |
continue; |
|
778 |
}
|
|
779 |
||
780 |
/* Skip internet address if present. */
|
|
781 |
if (DIGIT (buffer[i])) |
|
782 |
for (; buffer[i] && cr_whitespace (buffer[i]) == 0; i++); |
|
783 |
||
784 |
/* Gobble up names. Each name is separated with whitespace. */
|
|
785 |
while (buffer[i]) |
|
786 |
{
|
|
787 |
for (; cr_whitespace (buffer[i]); i++) |
|
788 |
;
|
|
789 |
if (buffer[i] == '\0' || buffer[i] == '#') |
|
790 |
break; |
|
791 |
||
792 |
/* Isolate the current word. */
|
|
793 |
for (start = i; buffer[i] && cr_whitespace (buffer[i]) == 0; i++) |
|
794 |
;
|
|
795 |
if (i == start) |
|
796 |
continue; |
|
797 |
strncpy (name, buffer + start, i - start); |
|
798 |
name[i - start] = '\0'; |
|
799 |
add_host_name (name); |
|
800 |
}
|
|
801 |
}
|
|
802 |
fclose (file); |
|
803 |
}
|
|
804 |
||
805 |
/* Return the hostname list. */
|
|
806 |
char ** |
|
807 |
get_hostname_list () |
|
808 |
{
|
|
809 |
if (hostname_list_initialized == 0) |
|
810 |
initialize_hostname_list (); |
|
811 |
return (hostname_list); |
|
812 |
}
|
|
813 |
||
814 |
void
|
|
815 |
clear_hostname_list () |
|
816 |
{
|
|
817 |
register int i; |
|
818 |
||
819 |
if (hostname_list_initialized == 0) |
|
820 |
return; |
|
821 |
for (i = 0; i < hostname_list_length; i++) |
|
822 |
free (hostname_list[i]); |
|
823 |
hostname_list_length = hostname_list_initialized = 0; |
|
824 |
}
|
|
825 |
||
826 |
/* Return a NULL terminated list of hostnames which begin with TEXT.
|
|
827 |
Initialize the hostname list the first time if necessary.
|
|
828 |
The array is malloc ()'ed, but not the individual strings. */
|
|
829 |
static char ** |
|
830 |
hostnames_matching (text) |
|
831 |
char *text; |
|
832 |
{
|
|
833 |
register int i, len, nmatch, rsize; |
|
834 |
char **result; |
|
835 |
||
836 |
if (hostname_list_initialized == 0) |
|
837 |
initialize_hostname_list (); |
|
838 |
||
839 |
if (hostname_list_initialized == 0) |
|
840 |
return ((char **)NULL); |
|
841 |
||
842 |
/* Special case. If TEXT consists of nothing, then the whole list is
|
|
843 |
what is desired. */
|
|
844 |
if (*text == '\0') |
|
845 |
{
|
|
846 |
result = strvec_create (1 + hostname_list_length); |
|
847 |
for (i = 0; i < hostname_list_length; i++) |
|
848 |
result[i] = hostname_list[i]; |
|
849 |
result[i] = (char *)NULL; |
|
850 |
return (result); |
|
851 |
}
|
|
852 |
||
853 |
/* Scan until found, or failure. */
|
|
854 |
len = strlen (text); |
|
855 |
result = (char **)NULL; |
|
856 |
for (i = nmatch = rsize = 0; i < hostname_list_length; i++) |
|
857 |
{
|
|
858 |
if (STREQN (text, hostname_list[i], len) == 0) |
|
859 |
continue; |
|
860 |
||
861 |
/* OK, it matches. Add it to the list. */
|
|
862 |
if (nmatch >= (rsize - 1)) |
|
863 |
{
|
|
864 |
rsize = (rsize + 16) - (rsize % 16); |
|
865 |
result = strvec_resize (result, rsize); |
|
866 |
}
|
|
867 |
||
868 |
result[nmatch++] = hostname_list[i]; |
|
869 |
}
|
|
870 |
if (nmatch) |
|
871 |
result[nmatch] = (char *)NULL; |
|
872 |
return (result); |
|
873 |
}
|
|
874 |
||
875 |
/* The equivalent of the Korn shell C-o operate-and-get-next-history-line
|
|
876 |
editing command. */
|
|
877 |
static int saved_history_line_to_use = -1; |
|
878 |
static int last_saved_history_line = -1; |
|
879 |
||
880 |
#define HISTORY_FULL() (history_is_stifled () && history_length >= history_max_entries)
|
|
881 |
||
882 |
static int |
|
883 |
set_saved_history () |
|
884 |
{
|
|
885 |
/* XXX - compensate for assumption that history was `shuffled' if it was
|
|
886 |
actually not. */
|
|
887 |
if (HISTORY_FULL () && |
|
888 |
hist_last_line_added == 0 && |
|
889 |
saved_history_line_to_use < history_length - 1) |
|
890 |
saved_history_line_to_use++; |
|
891 |
||
892 |
if (saved_history_line_to_use >= 0) |
|
893 |
{
|
|
894 |
rl_get_previous_history (history_length - saved_history_line_to_use, 0); |
|
895 |
last_saved_history_line = saved_history_line_to_use; |
|
896 |
}
|
|
897 |
saved_history_line_to_use = -1; |
|
898 |
rl_startup_hook = old_rl_startup_hook; |
|
899 |
return (0); |
|
900 |
}
|
|
901 |
||
902 |
static int |
|
903 |
operate_and_get_next (count, c) |
|
904 |
int count, c; |
|
905 |
{
|
|
906 |
int where; |
|
907 |
||
908 |
/* Accept the current line. */
|
|
909 |
rl_newline (1, c); |
|
910 |
||
911 |
/* Find the current line, and find the next line to use. */
|
|
912 |
where = where_history (); |
|
913 |
||
914 |
if (HISTORY_FULL () || (where >= history_length - 1)) |
|
915 |
saved_history_line_to_use = where; |
|
916 |
else
|
|
917 |
saved_history_line_to_use = where + 1; |
|
918 |
||
919 |
old_rl_startup_hook = rl_startup_hook; |
|
920 |
rl_startup_hook = set_saved_history; |
|
921 |
||
922 |
return 0; |
|
923 |
}
|
|
924 |
||
925 |
/* This vi mode command causes VI_EDIT_COMMAND to be run on the current
|
|
926 |
command being entered (if no explicit argument is given), otherwise on
|
|
927 |
a command from the history file. */
|
|
928 |
||
2.2.5
by Matthias Klose
New upstream version 4.3 rc1. |
929 |
#define VI_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-$(command -v editor || echo vi)}}\""
|
930 |
#define EMACS_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-$(command -v editor || echo emacs)}}\""
|
|
1.5.1
by Matthias Klose
Import upstream version 4.3~rc1 |
931 |
#define POSIX_VI_EDIT_COMMAND "fc -e vi"
|
932 |
||
933 |
static int |
|
934 |
edit_and_execute_command (count, c, editing_mode, edit_command) |
|
935 |
int count, c, editing_mode; |
|
936 |
char *edit_command; |
|
937 |
{
|
|
938 |
char *command, *metaval; |
|
939 |
int r, rrs, metaflag; |
|
940 |
sh_parser_state_t ps; |
|
941 |
||
942 |
rrs = rl_readline_state; |
|
943 |
saved_command_line_count = current_command_line_count; |
|
944 |
||
945 |
/* Accept the current line. */
|
|
946 |
rl_newline (1, c); |
|
947 |
||
948 |
if (rl_explicit_arg) |
|
949 |
{
|
|
950 |
command = (char *)xmalloc (strlen (edit_command) + 8); |
|
951 |
sprintf (command, "%s %d", edit_command, count); |
|
952 |
}
|
|
953 |
else
|
|
954 |
{
|
|
955 |
/* Take the command we were just editing, add it to the history file,
|
|
956 |
then call fc to operate on it. We have to add a dummy command to
|
|
957 |
the end of the history because fc ignores the last command (assumes
|
|
958 |
it's supposed to deal with the command before the `fc'). */
|
|
959 |
/* This breaks down when using command-oriented history and are not
|
|
960 |
finished with the command, so we should not ignore the last command */
|
|
961 |
using_history (); |
|
962 |
current_command_line_count++; /* for rl_newline above */ |
|
963 |
bash_add_history (rl_line_buffer); |
|
964 |
current_command_line_count = 0; /* for dummy history entry */ |
|
965 |
bash_add_history (""); |
|
966 |
history_lines_this_session++; |
|
967 |
using_history (); |
|
968 |
command = savestring (edit_command); |
|
969 |
}
|
|
970 |
||
971 |
metaval = rl_variable_value ("input-meta"); |
|
972 |
metaflag = RL_BOOLEAN_VARIABLE_VALUE (metaval); |
|
973 |
||
974 |
/* Now, POSIX.1-2001 and SUSv3 say that the commands executed from the
|
|
975 |
temporary file should be placed into the history. We don't do that
|
|
976 |
yet. */
|
|
977 |
if (rl_deprep_term_function) |
|
978 |
(*rl_deprep_term_function) (); |
|
979 |
save_parser_state (&ps); |
|
980 |
r = parse_and_execute (command, (editing_mode == VI_EDITING_MODE) ? "v" : "C-xC-e", SEVAL_NOHIST); |
|
981 |
restore_parser_state (&ps); |
|
982 |
if (rl_prep_term_function) |
|
983 |
(*rl_prep_term_function) (metaflag); |
|
984 |
||
985 |
current_command_line_count = saved_command_line_count; |
|
986 |
||
987 |
/* Now erase the contents of the current line and undo the effects of the
|
|
988 |
rl_accept_line() above. We don't even want to make the text we just
|
|
989 |
executed available for undoing. */
|
|
990 |
rl_line_buffer[0] = '\0'; /* XXX */ |
|
991 |
rl_point = rl_end = 0; |
|
992 |
rl_done = 0; |
|
993 |
rl_readline_state = rrs; |
|
994 |
||
995 |
rl_forced_update_display (); |
|
996 |
||
997 |
return r; |
|
998 |
}
|
|
999 |
||
1000 |
#if defined (VI_MODE)
|
|
1001 |
static int |
|
1002 |
vi_edit_and_execute_command (count, c) |
|
1003 |
int count, c; |
|
1004 |
{
|
|
1005 |
if (posixly_correct) |
|
1006 |
return (edit_and_execute_command (count, c, VI_EDITING_MODE, POSIX_VI_EDIT_COMMAND)); |
|
1007 |
else
|
|
1008 |
return (edit_and_execute_command (count, c, VI_EDITING_MODE, VI_EDIT_COMMAND)); |
|
1009 |
}
|
|
1010 |
#endif /* VI_MODE */ |
|
1011 |
||
1012 |
static int |
|
1013 |
emacs_edit_and_execute_command (count, c) |
|
1014 |
int count, c; |
|
1015 |
{
|
|
1016 |
return (edit_and_execute_command (count, c, EMACS_EDITING_MODE, EMACS_EDIT_COMMAND)); |
|
1017 |
}
|
|
1018 |
||
1019 |
#if defined (ALIAS)
|
|
1020 |
static int |
|
1021 |
posix_edit_macros (count, key) |
|
1022 |
int count, key; |
|
1023 |
{
|
|
1024 |
int c; |
|
1025 |
char alias_name[3], *alias_value, *macro; |
|
1026 |
||
1027 |
c = rl_read_key (); |
|
1028 |
alias_name[0] = '_'; |
|
1029 |
alias_name[1] = c; |
|
1030 |
alias_name[2] = '\0'; |
|
1031 |
||
1032 |
alias_value = get_alias_value (alias_name); |
|
1033 |
if (alias_value && *alias_value) |
|
1034 |
{
|
|
1035 |
macro = savestring (alias_value); |
|
1036 |
rl_push_macro_input (macro); |
|
1037 |
}
|
|
1038 |
return 0; |
|
1039 |
}
|
|
1040 |
#endif
|
|
1041 |
||
1042 |
/* Bindable commands that move `shell-words': that is, sequences of
|
|
1043 |
non-unquoted-metacharacters. */
|
|
1044 |
||
1045 |
#define WORDDELIM(c) (shellmeta(c) || shellblank(c))
|
|
1046 |
||
1047 |
static int |
|
1048 |
bash_forward_shellword (count, key) |
|
1049 |
int count, key; |
|
1050 |
{
|
|
1051 |
size_t slen; |
|
1052 |
int sindex, c, p; |
|
1053 |
DECLARE_MBSTATE; |
|
1054 |
||
1055 |
if (count < 0) |
|
1056 |
return (bash_backward_shellword (-count, key)); |
|
1057 |
||
1058 |
/* The tricky part of this is deciding whether or not the first character
|
|
1059 |
we're on is an unquoted metacharacter. Not completely handled yet. */
|
|
1060 |
/* XXX - need to test this stuff with backslash-escaped shell
|
|
1061 |
metacharacters and unclosed single- and double-quoted strings. */
|
|
1062 |
||
1063 |
p = rl_point; |
|
1064 |
slen = rl_end; |
|
1065 |
||
1066 |
while (count) |
|
1067 |
{
|
|
1068 |
if (p == rl_end) |
|
1069 |
{
|
|
1070 |
rl_point = rl_end; |
|
1071 |
return 0; |
|
1072 |
}
|
|
1073 |
||
1074 |
/* Are we in a quoted string? If we are, move to the end of the quoted
|
|
1075 |
string and continue the outer loop. We only want quoted strings, not
|
|
1076 |
backslash-escaped characters, but char_is_quoted doesn't
|
|
1077 |
differentiate. */
|
|
1078 |
if (char_is_quoted (rl_line_buffer, p) && p > 0 && rl_line_buffer[p-1] != '\\') |
|
1079 |
{
|
|
1080 |
do
|
|
1081 |
ADVANCE_CHAR (rl_line_buffer, slen, p); |
|
1082 |
while (p < rl_end && char_is_quoted (rl_line_buffer, p)); |
|
1083 |
count--; |
|
1084 |
continue; |
|
1085 |
}
|
|
1086 |
||
1087 |
/* Rest of code assumes we are not in a quoted string. */
|
|
1088 |
/* Move forward until we hit a non-metacharacter. */
|
|
1089 |
while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c)) |
|
1090 |
{
|
|
1091 |
switch (c) |
|
1092 |
{
|
|
1093 |
default: |
|
1094 |
ADVANCE_CHAR (rl_line_buffer, slen, p); |
|
1095 |
continue; /* straight back to loop, don't increment p */ |
|
1096 |
case '\\': |
|
1097 |
if (p < rl_end && rl_line_buffer[p]) |
|
1098 |
ADVANCE_CHAR (rl_line_buffer, slen, p); |
|
1099 |
break; |
|
1100 |
case '\'': |
|
1101 |
p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP); |
|
1102 |
break; |
|
1103 |
case '"': |
|
1104 |
p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP); |
|
1105 |
break; |
|
1106 |
}
|
|
1107 |
||
1108 |
if (p < rl_end) |
|
1109 |
p++; |
|
1110 |
}
|
|
1111 |
||
1112 |
if (rl_line_buffer[p] == 0 || p == rl_end) |
|
1113 |
{
|
|
1114 |
rl_point = rl_end; |
|
1115 |
rl_ding (); |
|
1116 |
return 0; |
|
1117 |
}
|
|
1118 |
||
1119 |
/* Now move forward until we hit a non-quoted metacharacter or EOL */
|
|
1120 |
while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c) == 0) |
|
1121 |
{
|
|
1122 |
switch (c) |
|
1123 |
{
|
|
1124 |
default: |
|
1125 |
ADVANCE_CHAR (rl_line_buffer, slen, p); |
|
1126 |
continue; /* straight back to loop, don't increment p */ |
|
1127 |
case '\\': |
|
1128 |
if (p < rl_end && rl_line_buffer[p]) |
|
1129 |
ADVANCE_CHAR (rl_line_buffer, slen, p); |
|
1130 |
break; |
|
1131 |
case '\'': |
|
1132 |
p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP); |
|
1133 |
break; |
|
1134 |
case '"': |
|
1135 |
p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP); |
|
1136 |
break; |
|
1137 |
}
|
|
1138 |
||
1139 |
if (p < rl_end) |
|
1140 |
p++; |
|
1141 |
}
|
|
1142 |
||
1143 |
if (p == rl_end || rl_line_buffer[p] == 0) |
|
1144 |
{
|
|
1145 |
rl_point = rl_end; |
|
1146 |
return (0); |
|
1147 |
}
|
|
1148 |
||
1149 |
count--; |
|
1150 |
}
|
|
1151 |
||
1152 |
rl_point = p; |
|
1153 |
return (0); |
|
1154 |
}
|
|
1155 |
||
1156 |
static int |
|
1157 |
bash_backward_shellword (count, key) |
|
1158 |
int count, key; |
|
1159 |
{
|
|
1160 |
size_t slen; |
|
1161 |
int sindex, c, p; |
|
1162 |
DECLARE_MBSTATE; |
|
1163 |
||
1164 |
if (count < 0) |
|
1165 |
return (bash_forward_shellword (-count, key)); |
|
1166 |
||
1167 |
p = rl_point; |
|
1168 |
slen = rl_end; |
|
1169 |
||
1170 |
while (count) |
|
1171 |
{
|
|
1172 |
if (p == 0) |
|
1173 |
{
|
|
1174 |
rl_point = 0; |
|
1175 |
return 0; |
|
1176 |
}
|
|
1177 |
||
1178 |
/* Move backward until we hit a non-metacharacter. */
|
|
1179 |
while (p > 0) |
|
1180 |
{
|
|
1181 |
c = rl_line_buffer[p]; |
|
1182 |
if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0) |
|
1183 |
BACKUP_CHAR (rl_line_buffer, slen, p); |
|
1184 |
break; |
|
1185 |
}
|
|
1186 |
||
1187 |
if (p == 0) |
|
1188 |
{
|
|
1189 |
rl_point = 0; |
|
1190 |
return 0; |
|
1191 |
}
|
|
1192 |
||
1193 |
/* Now move backward until we hit a metacharacter or BOL. */
|
|
1194 |
while (p > 0) |
|
1195 |
{
|
|
1196 |
c = rl_line_buffer[p]; |
|
1197 |
if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0) |
|
1198 |
break; |
|
1199 |
BACKUP_CHAR (rl_line_buffer, slen, p); |
|
1200 |
}
|
|
1201 |
||
1202 |
count--; |
|
1203 |
}
|
|
1204 |
||
1205 |
rl_point = p; |
|
1206 |
return 0; |
|
1207 |
}
|
|
1208 |
||
1209 |
static int |
|
1210 |
bash_kill_shellword (count, key) |
|
1211 |
int count, key; |
|
1212 |
{
|
|
1213 |
int p; |
|
1214 |
||
1215 |
if (count < 0) |
|
1216 |
return (bash_backward_kill_shellword (-count, key)); |
|
1217 |
||
1218 |
p = rl_point; |
|
1219 |
bash_forward_shellword (count, key); |
|
1220 |
||
1221 |
if (rl_point != p) |
|
1222 |
rl_kill_text (p, rl_point); |
|
1223 |
||
1224 |
rl_point = p; |
|
1225 |
if (rl_editing_mode == 1) /* 1 == emacs_mode */ |
|
1226 |
rl_mark = rl_point; |
|
1227 |
||
1228 |
return 0; |
|
1229 |
}
|
|
1230 |
||
1231 |
static int |
|
1232 |
bash_backward_kill_shellword (count, key) |
|
1233 |
int count, key; |
|
1234 |
{
|
|
1235 |
int p; |
|
1236 |
||
1237 |
if (count < 0) |
|
1238 |
return (bash_kill_shellword (-count, key)); |
|
1239 |
||
1240 |
p = rl_point; |
|
1241 |
bash_backward_shellword (count, key); |
|
1242 |
||
1243 |
if (rl_point != p) |
|
1244 |
rl_kill_text (p, rl_point); |
|
1245 |
||
1246 |
if (rl_editing_mode == 1) /* 1 == emacs_mode */ |
|
1247 |
rl_mark = rl_point; |
|
1248 |
||
1249 |
return 0; |
|
1250 |
}
|
|
1251 |
||
1252 |
||
1253 |
/* **************************************************************** */
|
|
1254 |
/* */
|
|
1255 |
/* How To Do Shell Completion */
|
|
1256 |
/* */
|
|
1257 |
/* **************************************************************** */
|
|
1258 |
||
1259 |
#define COMMAND_SEPARATORS ";|&{(`"
|
|
1260 |
/* )} */
|
|
1261 |
#define COMMAND_SEPARATORS_PLUS_WS ";|&{(` \t"
|
|
1262 |
/* )} */
|
|
1263 |
||
1264 |
/* check for redirections and other character combinations that are not
|
|
1265 |
command separators */
|
|
1266 |
static int |
|
1267 |
check_redir (ti) |
|
1268 |
int ti; |
|
1269 |
{
|
|
1270 |
register int this_char, prev_char; |
|
1271 |
||
1272 |
/* Handle the two character tokens `>&', `<&', and `>|'.
|
|
1273 |
We are not in a command position after one of these. */
|
|
1274 |
this_char = rl_line_buffer[ti]; |
|
1275 |
prev_char = rl_line_buffer[ti - 1]; |
|
1276 |
||
1277 |
if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) || |
|
1278 |
(this_char == '|' && prev_char == '>')) |
|
1279 |
return (1); |
|
1280 |
else if (this_char == '{' && prev_char == '$') /*}*/ |
|
1281 |
return (1); |
|
1282 |
#if 0 /* Not yet */ |
|
1283 |
else if (this_char == '(' && prev_char == '$') /*)*/
|
|
1284 |
return (1);
|
|
1285 |
else if (this_char == '(' && prev_char == '<') /*)*/
|
|
1286 |
return (1);
|
|
1287 |
#if defined (EXTENDED_GLOB)
|
|
1288 |
else if (extended_glob && this_char == '(' && prev_char == '!') /*)*/
|
|
1289 |
return (1);
|
|
1290 |
#endif
|
|
1291 |
#endif
|
|
1292 |
else if (char_is_quoted (rl_line_buffer, ti)) |
|
1293 |
return (1); |
|
1294 |
return (0); |
|
1295 |
}
|
|
1296 |
||
1297 |
#if defined (PROGRAMMABLE_COMPLETION)
|
|
1298 |
/*
|
|
1299 |
* XXX - because of the <= start test, and setting os = s+1, this can
|
|
1300 |
* potentially return os > start. This is probably not what we want to
|
|
1301 |
* happen, but fix later after 2.05a-release.
|
|
1302 |
*/
|
|
1303 |
static int |
|
1304 |
find_cmd_start (start) |
|
1305 |
int start; |
|
1306 |
{
|
|
1307 |
register int s, os; |
|
1308 |
||
1309 |
os = 0; |
|
1310 |
/* Flags == SD_NOJMP only because we want to skip over command substitutions
|
|
1311 |
in assignment statements. Have to test whether this affects `standalone'
|
|
1312 |
command substitutions as individual words. */
|
|
1313 |
while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS, SD_NOJMP/*|SD_NOSKIPCMD*/)) <= start) && |
|
1314 |
rl_line_buffer[s]) |
|
1315 |
os = s+1; |
|
1316 |
return os; |
|
1317 |
}
|
|
1318 |
||
1319 |
static int |
|
1320 |
find_cmd_end (end) |
|
1321 |
int end; |
|
1322 |
{
|
|
1323 |
register int e; |
|
1324 |
||
1325 |
e = skip_to_delim (rl_line_buffer, end, COMMAND_SEPARATORS, SD_NOJMP); |
|
1326 |
return e; |
|
1327 |
}
|
|
1328 |
||
1329 |
static char * |
|
1330 |
find_cmd_name (start, sp, ep) |
|
1331 |
int start; |
|
1332 |
int *sp, *ep; |
|
1333 |
{
|
|
1334 |
char *name; |
|
1335 |
register int s, e; |
|
1336 |
||
1337 |
for (s = start; whitespace (rl_line_buffer[s]); s++) |
|
1338 |
;
|
|
1339 |
||
1340 |
/* skip until a shell break character */
|
|
1341 |
e = skip_to_delim (rl_line_buffer, s, "()<>;&| \t\n", SD_NOJMP); |
|
1342 |
||
1343 |
name = substring (rl_line_buffer, s, e); |
|
1344 |
||
1345 |
if (sp) |
|
1346 |
*sp = s; |
|
1347 |
if (ep) |
|
1348 |
*ep = e; |
|
1349 |
||
1350 |
return (name); |
|
1351 |
}
|
|
1352 |
||
1353 |
static char * |
|
1354 |
prog_complete_return (text, matchnum) |
|
1355 |
const char *text; |
|
1356 |
int matchnum; |
|
1357 |
{
|
|
1358 |
static int ind; |
|
1359 |
||
1360 |
if (matchnum == 0) |
|
1361 |
ind = 0; |
|
1362 |
||
1363 |
if (prog_complete_matches == 0 || prog_complete_matches[ind] == 0) |
|
1364 |
return (char *)NULL; |
|
1365 |
return (prog_complete_matches[ind++]); |
|
1366 |
}
|
|
1367 |
||
1368 |
#endif /* PROGRAMMABLE_COMPLETION */ |
|
1369 |
||
1370 |
/* Do some completion on TEXT. The indices of TEXT in RL_LINE_BUFFER are
|
|
1371 |
at START and END. Return an array of matches, or NULL if none. */
|
|
1372 |
static char ** |
|
1373 |
attempt_shell_completion (text, start, end) |
|
1374 |
const char *text; |
|
1375 |
int start, end; |
|
1376 |
{
|
|
1377 |
int in_command_position, ti, saveti, qc, dflags; |
|
1378 |
char **matches, *command_separator_chars; |
|
1379 |
#if defined (PROGRAMMABLE_COMPLETION)
|
|
1380 |
int have_progcomps, was_assignment; |
|
1381 |
#endif
|
|
1382 |
||
1383 |
command_separator_chars = COMMAND_SEPARATORS; |
|
1384 |
matches = (char **)NULL; |
|
1385 |
rl_ignore_some_completions_function = filename_completion_ignore; |
|
1386 |
||
1387 |
rl_filename_quote_characters = default_filename_quote_characters; |
|
1388 |
set_filename_bstab (rl_filename_quote_characters); |
|
1389 |
set_directory_hook (); |
|
1390 |
rl_filename_stat_hook = bash_filename_stat_hook; |
|
1391 |
||
1392 |
/* Determine if this could be a command word. It is if it appears at
|
|
1393 |
the start of the line (ignoring preceding whitespace), or if it
|
|
1394 |
appears after a character that separates commands. It cannot be a
|
|
1395 |
command word if we aren't at the top-level prompt. */
|
|
1396 |
ti = start - 1; |
|
1397 |
saveti = qc = -1; |
|
1398 |
||
1399 |
while ((ti > -1) && (whitespace (rl_line_buffer[ti]))) |
|
1400 |
ti--; |
|
1401 |
||
1402 |
#if 1
|
|
1403 |
/* If this is an open quote, maybe we're trying to complete a quoted
|
|
1404 |
command name. */
|
|
1405 |
if (ti >= 0 && (rl_line_buffer[ti] == '"' || rl_line_buffer[ti] == '\'')) |
|
1406 |
{
|
|
1407 |
qc = rl_line_buffer[ti]; |
|
1408 |
saveti = ti--; |
|
1409 |
while (ti > -1 && (whitespace (rl_line_buffer[ti]))) |
|
1410 |
ti--; |
|
1411 |
}
|
|
1412 |
#endif
|
|
1413 |
||
1414 |
in_command_position = 0; |
|
1415 |
if (ti < 0) |
|
1416 |
{
|
|
1417 |
/* Only do command completion at the start of a line when we
|
|
1418 |
are prompting at the top level. */
|
|
1419 |
if (current_prompt_string == ps1_prompt) |
|
1420 |
in_command_position++; |
|
1421 |
else if (parser_in_command_position ()) |
|
1422 |
in_command_position++; |
|
1423 |
}
|
|
1424 |
else if (member (rl_line_buffer[ti], command_separator_chars)) |
|
1425 |
{
|
|
1426 |
in_command_position++; |
|
1427 |
||
1428 |
if (check_redir (ti) == 1) |
|
1429 |
in_command_position = 0; |
|
1430 |
}
|
|
1431 |
else
|
|
1432 |
{
|
|
1433 |
/* This still could be in command position. It is possible
|
|
1434 |
that all of the previous words on the line are variable
|
|
1435 |
assignments. */
|
|
1436 |
}
|
|
1437 |
||
1438 |
/* Check that we haven't incorrectly flagged a closed command substitution
|
|
1439 |
as indicating we're in a command position. */
|
|
1440 |
if (in_command_position && ti >= 0 && rl_line_buffer[ti] == '`' && |
|
1441 |
*text != '`' && unclosed_pair (rl_line_buffer, end, "`") == 0) |
|
1442 |
in_command_position = 0; |
|
1443 |
||
1444 |
/* Special handling for command substitution. If *TEXT is a backquote,
|
|
1445 |
it can be the start or end of an old-style command substitution, or
|
|
1446 |
unmatched. If it's unmatched, both calls to unclosed_pair will
|
|
1447 |
succeed. Don't bother if readline found a single quote and we are
|
|
1448 |
completing on the substring. */
|
|
1449 |
if (*text == '`' && rl_completion_quote_character != '\'' && |
|
1450 |
(in_command_position || (unclosed_pair (rl_line_buffer, start, "`") && |
|
1451 |
unclosed_pair (rl_line_buffer, end, "`")))) |
|
1452 |
matches = rl_completion_matches (text, command_subst_completion_function); |
|
1453 |
||
1454 |
#if defined (PROGRAMMABLE_COMPLETION)
|
|
1455 |
/* Attempt programmable completion. */
|
|
1456 |
have_progcomps = prog_completion_enabled && (progcomp_size () > 0); |
|
1457 |
if (matches == 0 && (in_command_position == 0 || text[0] == '\0') && |
|
1458 |
current_prompt_string == ps1_prompt) |
|
1459 |
{
|
|
1460 |
int s, e, s1, e1, os, foundcs; |
|
1461 |
char *n; |
|
1462 |
||
1463 |
/* XXX - don't free the members */
|
|
1464 |
if (prog_complete_matches) |
|
1465 |
free (prog_complete_matches); |
|
1466 |
prog_complete_matches = (char **)NULL; |
|
1467 |
||
1468 |
os = start; |
|
1469 |
n = 0; |
|
1470 |
s = find_cmd_start (os); |
|
1471 |
e = find_cmd_end (end); |
|
1472 |
do
|
|
1473 |
{
|
|
1474 |
/* Skip over assignment statements preceding a command name. If we
|
|
1475 |
don't find a command name at all, we can perform command name
|
|
1476 |
completion. If we find a partial command name, we should perform
|
|
1477 |
command name completion on it. */
|
|
1478 |
FREE (n); |
|
1479 |
n = find_cmd_name (s, &s1, &e1); |
|
1480 |
s = e1 + 1; |
|
1481 |
}
|
|
1482 |
while (was_assignment = assignment (n, 0)); |
|
1483 |
s = s1; /* reset to index where name begins */ |
|
1484 |
||
1485 |
/* s == index of where command name begins (reset above)
|
|
1486 |
e == end of current command, may be end of line
|
|
1487 |
s1 = index of where command name begins
|
|
1488 |
e1 == index of where command name ends
|
|
1489 |
start == index of where word to be completed begins
|
|
1490 |
end == index of where word to be completed ends
|
|
1491 |
if (s == start) we are doing command word completion for sure
|
|
1492 |
if (e1 == end) we are at the end of the command name and completing it */
|
|
1493 |
if (start == 0 && end == 0 && e != 0 && text[0] == '\0') /* beginning of non-empty line */ |
|
1494 |
foundcs = 0; |
|
1495 |
else if (start == end && start == s1 && e != 0 && e1 > end) /* beginning of command name, leading whitespace */ |
|
1496 |
foundcs = 0; |
|
1497 |
else if (e == 0 && e == s && text[0] == '\0' && have_progcomps) /* beginning of empty line */ |
|
1498 |
prog_complete_matches = programmable_completions ("_EmptycmD_", text, s, e, &foundcs); |
|
1499 |
else if (start == end && text[0] == '\0' && s1 > start && whitespace (rl_line_buffer[start])) |
|
1500 |
foundcs = 0; /* whitespace before command name */ |
|
1501 |
else if (e > s && was_assignment == 0 && e1 == end && rl_line_buffer[e] == 0 && whitespace (rl_line_buffer[e-1]) == 0) |
|
1502 |
{
|
|
1503 |
/* not assignment statement, but still want to perform command
|
|
1504 |
completion if we are composing command word. */
|
|
1505 |
foundcs = 0; |
|
1506 |
in_command_position = s == start && STREQ (n, text); /* XXX */ |
|
1507 |
}
|
|
1508 |
else if (e > s && was_assignment == 0 && have_progcomps) |
|
1509 |
{
|
|
1510 |
prog_complete_matches = programmable_completions (n, text, s, e, &foundcs); |
|
1511 |
/* command completion if programmable completion fails */
|
|
1512 |
in_command_position = s == start && STREQ (n, text); /* XXX */ |
|
1513 |
}
|
|
1514 |
else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0) |
|
1515 |
{
|
|
1516 |
foundcs = 0; /* empty command name following assignments */ |
|
1517 |
in_command_position = was_assignment; |
|
1518 |
}
|
|
1519 |
else if (s == start && e == end && STREQ (n, text) && start > 0) |
|
1520 |
{
|
|
1521 |
foundcs = 0; /* partial command name following assignments */ |
|
1522 |
in_command_position = 1; |
|
1523 |
}
|
|
1524 |
else
|
|
1525 |
foundcs = 0; |
|
1526 |
FREE (n); |
|
1527 |
/* XXX - if we found a COMPSPEC for the command, just return whatever
|
|
1528 |
the programmable completion code returns, and disable the default
|
|
1529 |
filename completion that readline will do unless the COPT_DEFAULT
|
|
1530 |
option has been set with the `-o default' option to complete or
|
|
1531 |
compopt. */
|
|
1532 |
if (foundcs) |
|
1533 |
{
|
|
1534 |
pcomp_set_readline_variables (foundcs, 1); |
|
1535 |
/* Turn what the programmable completion code returns into what
|
|
1536 |
readline wants. I should have made compute_lcd_of_matches
|
|
1537 |
external... */
|
|
1538 |
matches = rl_completion_matches (text, prog_complete_return); |
|
1539 |
if ((foundcs & COPT_DEFAULT) == 0) |
|
1540 |
rl_attempted_completion_over = 1; /* no default */ |
|
1541 |
if (matches || ((foundcs & COPT_BASHDEFAULT) == 0)) |
|
1542 |
return (matches); |
|
1543 |
}
|
|
1544 |
}
|
|
1545 |
#endif
|
|
1546 |
||
1547 |
if (matches == 0) |
|
1548 |
{
|
|
1549 |
dflags = 0; |
|
1550 |
if (in_command_position) |
|
1551 |
dflags |= DEFCOMP_CMDPOS; |
|
1552 |
matches = bash_default_completion (text, start, end, qc, dflags); |
|
1553 |
}
|
|
1554 |
||
1555 |
return matches; |
|
1556 |
}
|
|
1557 |
||
1558 |
char ** |
|
1559 |
bash_default_completion (text, start, end, qc, compflags) |
|
1560 |
const char *text; |
|
1561 |
int start, end, qc, compflags; |
|
1562 |
{
|
|
1563 |
char **matches, *t; |
|
1564 |
||
1565 |
matches = (char **)NULL; |
|
1566 |
||
1567 |
/* New posix-style command substitution or variable name? */
|
|
1568 |
if (!matches && *text == '$') |
|
1569 |
{
|
|
1570 |
if (qc != '\'' && text[1] == '(') /* ) */ |
|
1571 |
matches = rl_completion_matches (text, command_subst_completion_function); |
|
1572 |
else
|
|
1573 |
{
|
|
1574 |
matches = rl_completion_matches (text, variable_completion_function); |
|
1575 |
if (matches && matches[0] && matches[1] == 0) |
|
1576 |
{
|
|
1577 |
t = savestring (matches[0]); |
|
1578 |
bash_filename_stat_hook (&t); |
|
1579 |
/* doesn't use test_for_directory because that performs tilde
|
|
1580 |
expansion */
|
|
1581 |
if (file_isdir (t)) |
|
1582 |
rl_completion_append_character = '/'; |
|
1583 |
free (t); |
|
1584 |
}
|
|
1585 |
}
|
|
1586 |
}
|
|
1587 |
||
1588 |
/* If the word starts in `~', and there is no slash in the word, then
|
|
1589 |
try completing this word as a username. */
|
|
1590 |
if (matches == 0 && *text == '~' && mbschr (text, '/') == 0) |
|
1591 |
matches = rl_completion_matches (text, rl_username_completion_function); |
|
1592 |
||
1593 |
/* Another one. Why not? If the word starts in '@', then look through
|
|
1594 |
the world of known hostnames for completion first. */
|
|
1595 |
if (matches == 0 && perform_hostname_completion && *text == '@') |
|
1596 |
matches = rl_completion_matches (text, hostname_completion_function); |
|
1597 |
||
1598 |
/* And last, (but not least) if this word is in a command position, then
|
|
1599 |
complete over possible command names, including aliases, functions,
|
|
1600 |
and command names. */
|
|
1601 |
if (matches == 0 && (compflags & DEFCOMP_CMDPOS)) |
|
1602 |
{
|
|
1603 |
/* If END == START and text[0] == 0, we are trying to complete an empty
|
|
1604 |
command word. */
|
|
1605 |
if (no_empty_command_completion && end == start && text[0] == '\0') |
|
1606 |
{
|
|
1607 |
matches = (char **)NULL; |
|
1608 |
rl_ignore_some_completions_function = bash_ignore_everything; |
|
1609 |
}
|
|
1610 |
else
|
|
1611 |
{
|
|
1612 |
#define CMD_IS_DIR(x) (absolute_pathname(x) == 0 && absolute_program(x) == 0 && *(x) != '~' && test_for_directory (x))
|
|
1613 |
||
1614 |
dot_in_path = 0; |
|
1615 |
matches = rl_completion_matches (text, command_word_completion_function); |
|
1616 |
||
1617 |
/* If we are attempting command completion and nothing matches, we
|
|
1618 |
do not want readline to perform filename completion for us. We
|
|
1619 |
still want to be able to complete partial pathnames, so set the
|
|
1620 |
completion ignore function to something which will remove
|
|
1621 |
filenames and leave directories in the match list. */
|
|
1622 |
if (matches == (char **)NULL) |
|
1623 |
rl_ignore_some_completions_function = bash_ignore_filenames; |
|
1624 |
else if (matches[1] == 0 && CMD_IS_DIR(matches[0]) && dot_in_path == 0) |
|
1625 |
/* If we found a single match, without looking in the current
|
|
1626 |
directory (because it's not in $PATH), but the found name is
|
|
1627 |
also a command in the current directory, suppress appending any
|
|
1628 |
terminating character, since it's ambiguous. */
|
|
1629 |
{
|
|
1630 |
rl_completion_suppress_append = 1; |
|
1631 |
rl_filename_completion_desired = 0; |
|
1632 |
}
|
|
1633 |
else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) && CMD_IS_DIR (matches[0])) |
|
1634 |
/* There are multiple instances of the same match (duplicate
|
|
1635 |
completions haven't yet been removed). In this case, all of
|
|
1636 |
the matches will be the same, and the duplicate removal code
|
|
1637 |
will distill them all down to one. We turn on
|
|
1638 |
rl_completion_suppress_append for the same reason as above.
|
|
1639 |
Remember: we only care if there's eventually a single unique
|
|
1640 |
completion. If there are multiple completions this won't
|
|
1641 |
make a difference and the problem won't occur. */
|
|
1642 |
{
|
|
1643 |
rl_completion_suppress_append = 1; |
|
1644 |
rl_filename_completion_desired = 0; |
|
1645 |
}
|
|
1646 |
}
|
|
1647 |
}
|
|
1648 |
||
1649 |
/* This could be a globbing pattern, so try to expand it using pathname
|
|
1650 |
expansion. */
|
|
1651 |
if (!matches && glob_pattern_p (text)) |
|
1652 |
{
|
|
1653 |
matches = rl_completion_matches (text, glob_complete_word); |
|
1654 |
/* A glob expression that matches more than one filename is problematic.
|
|
1655 |
If we match more than one filename, punt. */
|
|
1656 |
if (matches && matches[1] && rl_completion_type == TAB) |
|
1657 |
{
|
|
1658 |
strvec_dispose (matches); |
|
1659 |
matches = (char **)0; |
|
1660 |
}
|
|
1661 |
else if (matches && matches[1] && rl_completion_type == '!') |
|
1662 |
{
|
|
1663 |
rl_completion_suppress_append = 1; |
|
1664 |
rl_filename_completion_desired = 0; |
|
1665 |
}
|
|
1666 |
}
|
|
1667 |
||
1668 |
return (matches); |
|
1669 |
}
|
|
1670 |
||
1671 |
static int |
|
1672 |
bash_command_name_stat_hook (name) |
|
1673 |
char **name; |
|
1674 |
{
|
|
1675 |
char *cname, *result; |
|
1676 |
||
1677 |
/* If it's not something we're going to look up in $PATH, just call the
|
|
1678 |
normal filename stat hook. */
|
|
1679 |
if (absolute_program (*name)) |
|
1680 |
return (bash_filename_stat_hook (name)); |
|
1681 |
||
1682 |
cname = *name; |
|
1683 |
/* XXX - we could do something here with converting aliases, builtins,
|
|
1684 |
and functions into something that came out as executable, but we don't. */
|
|
1685 |
result = search_for_command (cname, 0); |
|
1686 |
if (result) |
|
1687 |
{
|
|
1688 |
*name = result; |
|
1689 |
return 1; |
|
1690 |
}
|
|
1691 |
return 0; |
|
1692 |
}
|
|
1693 |
||
1694 |
static int |
|
1695 |
executable_completion (filename, searching_path) |
|
1696 |
const char *filename; |
|
1697 |
int searching_path; |
|
1698 |
{
|
|
1699 |
char *f; |
|
1700 |
int r; |
|
1701 |
||
1702 |
f = savestring (filename); |
|
1703 |
bash_directory_completion_hook (&f); |
|
1704 |
||
1705 |
r = searching_path ? executable_file (f) : executable_or_directory (f); |
|
1706 |
free (f); |
|
1707 |
return r; |
|
1708 |
}
|
|
1709 |
||
1710 |
/* This is the function to call when the word to complete is in a position
|
|
1711 |
where a command word can be found. It grovels $PATH, looking for commands
|
|
1712 |
that match. It also scans aliases, function names, and the shell_builtin
|
|
1713 |
table. */
|
|
1714 |
char * |
|
1715 |
command_word_completion_function (hint_text, state) |
|
1716 |
const char *hint_text; |
|
1717 |
int state; |
|
1718 |
{
|
|
1719 |
static char *hint = (char *)NULL; |
|
1720 |
static char *path = (char *)NULL; |
|
1721 |
static char *val = (char *)NULL; |
|
1722 |
static char *filename_hint = (char *)NULL; |
|
1.4.3
by Matthias Klose
Import upstream version 4.3 |
1723 |
static char *fnhint = (char *)NULL; |
1.5.1
by Matthias Klose
Import upstream version 4.3~rc1 |
1724 |
static char *dequoted_hint = (char *)NULL; |
1725 |
static char *directory_part = (char *)NULL; |
|
1726 |
static char **glob_matches = (char **)NULL; |
|
1727 |
static int path_index, hint_len, dequoted_len, istate, igncase; |
|
1728 |
static int mapping_over, local_index, searching_path, hint_is_dir; |
|
1729 |
static int old_glob_ignore_case, globpat; |
|
1730 |
static SHELL_VAR **varlist = (SHELL_VAR **)NULL; |
|
1731 |
#if defined (ALIAS)
|
|
1732 |
static alias_t **alias_list = (alias_t **)NULL; |
|
1733 |
#endif /* ALIAS */ |
|
1734 |
char *temp, *cval; |
|
1735 |
||
1736 |
/* We have to map over the possibilities for command words. If we have
|
|
1737 |
no state, then make one just for that purpose. */
|
|
1738 |
if (state == 0) |
|
1739 |
{
|
|
1740 |
rl_filename_stat_hook = bash_command_name_stat_hook; |
|
1741 |
||
1742 |
if (dequoted_hint && dequoted_hint != hint) |
|
1743 |
free (dequoted_hint); |
|
1744 |
if (hint) |
|
1745 |
free (hint); |
|
1746 |
||
1747 |
mapping_over = searching_path = 0; |
|
1748 |
hint_is_dir = CMD_IS_DIR (hint_text); |
|
1749 |
val = (char *)NULL; |
|
1750 |
||
1751 |
temp = rl_variable_value ("completion-ignore-case"); |
|
1752 |
igncase = RL_BOOLEAN_VARIABLE_VALUE (temp); |
|
1753 |
||
1754 |
if (glob_matches) |
|
1755 |
{
|
|
1756 |
free (glob_matches); |
|
1757 |
glob_matches = (char **)NULL; |
|
1758 |
}
|
|
1759 |
||
1760 |
globpat = glob_pattern_p (hint_text); |
|
1761 |
||
1762 |
/* If this is an absolute program name, do not check it against
|
|
1763 |
aliases, reserved words, functions or builtins. We must check
|
|
1764 |
whether or not it is unique, and, if so, whether that filename
|
|
1765 |
is executable. */
|
|
1766 |
if (globpat || absolute_program (hint_text)) |
|
1767 |
{
|
|
1768 |
/* Perform tilde expansion on what's passed, so we don't end up
|
|
1769 |
passing filenames with tildes directly to stat(). */
|
|
1770 |
if (*hint_text == '~') |
|
1771 |
{
|
|
1772 |
hint = bash_tilde_expand (hint_text, 0); |
|
1773 |
directory_part = savestring (hint_text); |
|
1774 |
temp = strchr (directory_part, '/'); |
|
1775 |
if (temp) |
|
1776 |
*temp = 0; |
|
1777 |
else
|
|
1778 |
{
|
|
1779 |
free (directory_part); |
|
1780 |
directory_part = (char *)NULL; |
|
1781 |
}
|
|
1782 |
}
|
|
1783 |
else
|
|
1784 |
hint = savestring (hint_text); |
|
1785 |
||
1786 |
dequoted_hint = hint; |
|
1787 |
/* If readline's completer found a quote character somewhere, but
|
|
1788 |
didn't set the quote character, there must have been a quote
|
|
1789 |
character embedded in the filename. It can't be at the start of
|
|
1790 |
the filename, so we need to dequote the filename before we look
|
|
1791 |
in the file system for it. */
|
|
1792 |
if (rl_completion_found_quote && rl_completion_quote_character == 0) |
|
1793 |
{
|
|
1794 |
dequoted_hint = bash_dequote_filename (hint, 0); |
|
1795 |
free (hint); |
|
1796 |
hint = dequoted_hint; |
|
1797 |
}
|
|
1798 |
dequoted_len = hint_len = strlen (hint); |
|
1799 |
||
1800 |
if (filename_hint) |
|
1801 |
free (filename_hint); |
|
1802 |
||
1.4.3
by Matthias Klose
Import upstream version 4.3 |
1803 |
fnhint = filename_hint = savestring (hint); |
1.5.1
by Matthias Klose
Import upstream version 4.3~rc1 |
1804 |
|
1805 |
istate = 0; |
|
1806 |
||
1807 |
if (globpat) |
|
1808 |
{
|
|
1809 |
mapping_over = 5; |
|
1810 |
goto globword; |
|
1811 |
}
|
|
1812 |
else
|
|
1813 |
{
|
|
1814 |
if (dircomplete_expand && path_dot_or_dotdot (filename_hint)) |
|
1815 |
{
|
|
1816 |
dircomplete_expand = 0; |
|
1817 |
set_directory_hook (); |
|
1818 |
dircomplete_expand = 1; |
|
1819 |
}
|
|
1820 |
mapping_over = 4; |
|
1821 |
goto inner; |
|
1822 |
}
|
|
1823 |
}
|
|
1824 |
||
1825 |
dequoted_hint = hint = savestring (hint_text); |
|
1826 |
dequoted_len = hint_len = strlen (hint); |
|
1827 |
||
1828 |
if (rl_completion_found_quote && rl_completion_quote_character == 0) |
|
1829 |
{
|
|
1830 |
dequoted_hint = bash_dequote_filename (hint, 0); |
|
1831 |
dequoted_len = strlen (dequoted_hint); |
|
1832 |
}
|
|
1833 |
||
1834 |
path = get_string_value ("PATH"); |
|
1835 |
path_index = dot_in_path = 0; |
|
1836 |
||
1837 |
/* Initialize the variables for each type of command word. */
|
|
1838 |
local_index = 0; |
|
1839 |
||
1840 |
if (varlist) |
|
1841 |
free (varlist); |
|
1842 |
||
1843 |
varlist = all_visible_functions (); |
|
1844 |
||
1845 |
#if defined (ALIAS)
|
|
1846 |
if (alias_list) |
|
1847 |
free (alias_list); |
|
1848 |
||
1849 |
alias_list = all_aliases (); |
|
1850 |
#endif /* ALIAS */ |
|
1851 |
}
|
|
1852 |
||
1853 |
/* mapping_over says what we are currently hacking. Note that every case
|
|
1854 |
in this list must fall through when there are no more possibilities. */
|
|
1855 |
||
1856 |
switch (mapping_over) |
|
1857 |
{
|
|
1858 |
case 0: /* Aliases come first. */ |
|
1859 |
#if defined (ALIAS)
|
|
1860 |
while (alias_list && alias_list[local_index]) |
|
1861 |
{
|
|
1862 |
register char *alias; |
|
1863 |
||
1864 |
alias = alias_list[local_index++]->name; |
|
1865 |
||
1866 |
if (STREQN (alias, hint, hint_len)) |
|
1867 |
return (savestring (alias)); |
|
1868 |
}
|
|
1869 |
#endif /* ALIAS */ |
|
1870 |
local_index = 0; |
|
1871 |
mapping_over++; |
|
1872 |
||
1873 |
case 1: /* Then shell reserved words. */ |
|
1874 |
{
|
|
1875 |
while (word_token_alist[local_index].word) |
|
1876 |
{
|
|
1877 |
register char *reserved_word; |
|
1878 |
||
1879 |
reserved_word = word_token_alist[local_index++].word; |
|
1880 |
||
1881 |
if (STREQN (reserved_word, hint, hint_len)) |
|
1882 |
return (savestring (reserved_word)); |
|
1883 |
}
|
|
1884 |
local_index = 0; |
|
1885 |
mapping_over++; |
|
1886 |
}
|
|
1887 |
||
1888 |
case 2: /* Then function names. */ |
|
1889 |
while (varlist && varlist[local_index]) |
|
1890 |
{
|
|
1891 |
register char *varname; |
|
1892 |
||
1893 |
varname = varlist[local_index++]->name; |
|
1894 |
||
1895 |
if (STREQN (varname, hint, hint_len)) |
|
1896 |
return (savestring (varname)); |
|
1897 |
}
|
|
1898 |
local_index = 0; |
|
1899 |
mapping_over++; |
|
1900 |
||
1901 |
case 3: /* Then shell builtins. */ |
|
1902 |
for (; local_index < num_shell_builtins; local_index++) |
|
1903 |
{
|
|
1904 |
/* Ignore it if it doesn't have a function pointer or if it
|
|
1905 |
is not currently enabled. */
|
|
1906 |
if (!shell_builtins[local_index].function || |
|
1907 |
(shell_builtins[local_index].flags & BUILTIN_ENABLED) == 0) |
|
1908 |
continue; |
|
1909 |
||
1910 |
if (STREQN (shell_builtins[local_index].name, hint, hint_len)) |
|
1911 |
{
|
|
1912 |
int i = local_index++; |
|
1913 |
||
1914 |
return (savestring (shell_builtins[i].name)); |
|
1915 |
}
|
|
1916 |
}
|
|
1917 |
local_index = 0; |
|
1918 |
mapping_over++; |
|
1919 |
}
|
|
1920 |
||
1921 |
globword: |
|
1922 |
/* Limited support for completing command words with globbing chars. Only
|
|
1923 |
a single match (multiple matches that end up reducing the number of
|
|
1924 |
characters in the common prefix are bad) will ever be returned on
|
|
1925 |
regular completion. */
|
|
1926 |
if (globpat) |
|
1927 |
{
|
|
1928 |
if (state == 0) |
|
1929 |
{
|
|
1930 |
glob_ignore_case = igncase; |
|
1931 |
glob_matches = shell_glob_filename (hint); |
|
1932 |
glob_ignore_case = old_glob_ignore_case; |
|
1933 |
||
1934 |
if (GLOB_FAILED (glob_matches) || glob_matches == 0) |
|
1935 |
{
|
|
1936 |
glob_matches = (char **)NULL; |
|
1937 |
return ((char *)NULL); |
|
1938 |
}
|
|
1939 |
||
1940 |
local_index = 0; |
|
1941 |
||
1942 |
if (glob_matches[1] && rl_completion_type == TAB) /* multiple matches are bad */ |
|
1943 |
return ((char *)NULL); |
|
1944 |
}
|
|
1945 |
||
1946 |
while (val = glob_matches[local_index++]) |
|
1947 |
{
|
|
1948 |
if (executable_or_directory (val)) |
|
1949 |
{
|
|
1950 |
if (*hint_text == '~' && directory_part) |
|
1951 |
{
|
|
1952 |
temp = maybe_restore_tilde (val, directory_part); |
|
1953 |
free (val); |
|
1954 |
val = temp; |
|
1955 |
}
|
|
1956 |
return (val); |
|
1957 |
}
|
|
1958 |
free (val); |
|
1959 |
}
|
|
1960 |
||
1961 |
glob_ignore_case = old_glob_ignore_case; |
|
1962 |
return ((char *)NULL); |
|
1963 |
}
|
|
1964 |
||
1965 |
/* If the text passed is a directory in the current directory, return it
|
|
1966 |
as a possible match. Executables in directories in the current
|
|
1967 |
directory can be specified using relative pathnames and successfully
|
|
1968 |
executed even when `.' is not in $PATH. */
|
|
1969 |
if (hint_is_dir) |
|
1970 |
{
|
|
1971 |
hint_is_dir = 0; /* only return the hint text once */ |
|
1972 |
return (savestring (hint_text)); |
|
1973 |
}
|
|
1974 |
||
1975 |
/* Repeatedly call filename_completion_function while we have
|
|
1976 |
members of PATH left. Question: should we stat each file?
|
|
1977 |
Answer: we call executable_file () on each file. */
|
|
1978 |
outer: |
|
1979 |
||
1980 |
istate = (val != (char *)NULL); |
|
1981 |
||
1982 |
if (istate == 0) |
|
1983 |
{
|
|
1984 |
char *current_path; |
|
1985 |
||
1986 |
/* Get the next directory from the path. If there is none, then we
|
|
1987 |
are all done. */
|
|
1988 |
if (path == 0 || path[path_index] == 0 || |
|
1989 |
(current_path = extract_colon_unit (path, &path_index)) == 0) |
|
1990 |
return ((char *)NULL); |
|
1991 |
||
1992 |
searching_path = 1; |
|
1993 |
if (*current_path == 0) |
|
1994 |
{
|
|
1995 |
free (current_path); |
|
1996 |
current_path = savestring ("."); |
|
1997 |
}
|
|
1998 |
||
1999 |
if (*current_path == '~') |
|
2000 |
{
|
|
2001 |
char *t; |
|
2002 |
||
2003 |
t = bash_tilde_expand (current_path, 0); |
|
2004 |
free (current_path); |
|
2005 |
current_path = t; |
|
2006 |
}
|
|
2007 |
||
2008 |
if (current_path[0] == '.' && current_path[1] == '\0') |
|
2009 |
dot_in_path = 1; |
|
2010 |
||
1.4.3
by Matthias Klose
Import upstream version 4.3 |
2011 |
if (fnhint && fnhint != filename_hint) |
2012 |
free (fnhint); |
|
1.5.1
by Matthias Klose
Import upstream version 4.3~rc1 |
2013 |
if (filename_hint) |
2014 |
free (filename_hint); |
|
2015 |
||
2016 |
filename_hint = sh_makepath (current_path, hint, 0); |
|
1.4.3
by Matthias Klose
Import upstream version 4.3 |
2017 |
/* Need a quoted version (though it doesn't matter much in most
|
2018 |
cases) because rl_filename_completion_function dequotes the
|
|
2019 |
filename it gets, assuming that it's been quoted as part of
|
|
2020 |
the input line buffer. */
|
|
2021 |
if (strpbrk (filename_hint, "\"'\\")) |
|
2022 |
fnhint = sh_backslash_quote (filename_hint, filename_bstab, 0); |
|
2023 |
else
|
|
2024 |
fnhint = filename_hint; |
|
1.5.1
by Matthias Klose
Import upstream version 4.3~rc1 |
2025 |
free (current_path); /* XXX */ |
2026 |
}
|
|
2027 |
||
2028 |
inner: |
|
1.4.3
by Matthias Klose
Import upstream version 4.3 |
2029 |
val = rl_filename_completion_function (fnhint, istate); |
1.5.1
by Matthias Klose
Import upstream version 4.3~rc1 |
2030 |
if (mapping_over == 4 && dircomplete_expand) |
2031 |
set_directory_hook (); |
|
2032 |
||
2033 |
istate = 1; |
|
2034 |
||
2035 |
if (val == 0) |
|
2036 |
{
|
|
2037 |
/* If the hint text is an absolute program, then don't bother
|
|
2038 |
searching through PATH. */
|
|
2039 |
if (absolute_program (hint)) |
|
2040 |
return ((char *)NULL); |
|
2041 |
||
2042 |
goto outer; |
|
2043 |
}
|
|
2044 |
else
|
|
2045 |
{
|
|
2046 |
int match, freetemp; |
|
2047 |
||
2048 |
if (absolute_program (hint)) |
|
2049 |
{
|
|
2050 |
if (igncase == 0) |
|
2051 |
match = strncmp (val, hint, hint_len) == 0; |
|
2052 |
else
|
|
2053 |
match = strncasecmp (val, hint, hint_len) == 0; |
|
2054 |
||
2055 |
/* If we performed tilde expansion, restore the original
|
|
2056 |
filename. */
|
|
2057 |
if (*hint_text == '~') |
|
2058 |
temp = maybe_restore_tilde (val, directory_part); |
|
2059 |
else
|
|
2060 |
temp = savestring (val); |
|
2061 |
freetemp = 1; |
|
2062 |
}
|
|
2063 |
else
|
|
2064 |
{
|
|
2065 |
temp = strrchr (val, '/'); |
|
2066 |
||
2067 |
if (temp) |
|
2068 |
{
|
|
2069 |
temp++; |
|
2070 |
if (igncase == 0) |
|
2071 |
freetemp = match = strncmp (temp, hint, hint_len) == 0; |
|
2072 |
else
|
|
2073 |
freetemp = match = strncasecmp (temp, hint, hint_len) == 0; |
|
2074 |
if (match) |
|
2075 |
temp = savestring (temp); |
|
2076 |
}
|
|
2077 |
else
|
|
2078 |
freetemp = match = 0; |
|
2079 |
}
|
|
2080 |
||
2081 |
/* If we have found a match, and it is an executable file, return it.
|
|
2082 |
We don't return directory names when searching $PATH, since the
|
|
2083 |
bash execution code won't find executables in directories which
|
|
2084 |
appear in directories in $PATH when they're specified using
|
|
2085 |
relative pathnames. */
|
|
2086 |
#if 0
|
|
2087 |
/* If we're not searching $PATH and we have a relative pathname, we
|
|
2088 |
need to re-canonicalize it before testing whether or not it's an
|
|
2089 |
executable or a directory so the shell treats .. relative to $PWD
|
|
2090 |
according to the physical/logical option. The shell already
|
|
2091 |
canonicalizes the directory name in order to tell readline where
|
|
2092 |
to look, so not doing it here will be inconsistent. */
|
|
2093 |
/* XXX -- currently not used -- will introduce more inconsistency,
|
|
2094 |
since shell does not canonicalize ../foo before passing it to
|
|
2095 |
shell_execve(). */
|
|
2096 |
if (match && searching_path == 0 && *val == '.')
|
|
2097 |
{
|
|
2098 |
char *t, *t1;
|
|
2099 |
||
2100 |
t = get_working_directory ("command-word-completion");
|
|
2101 |
t1 = make_absolute (val, t);
|
|
2102 |
free (t);
|
|
2103 |
cval = sh_canonpath (t1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
|
|
2104 |
}
|
|
2105 |
else
|
|
2106 |
#endif
|
|
2107 |
cval = val; |
|
2108 |
||
2109 |
if (match && executable_completion ((searching_path ? val : cval), searching_path)) |
|
2110 |
{
|
|
2111 |
if (cval != val) |
|
2112 |
free (cval); |
|
2113 |
free (val); |
|
2114 |
val = ""; /* So it won't be NULL. */ |
|
2115 |
return (temp); |
|
2116 |
}
|
|
2117 |
else
|
|
2118 |
{
|
|
2119 |
if (freetemp) |
|
2120 |
free (temp); |
|
2121 |
if (cval != val) |
|
2122 |
free (cval); |
|
2123 |
free (val); |
|
2124 |
goto inner; |
|
2125 |
}
|
|
2126 |
}
|
|
2127 |
}
|
|
2128 |
||
2129 |
/* Completion inside an unterminated command substitution. */
|
|
2130 |
static char * |
|
2131 |
command_subst_completion_function (text, state) |
|
2132 |
const char *text; |
|
2133 |
int state; |
|
2134 |
{
|
|
2135 |
static char **matches = (char **)NULL; |
|
2136 |
static const char *orig_start; |
|
2137 |
static char *filename_text = (char *)NULL; |
|
2138 |
static int cmd_index, start_len; |
|
2139 |
char *value; |
|
2140 |
||
2141 |
if (state == 0) |
|
2142 |
{
|
|
2143 |
if (filename_text) |
|
2144 |
free (filename_text); |
|
2145 |
orig_start = text; |
|
2146 |
if (*text == '`') |
|
2147 |
text++; |
|
2148 |
else if (*text == '$' && text[1] == '(') /* ) */ |
|
2149 |
text += 2; |
|
2150 |
/* If the text was quoted, suppress any quote character that the
|
|
2151 |
readline completion code would insert. */
|
|
2152 |
rl_completion_suppress_quote = 1; |
|
2153 |
start_len = text - orig_start; |
|
2154 |
filename_text = savestring (text); |
|
2155 |
if (matches) |
|
2156 |
free (matches); |
|
2157 |
||
2158 |
/*
|
|
2159 |
* At this point we can entertain the idea of re-parsing
|
|
2160 |
* `filename_text' into a (possibly incomplete) command name and
|
|
2161 |
* arguments, and doing completion based on that. This is
|
|
2162 |
* currently very rudimentary, but it is a small improvement.
|
|
2163 |
*/
|
|
2164 |
for (value = filename_text + strlen (filename_text) - 1; value > filename_text; value--) |
|
2165 |
if (whitespace (*value) || member (*value, COMMAND_SEPARATORS)) |
|
2166 |
break; |
|
2167 |
if (value <= filename_text) |
|
2168 |
matches = rl_completion_matches (filename_text, command_word_completion_function); |
|
2169 |
else
|
|
2170 |
{
|
|
2171 |
value++; |
|
2172 |
start_len += value - filename_text; |
|
2173 |
if (whitespace (value[-1])) |
|
2174 |
matches = rl_completion_matches (value, rl_filename_completion_function); |
|
2175 |
else
|
|
2176 |
matches = rl_completion_matches (value, command_word_completion_function); |
|
2177 |
}
|
|
2178 |
||
2179 |
/* If there is more than one match, rl_completion_matches has already
|
|
2180 |
put the lcd in matches[0]. Skip over it. */
|
|
2181 |
cmd_index = matches && matches[0] && matches[1]; |
|
2182 |
||
2183 |
/* If there's a single match and it's a directory, set the append char
|
|
2184 |
to the expected `/'. Otherwise, don't append anything. */
|
|
2185 |
if (matches && matches[0] && matches[1] == 0 && test_for_directory (matches[0])) |
|
2186 |
rl_completion_append_character = '/'; |
|
2187 |
else
|
|
2188 |
rl_completion_suppress_append = 1; |
|
2189 |
}
|
|
2190 |
||
2191 |
if (matches == 0 || matches[cmd_index] == 0) |
|
2192 |
{
|
|
2193 |
rl_filename_quoting_desired = 0; /* disable quoting */ |
|
2194 |
return ((char *)NULL); |
|
2195 |
}
|
|
2196 |
else
|
|
2197 |
{
|
|
2198 |
value = (char *)xmalloc (1 + start_len + strlen (matches[cmd_index])); |
|
2199 |
||
2200 |
if (start_len == 1) |
|
2201 |
value[0] = *orig_start; |
|
2202 |
else
|
|
2203 |
strncpy (value, orig_start, start_len); |
|
2204 |
||
2205 |
strcpy (value + start_len, matches[cmd_index]); |
|
2206 |
||
2207 |
cmd_index++; |
|
2208 |
return (value); |
|
2209 |
}
|
|
2210 |
}
|
|
2211 |
||
2212 |
/* Okay, now we write the entry_function for variable completion. */
|
|
2213 |
static char * |
|
2214 |
variable_completion_function (text, state) |
|
2215 |
const char *text; |
|
2216 |
int state; |
|
2217 |
{
|
|
2218 |
static char **varlist = (char **)NULL; |
|
2219 |
static int varlist_index; |
|
2220 |
static char *varname = (char *)NULL; |
|
2221 |
static int namelen; |
|
2222 |
static int first_char, first_char_loc; |
|
2223 |
||
2224 |
if (!state) |
|
2225 |
{
|
|
2226 |
if (varname) |
|
2227 |
free (varname); |
|
2228 |
||
2229 |
first_char_loc = 0; |
|
2230 |
first_char = text[0]; |
|
2231 |
||
2232 |
if (first_char == '$') |
|
2233 |
first_char_loc++; |
|
2234 |
||
2235 |
if (text[first_char_loc] == '{') |
|
2236 |
first_char_loc++; |
|
2237 |
||
2238 |
varname = savestring (text + first_char_loc); |
|
2239 |
||
2240 |
namelen = strlen (varname); |
|
2241 |
if (varlist) |
|
2242 |
strvec_dispose (varlist); |
|
2243 |
||
2244 |
varlist = all_variables_matching_prefix (varname); |
|
2245 |
varlist_index = 0; |
|
2246 |
}
|
|
2247 |
||
2248 |
if (!varlist || !varlist[varlist_index]) |
|
2249 |
{
|
|
2250 |
return ((char *)NULL); |
|
2251 |
}
|
|
2252 |
else
|
|
2253 |
{
|
|
2254 |
char *value; |
|
2255 |
||
2256 |
value = (char *)xmalloc (4 + strlen (varlist[varlist_index])); |
|
2257 |
||
2258 |
if (first_char_loc) |
|
2259 |
{
|
|
2260 |
value[0] = first_char; |
|
2261 |
if (first_char_loc == 2) |
|
2262 |
value[1] = '{'; |
|
2263 |
}
|
|
2264 |
||
2265 |
strcpy (value + first_char_loc, varlist[varlist_index]); |
|
2266 |
if (first_char_loc == 2) |
|
2267 |
strcat (value, "}"); |
|
2268 |
||
2269 |
varlist_index++; |
|
2270 |
return (value); |
|
2271 |
}
|
|
2272 |
}
|
|
2273 |
||
2274 |
/* How about a completion function for hostnames? */
|
|
2275 |
static char * |
|
2276 |
hostname_completion_function (text, state) |
|
2277 |
const char *text; |
|
2278 |
int state; |
|
2279 |
{
|
|
2280 |
static char **list = (char **)NULL; |
|
2281 |
static int list_index = 0; |
|
2282 |
static int first_char, first_char_loc; |
|
2283 |
||
2284 |
/* If we don't have any state, make some. */
|
|
2285 |
if (state == 0) |
|
2286 |
{
|
|
2287 |
FREE (list); |
|
2288 |
||
2289 |
list = (char **)NULL; |
|
2290 |
||
2291 |
first_char_loc = 0; |
|
2292 |
first_char = *text; |
|
2293 |
||
2294 |
if (first_char == '@') |
|
2295 |
first_char_loc++; |
|
2296 |
||
2297 |
list = hostnames_matching ((char *)text+first_char_loc); |
|
2298 |
list_index = 0; |
|
2299 |
}
|
|
2300 |
||
2301 |
if (list && list[list_index]) |
|
2302 |
{
|
|
2303 |
char *t; |
|
2304 |
||
2305 |
t = (char *)xmalloc (2 + strlen (list[list_index])); |
|
2306 |
*t = first_char; |
|
2307 |
strcpy (t + first_char_loc, list[list_index]); |
|
2308 |
list_index++; |
|
2309 |
return (t); |
|
2310 |
}
|
|
2311 |
||
2312 |
return ((char *)NULL); |
|
2313 |
}
|
|
2314 |
||
2315 |
/*
|
|
2316 |
* A completion function for service names from /etc/services (or wherever).
|
|
2317 |
*/
|
|
2318 |
char * |
|
2319 |
bash_servicename_completion_function (text, state) |
|
2320 |
const char *text; |
|
2321 |
int state; |
|
2322 |
{
|
|
2323 |
#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GETSERVENT)
|
|
2324 |
return ((char *)NULL); |
|
2325 |
#else
|
|
2326 |
static char *sname = (char *)NULL; |
|
2327 |
static struct servent *srvent; |
|
2328 |
static int snamelen, firstc; |
|
2329 |
char *value; |
|
2330 |
char **alist, *aentry; |
|
2331 |
int afound; |
|
2332 |
||
2333 |
if (state == 0) |
|
2334 |
{
|
|
2335 |
FREE (sname); |
|
2336 |
firstc = *text; |
|
2337 |
||
2338 |
sname = savestring (text); |
|
2339 |
snamelen = strlen (sname); |
|
2340 |
setservent (0); |
|
2341 |
}
|
|
2342 |
||
2343 |
while (srvent = getservent ()) |
|
2344 |
{
|
|
2345 |
afound = 0; |
|
2346 |
if (snamelen == 0 || (STREQN (sname, srvent->s_name, snamelen))) |
|
2347 |
break; |
|
2348 |
/* Not primary, check aliases */
|
|
2349 |
for (alist = srvent->s_aliases; *alist; alist++) |
|
2350 |
{
|
|
2351 |
aentry = *alist; |
|
2352 |
if (STREQN (sname, aentry, snamelen)) |
|
2353 |
{
|
|
2354 |
afound = 1; |
|
2355 |
break; |
|
2356 |
}
|
|
2357 |
}
|
|
2358 |
||
2359 |
if (afound) |
|
2360 |
break; |
|
2361 |
}
|
|
2362 |
||
2363 |
if (srvent == 0) |
|
2364 |
{
|
|
2365 |
endservent (); |
|
2366 |
return ((char *)NULL); |
|
2367 |
}
|
|
2368 |
||
2369 |
value = afound ? savestring (aentry) : savestring (srvent->s_name); |
|
2370 |
return value; |
|
2371 |
#endif
|
|
2372 |
}
|
|
2373 |
||
2374 |
/*
|
|
2375 |
* A completion function for group names from /etc/group (or wherever).
|
|
2376 |
*/
|
|
2377 |
char * |
|
2378 |
bash_groupname_completion_function (text, state) |
|
2379 |
const char *text; |
|
2380 |
int state; |
|
2381 |
{
|
|
2382 |
#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GRP_H)
|
|
2383 |
return ((char *)NULL); |
|
2384 |
#else
|
|
2385 |
static char *gname = (char *)NULL; |
|
2386 |
static struct group *grent; |
|
2387 |
static int gnamelen; |
|
2388 |
char *value; |
|
2389 |
||
2390 |
if (state == 0) |
|
2391 |
{
|
|
2392 |
FREE (gname); |
|
2393 |
gname = savestring (text); |
|
2394 |
gnamelen = strlen (gname); |
|
2395 |
||
2396 |
setgrent (); |
|
2397 |
}
|
|
2398 |
||
2399 |
while (grent = getgrent ()) |
|
2400 |
{
|
|
2401 |
if (gnamelen == 0 || (STREQN (gname, grent->gr_name, gnamelen))) |
|
2402 |
break; |
|
2403 |
}
|
|
2404 |
||
2405 |
if (grent == 0) |
|
2406 |
{
|
|
2407 |
endgrent (); |
|
2408 |
return ((char *)NULL); |
|
2409 |
}
|
|
2410 |
||
2411 |
value = savestring (grent->gr_name); |
|
2412 |
return (value); |
|
2413 |
#endif
|
|
2414 |
}
|
|
2415 |
||
2416 |
/* Functions to perform history and alias expansions on the current line. */
|
|
2417 |
||
2418 |
#if defined (BANG_HISTORY)
|
|
2419 |
/* Perform history expansion on the current line. If no history expansion
|
|
2420 |
is done, pre_process_line() returns what it was passed, so we need to
|
|
2421 |
allocate a new line here. */
|
|
2422 |
static char * |
|
2423 |
history_expand_line_internal (line) |
|
2424 |
char *line; |
|
2425 |
{
|
|
2426 |
char *new_line; |
|
2427 |
int old_verify; |
|
2428 |
||
2429 |
old_verify = hist_verify; |
|
2430 |
hist_verify = 0; |
|
2431 |
new_line = pre_process_line (line, 0, 0); |
|
2432 |
hist_verify = old_verify; |
|
2433 |
||
2434 |
return (new_line == line) ? savestring (line) : new_line; |
|
2435 |
}
|
|
2436 |
#endif
|
|
2437 |
||
2438 |
/* There was an error in expansion. Let the preprocessor print
|
|
2439 |
the error here. */
|
|
2440 |
static void |
|
2441 |
cleanup_expansion_error () |
|
2442 |
{
|
|
2443 |
char *to_free; |
|
2444 |
#if defined (BANG_HISTORY)
|
|
2445 |
int old_verify; |
|
2446 |
||
2447 |
old_verify = hist_verify; |
|
2448 |
hist_verify = 0; |
|
2449 |
#endif
|
|
2450 |
||
2451 |
fprintf (rl_outstream, "\r\n"); |
|
2452 |
to_free = pre_process_line (rl_line_buffer, 1, 0); |
|
2453 |
#if defined (BANG_HISTORY)
|
|
2454 |
hist_verify = old_verify; |
|
2455 |
#endif
|
|
2456 |
if (to_free != rl_line_buffer) |
|
2457 |
FREE (to_free); |
|
2458 |
putc ('\r', rl_outstream); |
|
2459 |
rl_forced_update_display (); |
|
2460 |
}
|
|
2461 |
||
2462 |
/* If NEW_LINE differs from what is in the readline line buffer, add an
|
|
2463 |
undo record to get from the readline line buffer contents to the new
|
|
2464 |
line and make NEW_LINE the current readline line. */
|
|
2465 |
static void |
|
2466 |
maybe_make_readline_line (new_line) |
|
2467 |
char *new_line; |
|
2468 |
{
|
|
2469 |
if (strcmp (new_line, rl_line_buffer) != 0) |
|
2470 |
{
|
|
2471 |
rl_point = rl_end; |
|
2472 |
||
2473 |
rl_add_undo (UNDO_BEGIN, 0, 0, 0); |
|
2474 |
rl_delete_text (0, rl_point); |
|
2475 |
rl_point = rl_end = rl_mark = 0; |
|
2476 |
rl_insert_text (new_line); |
|
2477 |
rl_add_undo (UNDO_END, 0, 0, 0); |
|
2478 |
}
|
|
2479 |
}
|
|
2480 |
||
2481 |
/* Make NEW_LINE be the current readline line. This frees NEW_LINE. */
|
|
2482 |
static void |
|
2483 |
set_up_new_line (new_line) |
|
2484 |
char *new_line; |
|
2485 |
{
|
|
2486 |
int old_point, at_end; |
|
2487 |
||
2488 |
old_point = rl_point; |
|
2489 |
at_end = rl_point == rl_end; |
|
2490 |
||
2491 |
/* If the line was history and alias expanded, then make that
|
|
2492 |
be one thing to undo. */
|
|
2493 |
maybe_make_readline_line (new_line); |
|
2494 |
free (new_line); |
|
2495 |
||
2496 |
/* Place rl_point where we think it should go. */
|
|
2497 |
if (at_end) |
|
2498 |
rl_point = rl_end; |
|
2499 |
else if (old_point < rl_end) |
|
2500 |
{
|
|
2501 |
rl_point = old_point; |
|
2502 |
if (!whitespace (rl_line_buffer[rl_point])) |
|
2503 |
rl_forward_word (1, 0); |
|
2504 |
}
|
|
2505 |
}
|
|
2506 |
||
2507 |
#if defined (ALIAS)
|
|
2508 |
/* Expand aliases in the current readline line. */
|
|
2509 |
static int |
|
2510 |
alias_expand_line (count, ignore) |
|
2511 |
int count, ignore; |
|
2512 |
{
|
|
2513 |
char *new_line; |
|
2514 |
||
2515 |
new_line = alias_expand (rl_line_buffer); |
|
2516 |
||
2517 |
if (new_line) |
|
2518 |
{
|
|
2519 |
set_up_new_line (new_line); |
|
2520 |
return (0); |
|
2521 |
}
|
|
2522 |
else
|
|
2523 |
{
|
|
2524 |
cleanup_expansion_error (); |
|
2525 |
return (1); |
|
2526 |
}
|
|
2527 |
}
|
|
2528 |
#endif
|
|
2529 |
||
2530 |
#if defined (BANG_HISTORY)
|
|
2531 |
/* History expand the line. */
|
|
2532 |
static int |
|
2533 |
history_expand_line (count, ignore) |
|
2534 |
int count, ignore; |
|
2535 |
{
|
|
2536 |
char *new_line; |
|
2537 |
||
2538 |
new_line = history_expand_line_internal (rl_line_buffer); |
|
2539 |
||
2540 |
if (new_line) |
|
2541 |
{
|
|
2542 |
set_up_new_line (new_line); |
|
2543 |
return (0); |
|
2544 |
}
|
|
2545 |
else
|
|
2546 |
{
|
|
2547 |
cleanup_expansion_error (); |
|
2548 |
return (1); |
|
2549 |
}
|
|
2550 |
}
|
|
2551 |
||
2552 |
/* Expand history substitutions in the current line and then insert a
|
|
2553 |
space (hopefully close to where we were before). */
|
|
2554 |
static int |
|
2555 |
tcsh_magic_space (count, ignore) |
|
2556 |
int count, ignore; |
|
2557 |
{
|
|
2558 |
int dist_from_end, old_point; |
|
2559 |
||
2560 |
old_point = rl_point; |
|
2561 |
dist_from_end = rl_end - rl_point; |
|
2562 |
if (history_expand_line (count, ignore) == 0) |
|
2563 |
{
|
|
2564 |
/* Try a simple heuristic from Stephen Gildea <gildea@intouchsys.com>.
|
|
2565 |
This works if all expansions were before rl_point or if no expansions
|
|
2566 |
were performed. */
|
|
2567 |
rl_point = (old_point == 0) ? old_point : rl_end - dist_from_end; |
|
2568 |
rl_insert (1, ' '); |
|
2569 |
return (0); |
|
2570 |
}
|
|
2571 |
else
|
|
2572 |
return (1); |
|
2573 |
}
|
|
2574 |
#endif /* BANG_HISTORY */ |
|
2575 |
||
2576 |
/* History and alias expand the line. */
|
|
2577 |
static int |
|
2578 |
history_and_alias_expand_line (count, ignore) |
|
2579 |
int count, ignore; |
|
2580 |
{
|
|
2581 |
char *new_line; |
|
2582 |
||
2583 |
new_line = 0; |
|
2584 |
#if defined (BANG_HISTORY)
|
|
2585 |
new_line = history_expand_line_internal (rl_line_buffer); |
|
2586 |
#endif
|
|
2587 |
||
2588 |
#if defined (ALIAS)
|
|
2589 |
if (new_line) |
|
2590 |
{
|
|
2591 |
char *alias_line; |
|
2592 |
||
2593 |
alias_line = alias_expand (new_line); |
|
2594 |
free (new_line); |
|
2595 |
new_line = alias_line; |
|
2596 |
}
|
|
2597 |
#endif /* ALIAS */ |
|
2598 |
||
2599 |
if (new_line) |
|
2600 |
{
|
|
2601 |
set_up_new_line (new_line); |
|
2602 |
return (0); |
|
2603 |
}
|
|
2604 |
else
|
|
2605 |
{
|
|
2606 |
cleanup_expansion_error (); |
|
2607 |
return (1); |
|
2608 |
}
|
|
2609 |
}
|
|
2610 |
||
2611 |
/* History and alias expand the line, then perform the shell word
|
|
2612 |
expansions by calling expand_string. This can't use set_up_new_line()
|
|
2613 |
because we want the variable expansions as a separate undo'able
|
|
2614 |
set of operations. */
|
|
2615 |
static int |
|
2616 |
shell_expand_line (count, ignore) |
|
2617 |
int count, ignore; |
|
2618 |
{
|
|
2619 |
char *new_line; |
|
2620 |
WORD_LIST *expanded_string; |
|
2621 |
||
2622 |
new_line = 0; |
|
2623 |
#if defined (BANG_HISTORY)
|
|
2624 |
new_line = history_expand_line_internal (rl_line_buffer); |
|
2625 |
#endif
|
|
2626 |
||
2627 |
#if defined (ALIAS)
|
|
2628 |
if (new_line) |
|
2629 |
{
|
|
2630 |
char *alias_line; |
|
2631 |
||
2632 |
alias_line = alias_expand (new_line); |
|
2633 |
free (new_line); |
|
2634 |
new_line = alias_line; |
|
2635 |
}
|
|
2636 |
#endif /* ALIAS */ |
|
2637 |
||
2638 |
if (new_line) |
|
2639 |
{
|
|
2640 |
int old_point = rl_point; |
|
2641 |
int at_end = rl_point == rl_end; |
|
2642 |
||
2643 |
/* If the line was history and alias expanded, then make that
|
|
2644 |
be one thing to undo. */
|
|
2645 |
maybe_make_readline_line (new_line); |
|
2646 |
free (new_line); |
|
2647 |
||
2648 |
/* If there is variable expansion to perform, do that as a separate
|
|
2649 |
operation to be undone. */
|
|
2650 |
new_line = savestring (rl_line_buffer); |
|
2651 |
expanded_string = expand_string (new_line, 0); |
|
2652 |
FREE (new_line); |
|
2653 |
if (expanded_string == 0) |
|
2654 |
{
|
|
2655 |
new_line = (char *)xmalloc (1); |
|
2656 |
new_line[0] = '\0'; |
|
2657 |
}
|
|
2658 |
else
|
|
2659 |
{
|
|
2660 |
new_line = string_list (expanded_string); |
|
2661 |
dispose_words (expanded_string); |
|
2662 |
}
|
|
2663 |
||
2664 |
maybe_make_readline_line (new_line); |
|
2665 |
free (new_line); |
|
2666 |
||
2667 |
/* Place rl_point where we think it should go. */
|
|
2668 |
if (at_end) |
|
2669 |
rl_point = rl_end; |
|
2670 |
else if (old_point < rl_end) |
|
2671 |
{
|
|
2672 |
rl_point = old_point; |
|
2673 |
if (!whitespace (rl_line_buffer[rl_point])) |
|
2674 |
rl_forward_word (1, 0); |
|
2675 |
}
|
|
2676 |
return 0; |
|
2677 |
}
|
|
2678 |
else
|
|
2679 |
{
|
|
2680 |
cleanup_expansion_error (); |
|
2681 |
return 1; |
|
2682 |
}
|
|
2683 |
}
|
|
2684 |
||
2685 |
/* If FIGNORE is set, then don't match files with the given suffixes when
|
|
2686 |
completing filenames. If only one of the possibilities has an acceptable
|
|
2687 |
suffix, delete the others, else just return and let the completer
|
|
2688 |
signal an error. It is called by the completer when real
|
|
2689 |
completions are done on filenames by the completer's internal
|
|
2690 |
function, not for completion lists (M-?) and not on "other"
|
|
2691 |
completion types, such as hostnames or commands. */
|
|
2692 |
||
2693 |
static struct ignorevar fignore = |
|
2694 |
{
|
|
2695 |
"FIGNORE", |
|
2696 |
(struct ign *)0, |
|
2697 |
0, |
|
2698 |
(char *)0, |
|
2699 |
(sh_iv_item_func_t *) 0, |
|
2700 |
};
|
|
2701 |
||
2702 |
static void |
|
2703 |
_ignore_completion_names (names, name_func) |
|
2704 |
char **names; |
|
2705 |
sh_ignore_func_t *name_func; |
|
2706 |
{
|
|
2707 |
char **newnames; |
|
2708 |
int idx, nidx; |
|
2709 |
char **oldnames; |
|
2710 |
int oidx; |
|
2711 |
||
2712 |
/* If there is only one completion, see if it is acceptable. If it is
|
|
2713 |
not, free it up. In any case, short-circuit and return. This is a
|
|
2714 |
special case because names[0] is not the prefix of the list of names
|
|
2715 |
if there is only one completion; it is the completion itself. */
|
|
2716 |
if (names[1] == (char *)0) |
|
2717 |
{
|
|
2718 |
if (force_fignore) |
|
2719 |
if ((*name_func) (names[0]) == 0) |
|
2720 |
{
|
|
2721 |
free (names[0]); |
|
2722 |
names[0] = (char *)NULL; |
|
2723 |
}
|
|
2724 |
||
2725 |
return; |
|
2726 |
}
|
|
2727 |
||
2728 |
/* Allocate space for array to hold list of pointers to matching
|
|
2729 |
filenames. The pointers are copied back to NAMES when done. */
|
|
2730 |
for (nidx = 1; names[nidx]; nidx++) |
|
2731 |
;
|
|
2732 |
newnames = strvec_create (nidx + 1); |
|
2733 |
||
2734 |
if (force_fignore == 0) |
|
2735 |
{
|
|
2736 |
oldnames = strvec_create (nidx - 1); |
|
2737 |
oidx = 0; |
|
2738 |
}
|
|
2739 |
||
2740 |
newnames[0] = names[0]; |
|
2741 |
for (idx = nidx = 1; names[idx]; idx++) |
|
2742 |
{
|
|
2743 |
if ((*name_func) (names[idx])) |
|
2744 |
newnames[nidx++] = names[idx]; |
|
2745 |
else if (force_fignore == 0) |
|
2746 |
oldnames[oidx++] = names[idx]; |
|
2747 |
else
|
|
2748 |
free (names[idx]); |
|
2749 |
}
|
|
2750 |
||
2751 |
newnames[nidx] = (char *)NULL; |
|
2752 |
||
2753 |
/* If none are acceptable then let the completer handle it. */
|
|
2754 |
if (nidx == 1) |
|
2755 |
{
|
|
2756 |
if (force_fignore) |
|
2757 |
{
|
|
2758 |
free (names[0]); |
|
2759 |
names[0] = (char *)NULL; |
|
2760 |
}
|
|
2761 |
else
|
|
2762 |
free (oldnames); |
|
2763 |
||
2764 |
free (newnames); |
|
2765 |
return; |
|
2766 |
}
|
|
2767 |
||
2768 |
if (force_fignore == 0) |
|
2769 |
{
|
|
2770 |
while (oidx) |
|
2771 |
free (oldnames[--oidx]); |
|
2772 |
free (oldnames); |
|
2773 |
}
|
|
2774 |
||
2775 |
/* If only one is acceptable, copy it to names[0] and return. */
|
|
2776 |
if (nidx == 2) |
|
2777 |
{
|
|
2778 |
free (names[0]); |
|
2779 |
names[0] = newnames[1]; |
|
2780 |
names[1] = (char *)NULL; |
|
2781 |
free (newnames); |
|
2782 |
return; |
|
2783 |
}
|
|
2784 |
||
2785 |
/* Copy the acceptable names back to NAMES, set the new array end,
|
|
2786 |
and return. */
|
|
2787 |
for (nidx = 1; newnames[nidx]; nidx++) |
|
2788 |
names[nidx] = newnames[nidx]; |
|
2789 |
names[nidx] = (char *)NULL; |
|
2790 |
free (newnames); |
|
2791 |
}
|
|
2792 |
||
2793 |
static int |
|
2794 |
name_is_acceptable (name) |
|
2795 |
const char *name; |
|
2796 |
{
|
|
2797 |
struct ign *p; |
|
2798 |
int nlen; |
|
2799 |
||
2800 |
for (nlen = strlen (name), p = fignore.ignores; p->val; p++) |
|
2801 |
{
|
|
2802 |
if (nlen > p->len && p->len > 0 && STREQ (p->val, &name[nlen - p->len])) |
|
2803 |
return (0); |
|
2804 |
}
|
|
2805 |
||
2806 |
return (1); |
|
2807 |
}
|
|
2808 |
||
2809 |
#if 0
|
|
2810 |
static int
|
|
2811 |
ignore_dot_names (name)
|
|
2812 |
char *name;
|
|
2813 |
{
|
|
2814 |
return (name[0] != '.');
|
|
2815 |
}
|
|
2816 |
#endif
|
|
2817 |
||
2818 |
static int |
|
2819 |
filename_completion_ignore (names) |
|
2820 |
char **names; |
|
2821 |
{
|
|
2822 |
#if 0
|
|
2823 |
if (glob_dot_filenames == 0)
|
|
2824 |
_ignore_completion_names (names, ignore_dot_names);
|
|
2825 |
#endif
|
|
2826 |
||
2827 |
setup_ignore_patterns (&fignore); |
|
2828 |
||
2829 |
if (fignore.num_ignores == 0) |
|
2830 |
return 0; |
|
2831 |
||
2832 |
_ignore_completion_names (names, name_is_acceptable); |
|
2833 |
||
2834 |
return 0; |
|
2835 |
}
|
|
2836 |
||
2837 |
/* Return 1 if NAME is a directory. NAME undergoes tilde expansion. */
|
|
2838 |
static int |
|
2839 |
test_for_directory (name) |
|
2840 |
const char *name; |
|
2841 |
{
|
|
2842 |
char *fn; |
|
2843 |
int r; |
|
2844 |
||
2845 |
fn = bash_tilde_expand (name, 0); |
|
2846 |
r = file_isdir (fn); |
|
2847 |
free (fn); |
|
2848 |
||
2849 |
return (r); |
|
2850 |
}
|
|
2851 |
||
2852 |
/* Remove files from NAMES, leaving directories. */
|
|
2853 |
static int |
|
2854 |
bash_ignore_filenames (names) |
|
2855 |
char **names; |
|
2856 |
{
|
|
2857 |
_ignore_completion_names (names, test_for_directory); |
|
2858 |
return 0; |
|
2859 |
}
|
|
2860 |
||
2861 |
static int |
|
2862 |
return_zero (name) |
|
2863 |
const char *name; |
|
2864 |
{
|
|
2865 |
return 0; |
|
2866 |
}
|
|
2867 |
||
2868 |
static int |
|
2869 |
bash_ignore_everything (names) |
|
2870 |
char **names; |
|
2871 |
{
|
|
2872 |
_ignore_completion_names (names, return_zero); |
|
2873 |
return 0; |
|
2874 |
}
|
|
2875 |
||
2876 |
/* Replace a tilde-prefix in VAL with a `~', assuming the user typed it. VAL
|
|
2877 |
is an expanded filename. DIRECTORY_PART is the tilde-prefix portion
|
|
2878 |
of the un-tilde-expanded version of VAL (what the user typed). */
|
|
2879 |
static char * |
|
2880 |
restore_tilde (val, directory_part) |
|
2881 |
char *val, *directory_part; |
|
2882 |
{
|
|
2883 |
int l, vl, dl2, xl; |
|
2884 |
char *dh2, *expdir, *ret; |
|
2885 |
||
2886 |
vl = strlen (val); |
|
2887 |
||
2888 |
/* We need to duplicate the expansions readline performs on the directory
|
|
2889 |
portion before passing it to our completion function. */
|
|
2890 |
dh2 = directory_part ? bash_dequote_filename (directory_part, 0) : 0; |
|
2891 |
bash_directory_expansion (&dh2); |
|
2892 |
dl2 = strlen (dh2); |
|
2893 |
||
2894 |
expdir = bash_tilde_expand (directory_part, 0); |
|
2895 |
xl = strlen (expdir); |
|
2896 |
free (expdir); |
|
2897 |
||
2898 |
/*
|
|
2899 |
dh2 = unexpanded but dequoted tilde-prefix
|
|
2900 |
dl2 = length of tilde-prefix
|
|
2901 |
expdir = tilde-expanded tilde-prefix
|
|
2902 |
xl = length of expanded tilde-prefix
|
|
2903 |
l = length of remainder after tilde-prefix
|
|
2904 |
*/
|
|
2905 |
l = (vl - xl) + 1; |
|
2906 |
||
2907 |
ret = (char *)xmalloc (dl2 + 2 + l); |
|
2908 |
strcpy (ret, dh2); |
|
2909 |
strcpy (ret + dl2, val + xl); |
|
2910 |
||
2911 |
free (dh2); |
|
2912 |
return (ret); |
|
2913 |
}
|
|
2914 |
||
2915 |
static char * |
|
2916 |
maybe_restore_tilde (val, directory_part) |
|
2917 |
char *val, *directory_part; |
|
2918 |
{
|
|
2919 |
rl_icppfunc_t *save; |
|
2920 |
char *ret; |
|
2921 |
||
2922 |
save = (dircomplete_expand == 0) ? save_directory_hook () : (rl_icppfunc_t *)0; |
|
2923 |
ret = restore_tilde (val, directory_part); |
|
2924 |
if (save) |
|
2925 |
restore_directory_hook (save); |
|
2926 |
return ret; |
|
2927 |
}
|
|
2928 |
||
2929 |
/* Simulate the expansions that will be performed by
|
|
2930 |
rl_filename_completion_function. This must be called with the address of
|
|
2931 |
a pointer to malloc'd memory. */
|
|
2932 |
static void |
|
2933 |
bash_directory_expansion (dirname) |
|
2934 |
char **dirname; |
|
2935 |
{
|
|
2936 |
char *d, *nd; |
|
2937 |
||
2938 |
d = savestring (*dirname); |
|
2939 |
||
2940 |
if ((rl_directory_rewrite_hook) && (*rl_directory_rewrite_hook) (&d)) |
|
2941 |
{
|
|
2942 |
free (*dirname); |
|
2943 |
*dirname = d; |
|
2944 |
}
|
|
2945 |
else if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&d)) |
|
2946 |
{
|
|
2947 |
free (*dirname); |
|
2948 |
*dirname = d; |
|
2949 |
}
|
|
2950 |
else if (rl_completion_found_quote) |
|
2951 |
{
|
|
2952 |
nd = bash_dequote_filename (d, rl_completion_quote_character); |
|
2953 |
free (*dirname); |
|
2954 |
free (d); |
|
2955 |
*dirname = nd; |
|
2956 |
}
|
|
2957 |
}
|
|
2958 |
||
2959 |
/* If necessary, rewrite directory entry */
|
|
2960 |
static char * |
|
2961 |
bash_filename_rewrite_hook (fname, fnlen) |
|
2962 |
char *fname; |
|
2963 |
int fnlen; |
|
2964 |
{
|
|
2965 |
char *conv; |
|
2966 |
||
2967 |
conv = fnx_fromfs (fname, fnlen); |
|
2968 |
if (conv != fname) |
|
2969 |
conv = savestring (conv); |
|
2970 |
return conv; |
|
2971 |
}
|
|
2972 |
||
2973 |
/* Functions to save and restore the appropriate directory hook */
|
|
2974 |
/* This is not static so the shopt code can call it */
|
|
2975 |
void
|
|
2976 |
set_directory_hook () |
|
2977 |
{
|
|
2978 |
if (dircomplete_expand) |
|
2979 |
{
|
|
2980 |
rl_directory_completion_hook = bash_directory_completion_hook; |
|
2981 |
rl_directory_rewrite_hook = (rl_icppfunc_t *)0; |
|
2982 |
}
|
|
2983 |
else
|
|
2984 |
{
|
|
2985 |
rl_directory_rewrite_hook = bash_directory_completion_hook; |
|
2986 |
rl_directory_completion_hook = (rl_icppfunc_t *)0; |
|
2987 |
}
|
|
2988 |
}
|
|
2989 |
||
2990 |
static rl_icppfunc_t * |
|
2991 |
save_directory_hook () |
|
2992 |
{
|
|
2993 |
rl_icppfunc_t *ret; |
|
2994 |
||
2995 |
if (dircomplete_expand) |
|
2996 |
{
|
|
2997 |
ret = rl_directory_completion_hook; |
|
2998 |
rl_directory_completion_hook = (rl_icppfunc_t *)NULL; |
|
2999 |
}
|
|
3000 |
else
|
|
3001 |
{
|
|
3002 |
ret = rl_directory_rewrite_hook; |
|
3003 |
rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL; |
|
3004 |
}
|
|
3005 |
||
3006 |
return ret; |
|
3007 |
}
|
|
3008 |
||
3009 |
static void |
|
3010 |
restore_directory_hook (hookf) |
|
3011 |
rl_icppfunc_t *hookf; |
|
3012 |
{
|
|
3013 |
if (dircomplete_expand) |
|
3014 |
rl_directory_completion_hook = hookf; |
|
3015 |
else
|
|
3016 |
rl_directory_rewrite_hook = hookf; |
|
3017 |
}
|
|
3018 |
||
3019 |
/* Expand a filename before the readline completion code passes it to stat(2).
|
|
3020 |
The filename will already have had tilde expansion performed. */
|
|
3021 |
static int |
|
3022 |
bash_filename_stat_hook (dirname) |
|
3023 |
char **dirname; |
|
3024 |
{
|
|
3025 |
char *local_dirname, *new_dirname, *t; |
|
3026 |
int should_expand_dirname, return_value; |
|
3027 |
WORD_LIST *wl; |
|
3028 |
struct stat sb; |
|
3029 |
||
3030 |
local_dirname = *dirname; |
|
3031 |
should_expand_dirname = return_value = 0; |
|
3032 |
if (t = mbschr (local_dirname, '$')) |
|
3033 |
should_expand_dirname = '$'; |
|
3034 |
else if (t = mbschr (local_dirname, '`')) /* XXX */ |
|
3035 |
should_expand_dirname = '`'; |
|
3036 |
||
3037 |
#if defined (HAVE_LSTAT)
|
|
3038 |
if (should_expand_dirname && lstat (local_dirname, &sb) == 0) |
|
3039 |
#else
|
|
3040 |
if (should_expand_dirname && stat (local_dirname, &sb) == 0) |
|
3041 |
#endif
|
|
3042 |
should_expand_dirname = 0; |
|
3043 |
||
3044 |
if (should_expand_dirname) |
|
3045 |
{
|
|
3046 |
new_dirname = savestring (local_dirname); |
|
3047 |
wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB); /* does the right thing */ |
|
3048 |
if (wl) |
|
3049 |
{
|
|
3050 |
free (new_dirname); |
|
3051 |
new_dirname = string_list (wl); |
|
3052 |
/* Tell the completer we actually expanded something and change
|
|
3053 |
*dirname only if we expanded to something non-null -- stat
|
|
3054 |
behaves unpredictably when passed null or empty strings */
|
|
3055 |
if (new_dirname && *new_dirname) |
|
3056 |
{
|
|
3057 |
free (local_dirname); /* XXX */ |
|
3058 |
local_dirname = *dirname = new_dirname; |
|
3059 |
return_value = STREQ (local_dirname, *dirname) == 0; |
|
3060 |
}
|
|
3061 |
else
|
|
3062 |
free (new_dirname); |
|
3063 |
dispose_words (wl); |
|
3064 |
}
|
|
3065 |
else
|
|
3066 |
free (new_dirname); |
|
3067 |
}
|
|
3068 |
||
3069 |
/* This is very similar to the code in bash_directory_completion_hook below,
|
|
3070 |
but without spelling correction and not worrying about whether or not
|
|
3071 |
we change relative pathnames. */
|
|
3072 |
if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1])) |
|
3073 |
{
|
|
3074 |
char *temp1, *temp2; |
|
3075 |
||
3076 |
t = get_working_directory ("symlink-hook"); |
|
3077 |
temp1 = make_absolute (local_dirname, t); |
|
3078 |
free (t); |
|
3079 |
temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS); |
|
3080 |
||
3081 |
/* If we can't canonicalize, bail. */
|
|
3082 |
if (temp2 == 0) |
|
3083 |
{
|
|
3084 |
free (temp1); |
|
3085 |
return return_value; |
|
3086 |
}
|
|
3087 |
||
3088 |
free (local_dirname); |
|
3089 |
*dirname = temp2; |
|
3090 |
free (temp1); |
|
3091 |
}
|
|
3092 |
||
3093 |
return (return_value); |
|
3094 |
}
|
|
3095 |
||
3096 |
/* Handle symbolic link references and other directory name
|
|
3097 |
expansions while hacking completion. This should return 1 if it modifies
|
|
3098 |
the DIRNAME argument, 0 otherwise. It should make sure not to modify
|
|
3099 |
DIRNAME if it returns 0. */
|
|
3100 |
static int |
|
3101 |
bash_directory_completion_hook (dirname) |
|
3102 |
char **dirname; |
|
3103 |
{
|
|
3104 |
char *local_dirname, *new_dirname, *t; |
|
3105 |
int return_value, should_expand_dirname, nextch, closer; |
|
3106 |
WORD_LIST *wl; |
|
3107 |
struct stat sb; |
|
3108 |
||
3109 |
return_value = should_expand_dirname = nextch = closer = 0; |
|
3110 |
local_dirname = *dirname; |
|
3111 |
||
3112 |
if (t = mbschr (local_dirname, '$')) |
|
3113 |
{
|
|
3114 |
should_expand_dirname = '$'; |
|
3115 |
nextch = t[1]; |
|
3116 |
/* Deliberately does not handle the deprecated $[...] arithmetic
|
|
3117 |
expansion syntax */
|
|
3118 |
if (nextch == '(') |
|
3119 |
closer = ')'; |
|
3120 |
else if (nextch == '{') |
|
3121 |
closer = '}'; |
|
3122 |
else
|
|
3123 |
nextch = 0; |
|
3124 |
}
|
|
3125 |
else if (local_dirname[0] == '~') |
|
3126 |
should_expand_dirname = '~'; |
|
3127 |
else
|
|
3128 |
{
|
|
3129 |
t = mbschr (local_dirname, '`'); |
|
3130 |
if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0) |
|
3131 |
should_expand_dirname = '`'; |
|
3132 |
}
|
|
3133 |
||
3134 |
#if defined (HAVE_LSTAT)
|
|
3135 |
if (should_expand_dirname && lstat (local_dirname, &sb) == 0) |
|
3136 |
#else
|
|
3137 |
if (should_expand_dirname && stat (local_dirname, &sb) == 0) |
|
3138 |
#endif
|
|
3139 |
should_expand_dirname = 0; |
|
3140 |
||
3141 |
if (should_expand_dirname) |
|
3142 |
{
|
|
3143 |
new_dirname = savestring (local_dirname); |
|
3144 |
wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB); /* does the right thing */ |
|
3145 |
if (wl) |
|
3146 |
{
|
|
3147 |
*dirname = string_list (wl); |
|
3148 |
/* Tell the completer to replace the directory name only if we
|
|
3149 |
actually expanded something. */
|
|
3150 |
return_value = STREQ (local_dirname, *dirname) == 0; |
|
3151 |
free (local_dirname); |
|
3152 |
free (new_dirname); |
|
3153 |
dispose_words (wl); |
|
3154 |
local_dirname = *dirname; |
|
3155 |
/* XXX - change rl_filename_quote_characters here based on
|
|
3156 |
should_expand_dirname/nextch/closer. This is the only place
|
|
3157 |
custom_filename_quote_characters is modified. */
|
|
3158 |
if (rl_filename_quote_characters && *rl_filename_quote_characters) |
|
3159 |
{
|
|
3160 |
int i, j, c; |
|
3161 |
i = strlen (default_filename_quote_characters); |
|
3162 |
custom_filename_quote_characters = xrealloc (custom_filename_quote_characters, i+1); |
|
3163 |
for (i = j = 0; c = default_filename_quote_characters[i]; i++) |
|
3164 |
{
|
|
3165 |
if (c == should_expand_dirname || c == nextch || c == closer) |
|
3166 |
continue; |
|
3167 |
custom_filename_quote_characters[j++] = c; |
|
3168 |
}
|
|
3169 |
custom_filename_quote_characters[j] = '\0'; |
|
3170 |
rl_filename_quote_characters = custom_filename_quote_characters; |
|
3171 |
set_filename_bstab (rl_filename_quote_characters); |
|
3172 |
}
|
|
3173 |
}
|
|
3174 |
else
|
|
3175 |
{
|
|
3176 |
free (new_dirname); |
|
3177 |
free (local_dirname); |
|
3178 |
*dirname = (char *)xmalloc (1); |
|
3179 |
**dirname = '\0'; |
|
3180 |
return 1; |
|
3181 |
}
|
|
3182 |
}
|
|
3183 |
else
|
|
3184 |
{
|
|
3185 |
/* Dequote the filename even if we don't expand it. */
|
|
3186 |
new_dirname = bash_dequote_filename (local_dirname, rl_completion_quote_character); |
|
3187 |
return_value = STREQ (local_dirname, new_dirname) == 0; |
|
3188 |
free (local_dirname); |
|
3189 |
local_dirname = *dirname = new_dirname; |
|
3190 |
}
|
|
3191 |
||
3192 |
/* no_symbolic_links == 0 -> use (default) logical view of the file system.
|
|
3193 |
local_dirname[0] == '.' && local_dirname[1] == '/' means files in the
|
|
3194 |
current directory (./).
|
|
3195 |
local_dirname[0] == '.' && local_dirname[1] == 0 means relative pathnames
|
|
3196 |
in the current directory (e.g., lib/sh).
|
|
3197 |
XXX - should we do spelling correction on these? */
|
|
3198 |
||
3199 |
/* This is test as it was in bash-4.2: skip relative pathnames in current
|
|
3200 |
directory. Change test to
|
|
3201 |
(local_dirname[0] != '.' || (local_dirname[1] && local_dirname[1] != '/'))
|
|
3202 |
if we want to skip paths beginning with ./ also. */
|
|
3203 |
if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1])) |
|
3204 |
{
|
|
3205 |
char *temp1, *temp2; |
|
3206 |
int len1, len2; |
|
3207 |
||
3208 |
/* If we have a relative path
|
|
3209 |
(local_dirname[0] != '/' && local_dirname[0] != '.')
|
|
3210 |
that is canonical after appending it to the current directory, then
|
|
3211 |
temp1 = temp2+'/'
|
|
3212 |
That is,
|
|
3213 |
strcmp (temp1, temp2) == 0
|
|
3214 |
after adding a slash to temp2 below. It should be safe to not
|
|
3215 |
change those.
|
|
3216 |
*/
|
|
3217 |
t = get_working_directory ("symlink-hook"); |
|
3218 |
temp1 = make_absolute (local_dirname, t); |
|
3219 |
free (t); |
|
3220 |
temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS); |
|
3221 |
||
3222 |
/* Try spelling correction if initial canonicalization fails. Make
|
|
3223 |
sure we are set to replace the directory name with the results so
|
|
3224 |
subsequent directory checks don't fail. */
|
|
3225 |
if (temp2 == 0 && dircomplete_spelling && dircomplete_expand) |
|
3226 |
{
|
|
3227 |
temp2 = dirspell (temp1); |
|
3228 |
if (temp2) |
|
3229 |
{
|
|
3230 |
free (temp1); |
|
3231 |
temp1 = temp2; |
|
3232 |
temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS); |
|
3233 |
return_value |= temp2 != 0; |
|
3234 |
}
|
|
3235 |
}
|
|
3236 |
/* If we can't canonicalize, bail. */
|
|
3237 |
if (temp2 == 0) |
|
3238 |
{
|
|
3239 |
free (temp1); |
|
3240 |
return return_value; |
|
3241 |
}
|
|
3242 |
len1 = strlen (temp1); |
|
3243 |
if (temp1[len1 - 1] == '/') |
|
3244 |
{
|
|
3245 |
len2 = strlen (temp2); |
|
3246 |
if (len2 > 2) /* don't append `/' to `/' or `//' */ |
|
3247 |
{
|
|
3248 |
temp2 = (char *)xrealloc (temp2, len2 + 2); |
|
3249 |
temp2[len2] = '/'; |
|
3250 |
temp2[len2 + 1] = '\0'; |
|
3251 |
}
|
|
3252 |
}
|
|
3253 |
||
3254 |
/* dircomplete_expand_relpath == 0 means we want to leave relative
|
|
3255 |
pathnames that are unchanged by canonicalization alone.
|
|
3256 |
*local_dirname != '/' && *local_dirname != '.' == relative pathname
|
|
3257 |
(consistent with general.c:absolute_pathname())
|
|
3258 |
temp1 == temp2 (after appending a slash to temp2) means the pathname
|
|
3259 |
is not changed by canonicalization as described above. */
|
|
3260 |
if (dircomplete_expand_relpath || ((local_dirname[0] != '/' && local_dirname[0] != '.') && STREQ (temp1, temp2) == 0)) |
|
3261 |
return_value |= STREQ (local_dirname, temp2) == 0; |
|
3262 |
free (local_dirname); |
|
3263 |
*dirname = temp2; |
|
3264 |
free (temp1); |
|
3265 |
}
|
|
3266 |
||
3267 |
return (return_value); |
|
3268 |
}
|
|
3269 |
||
3270 |
static char **history_completion_array = (char **)NULL; |
|
3271 |
static int harry_size; |
|
3272 |
static int harry_len; |
|
3273 |
||
3274 |
static void |
|
3275 |
build_history_completion_array () |
|
3276 |
{
|
|
3277 |
register int i, j; |
|
3278 |
HIST_ENTRY **hlist; |
|
3279 |
char **tokens; |
|
3280 |
||
3281 |
/* First, clear out the current dynamic history completion list. */
|
|
3282 |
if (harry_size) |
|
3283 |
{
|
|
3284 |
strvec_dispose (history_completion_array); |
|
3285 |
history_completion_array = (char **)NULL; |
|
3286 |
harry_size = 0; |
|
3287 |
harry_len = 0; |
|
3288 |
}
|
|
3289 |
||
3290 |
/* Next, grovel each line of history, making each shell-sized token
|
|
3291 |
a separate entry in the history_completion_array. */
|
|
3292 |
hlist = history_list (); |
|
3293 |
||
3294 |
if (hlist) |
|
3295 |
{
|
|
3296 |
for (i = 0; hlist[i]; i++) |
|
3297 |
;
|
|
3298 |
for ( --i; i >= 0; i--) |
|
3299 |
{
|
|
3300 |
/* Separate each token, and place into an array. */
|
|
3301 |
tokens = history_tokenize (hlist[i]->line); |
|
3302 |
||
3303 |
for (j = 0; tokens && tokens[j]; j++) |
|
3304 |
{
|
|
3305 |
if (harry_len + 2 > harry_size) |
|
3306 |
history_completion_array = strvec_resize (history_completion_array, harry_size += 10); |
|
3307 |
||
3308 |
history_completion_array[harry_len++] = tokens[j]; |
|
3309 |
history_completion_array[harry_len] = (char *)NULL; |
|
3310 |
}
|
|
3311 |
free (tokens); |
|
3312 |
}
|
|
3313 |
||
3314 |
/* Sort the complete list of tokens. */
|
|
3315 |
if (dabbrev_expand_active == 0) |
|
3316 |
qsort (history_completion_array, harry_len, sizeof (char *), (QSFUNC *)strvec_strcmp); |
|
3317 |
}
|
|
3318 |
}
|
|
3319 |
||
3320 |
static char * |
|
3321 |
history_completion_generator (hint_text, state) |
|
3322 |
const char *hint_text; |
|
3323 |
int state; |
|
3324 |
{
|
|
3325 |
static int local_index, len; |
|
3326 |
static const char *text; |
|
3327 |
||
3328 |
/* If this is the first call to the generator, then initialize the
|
|
3329 |
list of strings to complete over. */
|
|
3330 |
if (state == 0) |
|
3331 |
{
|
|
3332 |
if (dabbrev_expand_active) /* This is kind of messy */ |
|
3333 |
rl_completion_suppress_append = 1; |
|
3334 |
local_index = 0; |
|
3335 |
build_history_completion_array (); |
|
3336 |
text = hint_text; |
|
3337 |
len = strlen (text); |
|
3338 |
}
|
|
3339 |
||
3340 |
while (history_completion_array && history_completion_array[local_index]) |
|
3341 |
{
|
|
3342 |
if (strncmp (text, history_completion_array[local_index++], len) == 0) |
|
3343 |
return (savestring (history_completion_array[local_index - 1])); |
|
3344 |
}
|
|
3345 |
return ((char *)NULL); |
|
3346 |
}
|
|
3347 |
||
3348 |
static int |
|
3349 |
dynamic_complete_history (count, key) |
|
3350 |
int count, key; |
|
3351 |
{
|
|
3352 |
int r; |
|
3353 |
rl_compentry_func_t *orig_func; |
|
3354 |
rl_completion_func_t *orig_attempt_func; |
|
3355 |
rl_compignore_func_t *orig_ignore_func; |
|
3356 |
||
3357 |
orig_func = rl_completion_entry_function; |
|
3358 |
orig_attempt_func = rl_attempted_completion_function; |
|
3359 |
orig_ignore_func = rl_ignore_some_completions_function; |
|
3360 |
||
3361 |
rl_completion_entry_function = history_completion_generator; |
|
3362 |
rl_attempted_completion_function = (rl_completion_func_t *)NULL; |
|
3363 |
rl_ignore_some_completions_function = filename_completion_ignore; |
|
3364 |
||
3365 |
/* XXX - use rl_completion_mode here? */
|
|
3366 |
if (rl_last_func == dynamic_complete_history) |
|
3367 |
r = rl_complete_internal ('?'); |
|
3368 |
else
|
|
3369 |
r = rl_complete_internal (TAB); |
|
3370 |
||
3371 |
rl_completion_entry_function = orig_func; |
|
3372 |
rl_attempted_completion_function = orig_attempt_func; |
|
3373 |
rl_ignore_some_completions_function = orig_ignore_func; |
|
3374 |
||
3375 |
return r; |
|
3376 |
}
|
|
3377 |
||
3378 |
static int |
|
3379 |
bash_dabbrev_expand (count, key) |
|
3380 |
int count, key; |
|
3381 |
{
|
|
3382 |
int r, orig_suppress, orig_sort; |
|
3383 |
rl_compentry_func_t *orig_func; |
|
3384 |
rl_completion_func_t *orig_attempt_func; |
|
3385 |
rl_compignore_func_t *orig_ignore_func; |
|
3386 |
||
3387 |
orig_func = rl_menu_completion_entry_function; |
|
3388 |
orig_attempt_func = rl_attempted_completion_function; |
|
3389 |
orig_ignore_func = rl_ignore_some_completions_function; |
|
3390 |
orig_suppress = rl_completion_suppress_append; |
|
3391 |
orig_sort = rl_sort_completion_matches; |
|
3392 |
||
3393 |
rl_menu_completion_entry_function = history_completion_generator; |
|
3394 |
rl_attempted_completion_function = (rl_completion_func_t *)NULL; |
|
3395 |
rl_ignore_some_completions_function = filename_completion_ignore; |
|
3396 |
rl_filename_completion_desired = 0; |
|
3397 |
rl_completion_suppress_append = 1; |
|
3398 |
rl_sort_completion_matches = 0; |
|
3399 |
||
3400 |
/* XXX - use rl_completion_mode here? */
|
|
3401 |
dabbrev_expand_active = 1; |
|
3402 |
if (rl_last_func == bash_dabbrev_expand) |
|
3403 |
rl_last_func = rl_menu_complete; |
|
3404 |
r = rl_menu_complete (count, key); |
|
3405 |
dabbrev_expand_active = 0; |
|
3406 |
||
3407 |
rl_last_func = bash_dabbrev_expand; |
|
3408 |
rl_menu_completion_entry_function = orig_func; |
|
3409 |
rl_attempted_completion_function = orig_attempt_func; |
|
3410 |
rl_ignore_some_completions_function = orig_ignore_func; |
|
3411 |
rl_completion_suppress_append = orig_suppress; |
|
3412 |
rl_sort_completion_matches = orig_sort; |
|
3413 |
||
3414 |
return r; |
|
3415 |
}
|
|
3416 |
||
3417 |
#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
|
|
3418 |
static int |
|
3419 |
bash_complete_username (ignore, ignore2) |
|
3420 |
int ignore, ignore2; |
|
3421 |
{
|
|
3422 |
return bash_complete_username_internal (rl_completion_mode (bash_complete_username)); |
|
3423 |
}
|
|
3424 |
||
3425 |
static int |
|
3426 |
bash_possible_username_completions (ignore, ignore2) |
|
3427 |
int ignore, ignore2; |
|
3428 |
{
|
|
3429 |
return bash_complete_username_internal ('?'); |
|
3430 |
}
|
|
3431 |
||
3432 |
static int |
|
3433 |
bash_complete_username_internal (what_to_do) |
|
3434 |
int what_to_do; |
|
3435 |
{
|
|
3436 |
return bash_specific_completion (what_to_do, rl_username_completion_function); |
|
3437 |
}
|
|
3438 |
||
3439 |
static int |
|
3440 |
bash_complete_filename (ignore, ignore2) |
|
3441 |
int ignore, ignore2; |
|
3442 |
{
|
|
3443 |
return bash_complete_filename_internal (rl_completion_mode (bash_complete_filename)); |
|
3444 |
}
|
|
3445 |
||
3446 |
static int |
|
3447 |
bash_possible_filename_completions (ignore, ignore2) |
|
3448 |
int ignore, ignore2; |
|
3449 |
{
|
|
3450 |
return bash_complete_filename_internal ('?'); |
|
3451 |
}
|
|
3452 |
||
3453 |
static int |
|
3454 |
bash_complete_filename_internal (what_to_do) |
|
3455 |
int what_to_do; |
|
3456 |
{
|
|
3457 |
rl_compentry_func_t *orig_func; |
|
3458 |
rl_completion_func_t *orig_attempt_func; |
|
3459 |
rl_icppfunc_t *orig_dir_func; |
|
3460 |
rl_compignore_func_t *orig_ignore_func; |
|
3461 |
/*const*/ char *orig_rl_completer_word_break_characters; |
|
3462 |
int r; |
|
3463 |
||
3464 |
orig_func = rl_completion_entry_function; |
|
3465 |
orig_attempt_func = rl_attempted_completion_function; |
|
3466 |
orig_ignore_func = rl_ignore_some_completions_function; |
|
3467 |
orig_rl_completer_word_break_characters = rl_completer_word_break_characters; |
|
3468 |
||
3469 |
orig_dir_func = save_directory_hook (); |
|
3470 |
||
3471 |
rl_completion_entry_function = rl_filename_completion_function; |
|
3472 |
rl_attempted_completion_function = (rl_completion_func_t *)NULL; |
|
3473 |
rl_ignore_some_completions_function = filename_completion_ignore; |
|
3474 |
rl_completer_word_break_characters = " \t\n\"\'"; |
|
3475 |
||
3476 |
r = rl_complete_internal (what_to_do); |
|
3477 |
||
3478 |
rl_completion_entry_function = orig_func; |
|
3479 |
rl_attempted_completion_function = orig_attempt_func; |
|
3480 |
rl_ignore_some_completions_function = orig_ignore_func; |
|
3481 |
rl_completer_word_break_characters = orig_rl_completer_word_break_characters; |
|
3482 |
||
3483 |
restore_directory_hook (orig_dir_func); |
|
3484 |
||
3485 |
return r; |
|
3486 |
}
|
|
3487 |
||
3488 |
static int |
|
3489 |
bash_complete_hostname (ignore, ignore2) |
|
3490 |
int ignore, ignore2; |
|
3491 |
{
|
|
3492 |
return bash_complete_hostname_internal (rl_completion_mode (bash_complete_hostname)); |
|
3493 |
}
|
|
3494 |
||
3495 |
static int |
|
3496 |
bash_possible_hostname_completions (ignore, ignore2) |
|
3497 |
int ignore, ignore2; |
|
3498 |
{
|
|
3499 |
return bash_complete_hostname_internal ('?'); |
|
3500 |
}
|
|
3501 |
||
3502 |
static int |
|
3503 |
bash_complete_variable (ignore, ignore2) |
|
3504 |
int ignore, ignore2; |
|
3505 |
{
|
|
3506 |
return bash_complete_variable_internal (rl_completion_mode (bash_complete_variable)); |
|
3507 |
}
|
|
3508 |
||
3509 |
static int |
|
3510 |
bash_possible_variable_completions (ignore, ignore2) |
|
3511 |
int ignore, ignore2; |
|
3512 |
{
|
|
3513 |
return bash_complete_variable_internal ('?'); |
|
3514 |
}
|
|
3515 |
||
3516 |
static int |
|
3517 |
bash_complete_command (ignore, ignore2) |
|
3518 |
int ignore, ignore2; |
|
3519 |
{
|
|
3520 |
return bash_complete_command_internal (rl_completion_mode (bash_complete_command)); |
|
3521 |
}
|
|
3522 |
||
3523 |
static int |
|
3524 |
bash_possible_command_completions (ignore, ignore2) |
|
3525 |
int ignore, ignore2; |
|
3526 |
{
|
|
3527 |
return bash_complete_command_internal ('?'); |
|
3528 |
}
|
|
3529 |
||
3530 |
static int |
|
3531 |
bash_complete_hostname_internal (what_to_do) |
|
3532 |
int what_to_do; |
|
3533 |
{
|
|
3534 |
return bash_specific_completion (what_to_do, hostname_completion_function); |
|
3535 |
}
|
|
3536 |
||
3537 |
static int |
|
3538 |
bash_complete_variable_internal (what_to_do) |
|
3539 |
int what_to_do; |
|
3540 |
{
|
|
3541 |
return bash_specific_completion (what_to_do, variable_completion_function); |
|
3542 |
}
|
|
3543 |
||
3544 |
static int |
|
3545 |
bash_complete_command_internal (what_to_do) |
|
3546 |
int what_to_do; |
|
3547 |
{
|
|
3548 |
return bash_specific_completion (what_to_do, command_word_completion_function); |
|
3549 |
}
|
|
3550 |
||
3551 |
static char *globtext; |
|
3552 |
static char *globorig; |
|
3553 |
||
3554 |
static char * |
|
3555 |
glob_complete_word (text, state) |
|
3556 |
const char *text; |
|
3557 |
int state; |
|
3558 |
{
|
|
3559 |
static char **matches = (char **)NULL; |
|
3560 |
static int ind; |
|
3561 |
int glen; |
|
3562 |
char *ret, *ttext; |
|
3563 |
||
3564 |
if (state == 0) |
|
3565 |
{
|
|
3566 |
rl_filename_completion_desired = 1; |
|
3567 |
FREE (matches); |
|
3568 |
if (globorig != globtext) |
|
3569 |
FREE (globorig); |
|
3570 |
FREE (globtext); |
|
3571 |
||
3572 |
ttext = bash_tilde_expand (text, 0); |
|
3573 |
||
3574 |
if (rl_explicit_arg) |
|
3575 |
{
|
|
3576 |
globorig = savestring (ttext); |
|
3577 |
glen = strlen (ttext); |
|
3578 |
globtext = (char *)xmalloc (glen + 2); |
|
3579 |
strcpy (globtext, ttext); |
|
3580 |
globtext[glen] = '*'; |
|
3581 |
globtext[glen+1] = '\0'; |
|
3582 |
}
|
|
3583 |
else
|
|
3584 |
globtext = globorig = savestring (ttext); |
|
3585 |
||
3586 |
if (ttext != text) |
|
3587 |
free (ttext); |
|
3588 |
||
3589 |
matches = shell_glob_filename (globtext); |
|
3590 |
if (GLOB_FAILED (matches)) |
|
3591 |
matches = (char **)NULL; |
|
3592 |
ind = 0; |
|
3593 |
}
|
|
3594 |
||
3595 |
ret = matches ? matches[ind] : (char *)NULL; |
|
3596 |
ind++; |
|
3597 |
return ret; |
|
3598 |
}
|
|
3599 |
||
3600 |
static int |
|
3601 |
bash_glob_completion_internal (what_to_do) |
|
3602 |
int what_to_do; |
|
3603 |
{
|
|
3604 |
return bash_specific_completion (what_to_do, glob_complete_word); |
|
3605 |
}
|
|
3606 |
||
3607 |
/* A special quoting function so we don't end up quoting globbing characters
|
|
3608 |
in the word if there are no matches or multiple matches. */
|
|
3609 |
static char * |
|
3610 |
bash_glob_quote_filename (s, rtype, qcp) |
|
3611 |
char *s; |
|
3612 |
int rtype; |
|
3613 |
char *qcp; |
|
3614 |
{
|
|
3615 |
if (globorig && qcp && *qcp == '\0' && STREQ (s, globorig)) |
|
3616 |
return (savestring (s)); |
|
3617 |
else
|
|
3618 |
return (bash_quote_filename (s, rtype, qcp)); |
|
3619 |
}
|
|
3620 |
||
3621 |
static int |
|
3622 |
bash_glob_complete_word (count, key) |
|
3623 |
int count, key; |
|
3624 |
{
|
|
3625 |
int r; |
|
3626 |
rl_quote_func_t *orig_quoting_function; |
|
3627 |
||
3628 |
if (rl_editing_mode == EMACS_EDITING_MODE) |
|
3629 |
rl_explicit_arg = 1; /* force `*' append */ |
|
3630 |
orig_quoting_function = rl_filename_quoting_function; |
|
3631 |
rl_filename_quoting_function = bash_glob_quote_filename; |
|
3632 |
||
3633 |
r = bash_glob_completion_internal (rl_completion_mode (bash_glob_complete_word)); |
|
3634 |
||
3635 |
rl_filename_quoting_function = orig_quoting_function; |
|
3636 |
return r; |
|
3637 |
}
|
|
3638 |
||
3639 |
static int |
|
3640 |
bash_glob_expand_word (count, key) |
|
3641 |
int count, key; |
|
3642 |
{
|
|
3643 |
return bash_glob_completion_internal ('*'); |
|
3644 |
}
|
|
3645 |
||
3646 |
static int |
|
3647 |
bash_glob_list_expansions (count, key) |
|
3648 |
int count, key; |
|
3649 |
{
|
|
3650 |
return bash_glob_completion_internal ('?'); |
|
3651 |
}
|
|
3652 |
||
3653 |
static int |
|
3654 |
bash_specific_completion (what_to_do, generator) |
|
3655 |
int what_to_do; |
|
3656 |
rl_compentry_func_t *generator; |
|
3657 |
{
|
|
3658 |
rl_compentry_func_t *orig_func; |
|
3659 |
rl_completion_func_t *orig_attempt_func; |
|
3660 |
rl_compignore_func_t *orig_ignore_func; |
|
3661 |
int r; |
|
3662 |
||
3663 |
orig_func = rl_completion_entry_function; |
|
3664 |
orig_attempt_func = rl_attempted_completion_function; |
|
3665 |
orig_ignore_func = rl_ignore_some_completions_function; |
|
3666 |
rl_completion_entry_function = generator; |
|
3667 |
rl_attempted_completion_function = NULL; |
|
3668 |
rl_ignore_some_completions_function = orig_ignore_func; |
|
3669 |
||
3670 |
r = rl_complete_internal (what_to_do); |
|
3671 |
||
3672 |
rl_completion_entry_function = orig_func; |
|
3673 |
rl_attempted_completion_function = orig_attempt_func; |
|
3674 |
rl_ignore_some_completions_function = orig_ignore_func; |
|
3675 |
||
3676 |
return r; |
|
3677 |
}
|
|
3678 |
||
3679 |
#endif /* SPECIFIC_COMPLETION_FUNCTIONS */ |
|
3680 |
||
3681 |
#if defined (VI_MODE)
|
|
3682 |
/* Completion, from vi mode's point of view. This is a modified version of
|
|
3683 |
rl_vi_complete which uses the bash globbing code to implement what POSIX
|
|
3684 |
specifies, which is to append a `*' and attempt filename generation (which
|
|
3685 |
has the side effect of expanding any globbing characters in the word). */
|
|
3686 |
static int |
|
3687 |
bash_vi_complete (count, key) |
|
3688 |
int count, key; |
|
3689 |
{
|
|
3690 |
#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
|
|
3691 |
int p, r; |
|
3692 |
char *t; |
|
3693 |
||
3694 |
if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point]))) |
|
3695 |
{
|
|
3696 |
if (!whitespace (rl_line_buffer[rl_point + 1])) |
|
3697 |
rl_vi_end_word (1, 'E'); |
|
3698 |
rl_point++; |
|
3699 |
}
|
|
3700 |
||
3701 |
/* Find boundaries of current word, according to vi definition of a
|
|
3702 |
`bigword'. */
|
|
3703 |
t = 0; |
|
3704 |
if (rl_point > 0) |
|
3705 |
{
|
|
3706 |
p = rl_point; |
|
3707 |
rl_vi_bWord (1, 'B'); |
|
3708 |
r = rl_point; |
|
3709 |
rl_point = p; |
|
3710 |
p = r; |
|
3711 |
||
3712 |
t = substring (rl_line_buffer, p, rl_point); |
|
3713 |
}
|
|
3714 |
||
3715 |
if (t && glob_pattern_p (t) == 0) |
|
3716 |
rl_explicit_arg = 1; /* XXX - force glob_complete_word to append `*' */ |
|
3717 |
FREE (t); |
|
3718 |
||
3719 |
if (key == '*') /* Expansion and replacement. */ |
|
3720 |
r = bash_glob_expand_word (count, key); |
|
3721 |
else if (key == '=') /* List possible completions. */ |
|
3722 |
r = bash_glob_list_expansions (count, key); |
|
3723 |
else if (key == '\\') /* Standard completion */ |
|
3724 |
r = bash_glob_complete_word (count, key); |
|
3725 |
else
|
|
3726 |
r = rl_complete (0, key); |
|
3727 |
||
3728 |
if (key == '*' || key == '\\') |
|
3729 |
rl_vi_start_inserting (key, 1, 1); |
|
3730 |
||
3731 |
return (r); |
|
3732 |
#else
|
|
3733 |
return rl_vi_complete (count, key); |
|
3734 |
#endif /* !SPECIFIC_COMPLETION_FUNCTIONS */ |
|
3735 |
}
|
|
3736 |
#endif /* VI_MODE */ |
|
3737 |
||
3738 |
/* Filename quoting for completion. */
|
|
3739 |
/* A function to strip unquoted quote characters (single quotes, double
|
|
3740 |
quotes, and backslashes). It allows single quotes to appear
|
|
3741 |
within double quotes, and vice versa. It should be smarter. */
|
|
3742 |
static char * |
|
3743 |
bash_dequote_filename (text, quote_char) |
|
3744 |
char *text; |
|
3745 |
int quote_char; |
|
3746 |
{
|
|
3747 |
char *ret, *p, *r; |
|
3748 |
int l, quoted; |
|
3749 |
||
3750 |
l = strlen (text); |
|
3751 |
ret = (char *)xmalloc (l + 1); |
|
3752 |
for (quoted = quote_char, p = text, r = ret; p && *p; p++) |
|
3753 |
{
|
|
3754 |
/* Allow backslash-escaped characters to pass through unscathed. */
|
|
3755 |
if (*p == '\\') |
|
3756 |
{
|
|
3757 |
/* Backslashes are preserved within single quotes. */
|
|
3758 |
if (quoted == '\'') |
|
3759 |
*r++ = *p; |
|
3760 |
/* Backslashes are preserved within double quotes unless the
|
|
3761 |
character is one that is defined to be escaped */
|
|
3762 |
else if (quoted == '"' && ((sh_syntaxtab[p[1]] & CBSDQUOTE) == 0)) |
|
3763 |
*r++ = *p; |
|
3764 |
||
3765 |
*r++ = *++p; |
|
3766 |
if (*p == '\0') |
|
3767 |
return ret; /* XXX - was break; */ |
|
3768 |
continue; |
|
3769 |
}
|
|
3770 |
/* Close quote. */
|
|
3771 |
if (quoted && *p == quoted) |
|
3772 |
{
|
|
3773 |
quoted = 0; |
|
3774 |
continue; |
|
3775 |
}
|
|
3776 |
/* Open quote. */
|
|
3777 |
if (quoted == 0 && (*p == '\'' || *p == '"')) |
|
3778 |
{
|
|
3779 |
quoted = *p; |
|
3780 |
continue; |
|
3781 |
}
|
|
3782 |
*r++ = *p; |
|
3783 |
}
|
|
3784 |
*r = '\0'; |
|
3785 |
return ret; |
|
3786 |
}
|
|
3787 |
||
3788 |
/* Quote characters that the readline completion code would treat as
|
|
3789 |
word break characters with backslashes. Pass backslash-quoted
|
|
3790 |
characters through without examination. */
|
|
3791 |
static char * |
|
3792 |
quote_word_break_chars (text) |
|
3793 |
char *text; |
|
3794 |
{
|
|
3795 |
char *ret, *r, *s; |
|
3796 |
int l; |
|
3797 |
||
3798 |
l = strlen (text); |
|
3799 |
ret = (char *)xmalloc ((2 * l) + 1); |
|
3800 |
for (s = text, r = ret; *s; s++) |
|
3801 |
{
|
|
3802 |
/* Pass backslash-quoted characters through, including the backslash. */
|
|
3803 |
if (*s == '\\') |
|
3804 |
{
|
|
3805 |
*r++ = '\\'; |
|
3806 |
*r++ = *++s; |
|
3807 |
if (*s == '\0') |
|
3808 |
break; |
|
3809 |
continue; |
|
3810 |
}
|
|
3811 |
/* OK, we have an unquoted character. Check its presence in
|
|
3812 |
rl_completer_word_break_characters. */
|
|
3813 |
if (mbschr (rl_completer_word_break_characters, *s)) |
|
3814 |
*r++ = '\\'; |
|
3815 |
/* XXX -- check for standalone tildes here and backslash-quote them */
|
|
3816 |
if (s == text && *s == '~' && file_exists (text)) |
|
3817 |
*r++ = '\\'; |
|
3818 |
*r++ = *s; |
|
3819 |
}
|
|
3820 |
*r = '\0'; |
|
3821 |
return ret; |
|
3822 |
}
|
|
3823 |
||
3824 |
/* Use characters in STRING to populate the table of characters that should
|
|
3825 |
be backslash-quoted. The table will be used for sh_backslash_quote from
|
|
3826 |
this file. */
|
|
3827 |
static void |
|
3828 |
set_filename_bstab (string) |
|
3829 |
const char *string; |
|
3830 |
{
|
|
3831 |
const char *s; |
|
3832 |
||
3833 |
memset (filename_bstab, 0, sizeof (filename_bstab)); |
|
3834 |
for (s = string; s && *s; s++) |
|
3835 |
filename_bstab[*s] = 1; |
|
3836 |
}
|
|
3837 |
||
3838 |
/* Quote a filename using double quotes, single quotes, or backslashes
|
|
3839 |
depending on the value of completion_quoting_style. If we're
|
|
3840 |
completing using backslashes, we need to quote some additional
|
|
3841 |
characters (those that readline treats as word breaks), so we call
|
|
3842 |
quote_word_break_chars on the result. This returns newly-allocated
|
|
3843 |
memory. */
|
|
3844 |
static char * |
|
3845 |
bash_quote_filename (s, rtype, qcp) |
|
3846 |
char *s; |
|
3847 |
int rtype; |
|
3848 |
char *qcp; |
|
3849 |
{
|
|
3850 |
char *rtext, *mtext, *ret; |
|
3851 |
int rlen, cs; |
|
3852 |
||
3853 |
rtext = (char *)NULL; |
|
3854 |
||
3855 |
/* If RTYPE == MULT_MATCH, it means that there is
|
|
3856 |
more than one match. In this case, we do not add
|
|
3857 |
the closing quote or attempt to perform tilde
|
|
3858 |
expansion. If RTYPE == SINGLE_MATCH, we try
|
|
3859 |
to perform tilde expansion, because single and double
|
|
3860 |
quotes inhibit tilde expansion by the shell. */
|
|
3861 |
||
3862 |
cs = completion_quoting_style; |
|
3863 |
/* Might need to modify the default completion style based on *qcp,
|
|
3864 |
since it's set to any user-provided opening quote. We also change
|
|
3865 |
to single-quoting if there is no user-provided opening quote and
|
|
3866 |
the word being completed contains newlines, since those are not
|
|
3867 |
quoted correctly using backslashes (a backslash-newline pair is
|
|
3868 |
special to the shell parser). */
|
|
3869 |
if (*qcp == '\0' && cs == COMPLETE_BSQUOTE && mbschr (s, '\n')) |
|
3870 |
cs = COMPLETE_SQUOTE; |
|
3871 |
else if (*qcp == '"') |
|
3872 |
cs = COMPLETE_DQUOTE; |
|
3873 |
else if (*qcp == '\'') |
|
3874 |
cs = COMPLETE_SQUOTE; |
|
3875 |
#if defined (BANG_HISTORY)
|
|
3876 |
else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE && |
|
3877 |
history_expansion_inhibited == 0 && mbschr (s, '!')) |
|
3878 |
cs = COMPLETE_BSQUOTE; |
|
3879 |
||
3880 |
if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE && |
|
3881 |
history_expansion_inhibited == 0 && mbschr (s, '!')) |
|
3882 |
{
|
|
3883 |
cs = COMPLETE_BSQUOTE; |
|
3884 |
*qcp = '\0'; |
|
3885 |
}
|
|
3886 |
#endif
|
|
3887 |
||
3888 |
/* Don't tilde-expand backslash-quoted filenames, since only single and
|
|
3889 |
double quotes inhibit tilde expansion. */
|
|
3890 |
mtext = s; |
|
3891 |
if (mtext[0] == '~' && rtype == SINGLE_MATCH && cs != COMPLETE_BSQUOTE) |
|
3892 |
mtext = bash_tilde_expand (s, 0); |
|
3893 |
||
3894 |
switch (cs) |
|
3895 |
{
|
|
3896 |
case COMPLETE_DQUOTE: |
|
3897 |
rtext = sh_double_quote (mtext); |
|
3898 |
break; |
|
3899 |
case COMPLETE_SQUOTE: |
|
3900 |
rtext = sh_single_quote (mtext); |
|
3901 |
break; |
|
3902 |
case COMPLETE_BSQUOTE: |
|
3903 |
rtext = sh_backslash_quote (mtext, complete_fullquote ? 0 : filename_bstab, 0); |
|
3904 |
break; |
|
3905 |
}
|
|
3906 |
||
3907 |
if (mtext != s) |
|
3908 |
free (mtext); |
|
3909 |
||
3910 |
/* We may need to quote additional characters: those that readline treats
|
|
3911 |
as word breaks that are not quoted by backslash_quote. */
|
|
3912 |
if (rtext && cs == COMPLETE_BSQUOTE) |
|
3913 |
{
|
|
3914 |
mtext = quote_word_break_chars (rtext); |
|
3915 |
free (rtext); |
|
3916 |
rtext = mtext; |
|
3917 |
}
|
|
3918 |
||
3919 |
/* Leave the opening quote intact. The readline completion code takes
|
|
3920 |
care of avoiding doubled opening quotes. */
|
|
3921 |
if (rtext) |
|
3922 |
{
|
|
3923 |
rlen = strlen (rtext); |
|
3924 |
ret = (char *)xmalloc (rlen + 1); |
|
3925 |
strcpy (ret, rtext); |
|
3926 |
}
|
|
3927 |
else
|
|
3928 |
{
|
|
3929 |
ret = (char *)xmalloc (rlen = 1); |
|
3930 |
ret[0] = '\0'; |
|
3931 |
}
|
|
3932 |
||
3933 |
/* If there are multiple matches, cut off the closing quote. */
|
|
3934 |
if (rtype == MULT_MATCH && cs != COMPLETE_BSQUOTE) |
|
3935 |
ret[rlen - 1] = '\0'; |
|
3936 |
free (rtext); |
|
3937 |
return ret; |
|
3938 |
}
|
|
3939 |
||
3940 |
/* Support for binding readline key sequences to Unix commands. */
|
|
3941 |
static Keymap cmd_xmap; |
|
3942 |
||
3943 |
#ifdef _MINIX
|
|
3944 |
static void |
|
3945 |
#else
|
|
3946 |
static int |
|
3947 |
#endif
|
|
3948 |
putx(c) |
|
3949 |
int c; |
|
3950 |
{
|
|
3951 |
int x; |
|
3952 |
x = putc (c, rl_outstream); |
|
3953 |
#ifndef _MINIX
|
|
3954 |
return x; |
|
3955 |
#endif
|
|
3956 |
}
|
|
3957 |
||
3958 |
static int |
|
3959 |
bash_execute_unix_command (count, key) |
|
3960 |
int count; /* ignored */ |
|
3961 |
int key; |
|
3962 |
{
|
|
3963 |
Keymap ckmap; /* current keymap */ |
|
3964 |
Keymap xkmap; /* unix command executing keymap */ |
|
3965 |
rl_command_func_t *func; |
|
3966 |
int type; |
|
3967 |
register int i, r; |
|
3968 |
intmax_t mi; |
|
3969 |
sh_parser_state_t ps; |
|
3970 |
char *cmd, *value, *l, *l1, *ce; |
|
3971 |
SHELL_VAR *v; |
|
3972 |
char ibuf[INT_STRLEN_BOUND(int) + 1]; |
|
3973 |
||
3974 |
/* First, we need to find the right command to execute. This is tricky,
|
|
3975 |
because we might have already indirected into another keymap, so we
|
|
3976 |
have to walk cmd_xmap using the entire key sequence. */
|
|
3977 |
cmd = (char *)rl_function_of_keyseq (rl_executing_keyseq, cmd_xmap, &type); |
|
3978 |
||
3979 |
if (cmd == 0 || type != ISMACR) |
|
3980 |
{
|
|
3981 |
rl_crlf (); |
|
3982 |
internal_error (_("bash_execute_unix_command: cannot find keymap for command")); |
|
3983 |
rl_forced_update_display (); |
|
3984 |
return 1; |
|
3985 |
}
|
|
3986 |
||
3987 |
ce = rl_get_termcap ("ce"); |
|
3988 |
if (ce) /* clear current line */ |
|
3989 |
{
|
|
3990 |
fprintf (rl_outstream, "\r"); |
|
3991 |
tputs (ce, 1, putx); |
|
3992 |
fflush (rl_outstream); |
|
3993 |
}
|
|
3994 |
else
|
|
3995 |
rl_crlf (); /* move to a new line */ |
|
3996 |
||
3997 |
v = bind_variable ("READLINE_LINE", rl_line_buffer, 0); |
|
3998 |
if (v) |
|
3999 |
VSETATTR (v, att_exported); |
|
4000 |
l = v ? value_cell (v) : 0; |
|
4001 |
value = inttostr (rl_point, ibuf, sizeof (ibuf)); |
|
4002 |
v = bind_int_variable ("READLINE_POINT", value); |
|
4003 |
if (v) |
|
4004 |
VSETATTR (v, att_exported); |
|
4005 |
array_needs_making = 1; |
|
4006 |
||
4007 |
save_parser_state (&ps); |
|
4008 |
r = parse_and_execute (cmd, "bash_execute_unix_command", SEVAL_NOHIST|SEVAL_NOFREE); |
|
4009 |
restore_parser_state (&ps); |
|
4010 |
||
4011 |
v = find_variable ("READLINE_LINE"); |
|
4012 |
l1 = v ? value_cell (v) : 0; |
|
4013 |
if (l1 != l) |
|
4014 |
maybe_make_readline_line (value_cell (v)); |
|
4015 |
v = find_variable ("READLINE_POINT"); |
|
4016 |
if (v && legal_number (value_cell (v), &mi)) |
|
4017 |
{
|
|
4018 |
i = mi; |
|
4019 |
if (i != rl_point) |
|
4020 |
{
|
|
4021 |
rl_point = i; |
|
4022 |
if (rl_point > rl_end) |
|
4023 |
rl_point = rl_end; |
|
4024 |
else if (rl_point < 0) |
|
4025 |
rl_point = 0; |
|
4026 |
}
|
|
4027 |
}
|
|
4028 |
||
4029 |
unbind_variable ("READLINE_LINE"); |
|
4030 |
unbind_variable ("READLINE_POINT"); |
|
4031 |
array_needs_making = 1; |
|
4032 |
||
4033 |
/* and restore the readline buffer and display after command execution. */
|
|
4034 |
rl_forced_update_display (); |
|
4035 |
return 0; |
|
4036 |
}
|
|
4037 |
||
4038 |
int
|
|
4039 |
print_unix_command_map () |
|
4040 |
{
|
|
4041 |
Keymap save; |
|
4042 |
||
4043 |
save = rl_get_keymap (); |
|
4044 |
rl_set_keymap (cmd_xmap); |
|
4045 |
rl_macro_dumper (1); |
|
4046 |
rl_set_keymap (save); |
|
4047 |
return 0; |
|
4048 |
}
|
|
4049 |
||
4050 |
static void |
|
4051 |
init_unix_command_map () |
|
4052 |
{
|
|
4053 |
cmd_xmap = rl_make_bare_keymap (); |
|
4054 |
}
|
|
4055 |
||
4056 |
static int |
|
4057 |
isolate_sequence (string, ind, need_dquote, startp) |
|
4058 |
char *string; |
|
4059 |
int ind, need_dquote, *startp; |
|
4060 |
{
|
|
4061 |
register int i; |
|
4062 |
int c, passc, delim; |
|
4063 |
||
4064 |
for (i = ind; string[i] && whitespace (string[i]); i++) |
|
4065 |
;
|
|
4066 |
/* NEED_DQUOTE means that the first non-white character *must* be `"'. */
|
|
4067 |
if (need_dquote && string[i] != '"') |
|
4068 |
{
|
|
4069 |
builtin_error (_("%s: first non-whitespace character is not `\"'"), string); |
|
4070 |
return -1; |
|
4071 |
}
|
|
4072 |
||
4073 |
/* We can have delimited strings even if NEED_DQUOTE == 0, like the command
|
|
4074 |
string to bind the key sequence to. */
|
|
4075 |
delim = (string[i] == '"' || string[i] == '\'') ? string[i] : 0; |
|
4076 |
||
4077 |
if (startp) |
|
4078 |
*startp = delim ? ++i : i; |
|
4079 |
||
4080 |
for (passc = 0; c = string[i]; i++) |
|
4081 |
{
|
|
4082 |
if (passc) |
|
4083 |
{
|
|
4084 |
passc = 0; |
|
4085 |
continue; |
|
4086 |
}
|
|
4087 |
if (c == '\\') |
|
4088 |
{
|
|
4089 |
passc++; |
|
4090 |
continue; |
|
4091 |
}
|
|
4092 |
if (c == delim) |
|
4093 |
break; |
|
4094 |
}
|
|
4095 |
||
4096 |
if (delim && string[i] != delim) |
|
4097 |
{
|
|
4098 |
builtin_error (_("no closing `%c' in %s"), delim, string); |
|
4099 |
return -1; |
|
4100 |
}
|
|
4101 |
||
4102 |
return i; |
|
4103 |
}
|
|
4104 |
||
4105 |
int
|
|
4106 |
bind_keyseq_to_unix_command (line) |
|
4107 |
char *line; |
|
4108 |
{
|
|
4109 |
Keymap kmap; |
|
4110 |
char *kseq, *value; |
|
4111 |
int i, kstart; |
|
4112 |
||
4113 |
if (cmd_xmap == 0) |
|
4114 |
init_unix_command_map (); |
|
4115 |
||
4116 |
kmap = rl_get_keymap (); |
|
4117 |
||
4118 |
/* We duplicate some of the work done by rl_parse_and_bind here, but
|
|
4119 |
this code only has to handle `"keyseq": ["]command["]' and can
|
|
4120 |
generate an error for anything else. */
|
|
4121 |
i = isolate_sequence (line, 0, 1, &kstart); |
|
4122 |
if (i < 0) |
|
4123 |
return -1; |
|
4124 |
||
4125 |
/* Create the key sequence string to pass to rl_generic_bind */
|
|
4126 |
kseq = substring (line, kstart, i); |
|
4127 |
||
4128 |
for ( ; line[i] && line[i] != ':'; i++) |
|
4129 |
;
|
|
4130 |
if (line[i] != ':') |
|
4131 |
{
|
|
4132 |
builtin_error (_("%s: missing colon separator"), line); |
|
4133 |
FREE (kseq); |
|
4134 |
return -1; |
|
4135 |
}
|
|
4136 |
||
4137 |
i = isolate_sequence (line, i + 1, 0, &kstart); |
|
4138 |
if (i < 0) |
|
4139 |
{
|
|
4140 |
FREE (kseq); |
|
4141 |
return -1; |
|
4142 |
}
|
|
4143 |
||
4144 |
/* Create the value string containing the command to execute. */
|
|
4145 |
value = substring (line, kstart, i); |
|
4146 |
||
4147 |
/* Save the command to execute and the key sequence in the CMD_XMAP */
|
|
4148 |
rl_generic_bind (ISMACR, kseq, value, cmd_xmap); |
|
4149 |
||
4150 |
/* and bind the key sequence in the current keymap to a function that
|
|
4151 |
understands how to execute from CMD_XMAP */
|
|
4152 |
rl_bind_keyseq_in_map (kseq, bash_execute_unix_command, kmap); |
|
4153 |
||
4154 |
free (kseq); |
|
4155 |
return 0; |
|
4156 |
}
|
|
4157 |
||
4158 |
/* Used by the programmable completion code. Complete TEXT as a filename,
|
|
4159 |
but return only directories as matches. Dequotes the filename before
|
|
4160 |
attempting to find matches. */
|
|
4161 |
char ** |
|
4162 |
bash_directory_completion_matches (text) |
|
4163 |
const char *text; |
|
4164 |
{
|
|
4165 |
char **m1; |
|
4166 |
char *dfn; |
|
4167 |
int qc; |
|
4168 |
||
4169 |
qc = rl_dispatching ? rl_completion_quote_character : 0; |
|
4170 |
dfn = bash_dequote_filename ((char *)text, qc); |
|
4171 |
m1 = rl_completion_matches (dfn, rl_filename_completion_function); |
|
4172 |
free (dfn); |
|
4173 |
||
4174 |
if (m1 == 0 || m1[0] == 0) |
|
4175 |
return m1; |
|
4176 |
/* We don't bother recomputing the lcd of the matches, because it will just
|
|
4177 |
get thrown away by the programmable completion code and recomputed
|
|
4178 |
later. */
|
|
4179 |
(void)bash_ignore_filenames (m1); |
|
4180 |
return m1; |
|
4181 |
}
|
|
4182 |
||
4183 |
char * |
|
4184 |
bash_dequote_text (text) |
|
4185 |
const char *text; |
|
4186 |
{
|
|
4187 |
char *dtxt; |
|
4188 |
int qc; |
|
4189 |
||
4190 |
qc = (text[0] == '"' || text[0] == '\'') ? text[0] : 0; |
|
4191 |
dtxt = bash_dequote_filename ((char *)text, qc); |
|
4192 |
return (dtxt); |
|
4193 |
}
|
|
4194 |
||
4195 |
/* This event hook is designed to be called after readline receives a signal
|
|
4196 |
that interrupts read(2). It gives reasonable responsiveness to interrupts
|
|
4197 |
and fatal signals without executing too much code in a signal handler
|
|
4198 |
context. */
|
|
4199 |
static int |
|
4200 |
bash_event_hook () |
|
4201 |
{
|
|
1.5.2
by Matthias Klose
Import upstream version 4.3~rc2 |
4202 |
/* If we're going to longjmp to top_level, make sure we clean up readline.
|
4203 |
check_signals will call QUIT, which will eventually longjmp to top_level,
|
|
4204 |
calling run_interrupt_trap along the way. */
|
|
4205 |
if (interrupt_state) |
|
1.5.1
by Matthias Klose
Import upstream version 4.3~rc1 |
4206 |
rl_cleanup_after_signal (); |
4207 |
bashline_reset_event_hook (); |
|
4208 |
check_signals_and_traps (); /* XXX */ |
|
4209 |
return 0; |
|
4210 |
}
|
|
4211 |
||
4212 |
#endif /* READLINE */ |