LCOV - code coverage report
Current view: top level - bash-4.4.23 - bashline.c (source / functions) Hit Total Coverage
Test: cov-bash.info Lines: 122 1782 6.8 %
Date: 2020-10-29 14:49:28 Functions: 5 103 4.9 %

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

Generated by: LCOV version 1.14.0.6.4058