use it if -0 is specified as the beginning or end of the history
range to list. Doesn't work for fc -e or fc -s by design. Feature
requested by Mike Fied <micfied@gmail.com>
+
+ 8/16
+ ----
+trap.c
+ - _run_trap_internal: use {save,restore}_parser_state instead of
+ {save,restore}_token_state. It's more comprehensive
+
+ 8/23
+ ----
+doc/bash.1
+ - disown: remove repeated text. Report and fix from Thomas Hood
+ <jdthood@gmail.com>
+
+ 8/25
+ ----
+lib/readline/rltty.c
+ - set_special_char: fix prototype (last arg is rl_command_func_t *)
+
+sig.c
+ - set_signal_handler: return oact.sa_handler only if sigaction
+ succeeds; if it doesn't, return SIG_DFL (reasonable default). From
+ https://bugzilla.redhat.com/show_bug.cgi?id=911404
+
+bashline.c
+ - attempt_shell_completion: fix to skip assignment statements preceding
+ command name even if there are no programmable completions defined.
+ From https://bugzilla.redhat.com/show_bug.cgi?id=994659
+ - attempt_shell_completion: if still completing command word following
+ assignment statements, do command completion even if programmable
+ completion defined for partial command name entered so far
+
+ 8/26
+ ----
+pcomplete.c
+ - pcomp_filename_completion_function: make sure rl_filename_dequoting_function
+ is non-NULL before trying to call it. Bug and fix from
+ Andreas Schwab <schwab@linux-m68k.org>
+
+bashline.c
+ - bash_command_name_stat_hook: if *name is not something we're going
+ to look up in $PATH (absolute_program(*name) != 0), just call the
+ usual bash_filename_stat_hook and return those results. This makes
+ completions like $PWD/exam[TAB] add a trailing slash
- assign_array_element_internal: before using array_max_index() when
processing a negative subscript, make sure the variable is an array.
if it's not, use 0 as array_max_index assuming it's a string.
- Bug report from Geir Hauge <geir.hauge@gmail.com>
+ Fixes bug report from Geir Hauge <geir.hauge@gmail.com>
+
+ 8/3
+ ---
+Makefile.in
+ - pcomplete.o: add dependency on $(DEFDIR)/builtext.h. Suggested by
+ Curtis Doty <curtis@greenkey.net>
+
+ 8/5
+ ---
+lib/glob/sm_loop.c
+ - strcompare: short-circuit and return FNM_NOMATCH if the lengths of the
+ pattern and string (pe - p and se - s, respectively) are not equal
+ - strcompare: don't bother trying to set *pe or *se to '\0' if that's
+ what they already are. Fixes bug reported by Geir Hauge
+ <geir.hauge@gmail.com>
+
+ 8/6
+ ---
+doc/{bash.1,bashref.texi},builtins/hash.def,lib/readline/doc/rluser.texi
+ - minor typo changes from Geir Hauge <geir.hauge@gmail.com>
+
+bultins/help.def
+ - show_longdoc: avoid trying to translate the empty string because it
+ often translates to some boilerplate about the project and
+ translation. Report and fix from Geir Hauge <geir.hauge@gmail.com>
+
+ 8/8
+ ---
+builtins/help.def
+ - help_builtin: try two passes through the list of help topics for each
+ argument: one doing exact string matching and one, if the first pass
+ fails to find a match, doing string prefix matching like previous
+ versions. This prevents `help read' from matching both `read' and
+ `readonly', but allows `help r' to match everything beginning with
+ `r'. Inspired by report from Geir Hauge <geir.hauge@gmail.com>
+
+ 8/13
+ ----
+builtins/fc.def
+ - fc_builtin,fc_gethnum: calculate `real' end of the history list and
+ use it if -0 is specified as the beginning or end of the history
+ range to list. Doesn't work for fc -e or fc -s by design. Feature
+ requested by Mike Fied <micfied@gmail.com>
+
+ 8/16
+ ----
+trap.c
+ - _run_trap_internal: use {save,restore}_parser_state instead of
+ {save,restore}_token_state. It's more comprehensive
+
+ 8/23
+ ----
+doc/bash.1
+ - disown: remove repeated text. Report and fix from Thomas Hood
+ <jdthood@gmail.com>
+
+ 8/25
+ ----
+lib/readline/rltty.c
+ - set_special_char: fix prototype (last arg is rl_command_func_t *)
+
+sig.c
+ - set_signal_handler: return oact.sa_handler only if sigaction
+ succeeds; if it doesn't, return SIG_DFL (reasonable default). From
+ https://bugzilla.redhat.com/show_bug.cgi?id=911404
+
+bashline.c
+ - attempt_shell_completion: fix to skip assignment statements preceding
+ command name even if there are no programmable completions defined.
+ From https://bugzilla.redhat.com/show_bug.cgi?id=994659
+ - attempt_shell_completion: if still completing command word following
+ assignment statements, do command completion even if programmable
+ completion defined for partial command name entered so far
+
+ 8/26
+ ----
+pcomplete.c
+ - pcomp_filename_completion_function: make sure rl_filename_dequoting_function
+ is non-NULL before trying to call it. Bug and fix from
+ Andreas Schwab <schwab@linux-m68k.org>
{
int in_command_position, ti, saveti, qc, dflags;
char **matches, *command_separator_chars;
+#if defined (PROGRAMMABLE_COMPLETION)
+ int have_progcomps, was_assignment;
+#endif
command_separator_chars = COMMAND_SEPARATORS;
matches = (char **)NULL;
#if defined (PROGRAMMABLE_COMPLETION)
/* Attempt programmable completion. */
+ have_progcomps = prog_completion_enabled && (progcomp_size () > 0);
if (matches == 0 && (in_command_position == 0 || text[0] == '\0') &&
- prog_completion_enabled && (progcomp_size () > 0) &&
current_prompt_string == ps1_prompt)
{
int s, e, s1, e1, os, foundcs;
n = find_cmd_name (s, &s1, &e1);
s = e1 + 1;
}
- while (assignment (n, 0));
+ while (was_assignment = assignment (n, 0));
s = s1; /* reset to index where name begins */
+ /* s == index of where command name begins (reset above)
+ e == end of current command, may be end of line
+ s1 = index of where command name begins
+ e1 == index of where command name ends
+ start == index of where word to be completed begins
+ end == index of where word to be completed ends
+ if (s == start) we are doing command word completion for sure
+ if (e1 == end) we are at the end of the command name and completing it */
if (start == 0 && end == 0 && e != 0 && text[0] == '\0') /* beginning of non-empty line */
foundcs = 0;
else if (start == end && start == s1 && e != 0 && e1 > end) /* beginning of command name, leading whitespace */
foundcs = 0;
- else if (e == 0 && e == s && text[0] == '\0') /* beginning of empty line */
+ else if (e == 0 && e == s && text[0] == '\0' && have_progcomps) /* beginning of empty line */
prog_complete_matches = programmable_completions ("_EmptycmD_", text, s, e, &foundcs);
else if (start == end && text[0] == '\0' && s1 > start && whitespace (rl_line_buffer[start]))
foundcs = 0; /* whitespace before command name */
- else if (e > s && assignment (n, 0) == 0)
- prog_complete_matches = programmable_completions (n, text, s, e, &foundcs);
+ else if (e > s && was_assignment == 0 && e1 == end && rl_line_buffer[e] == 0 && whitespace (rl_line_buffer[e-1]) == 0)
+ {
+ /* not assignment statement, but still want to perform command
+ completion if we are composing command word. */
+ foundcs = 0;
+ in_command_position = s == start && STREQ (n, text); /* XXX */
+ }
+ else if (e > s && was_assignment == 0 && have_progcomps)
+ {
+ prog_complete_matches = programmable_completions (n, text, s, e, &foundcs);
+ /* command completion if programmable completion fails */
+ in_command_position = s == start && STREQ (n, text); /* XXX */
+ }
else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0)
{
foundcs = 0; /* empty command name following assignments */
- in_command_position = 1;
+ in_command_position = was_assignment;
}
else if (s == start && e == end && STREQ (n, text) && start > 0)
{
{
char *cname, *result;
+ /* If it's not something we're going to look up in $PATH, just call the
+ normal filename stat hook. */
+ if (absolute_program (*name))
+ return (bash_filename_stat_hook (name));
+
cname = *name;
/* XXX - we could do something here with converting aliases, builtins,
and functions into something that came out as executable, but we don't. */
--- /dev/null
+/* bashline.c -- Bash's interface to the readline library. */
+
+/* Copyright (C) 1987-2013 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bash is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bash. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#if defined (READLINE)
+
+#include "bashtypes.h"
+#include "posixstat.h"
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined (HAVE_GRP_H)
+# include <grp.h>
+#endif
+
+#if defined (HAVE_NETDB_H)
+# include <netdb.h>
+#endif
+
+#include <signal.h>
+
+#include <stdio.h>
+#include "chartypes.h"
+#include "bashansi.h"
+#include "bashintl.h"
+
+#include "shell.h"
+#include "input.h"
+#include "builtins.h"
+#include "bashhist.h"
+#include "bashline.h"
+#include "execute_cmd.h"
+#include "findcmd.h"
+#include "pathexp.h"
+#include "shmbutil.h"
+
+#include "builtins/common.h"
+
+#include <readline/rlconf.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include <glob/glob.h>
+
+#if defined (ALIAS)
+# include "alias.h"
+#endif
+
+#if defined (PROGRAMMABLE_COMPLETION)
+# include "pcomplete.h"
+#endif
+
+/* These should agree with the defines for emacs_mode and vi_mode in
+ rldefs.h, even though that's not a public readline header file. */
+#ifndef EMACS_EDITING_MODE
+# define NO_EDITING_MODE -1
+# define EMACS_EDITING_MODE 1
+# define VI_EDITING_MODE 0
+#endif
+
+#define RL_BOOLEAN_VARIABLE_VALUE(s) ((s)[0] == 'o' && (s)[1] == 'n' && (s)[2] == '\0')
+
+#if defined (BRACE_COMPLETION)
+extern int bash_brace_completion __P((int, int));
+#endif /* BRACE_COMPLETION */
+
+/* To avoid including curses.h/term.h/termcap.h and that whole mess. */
+#ifdef _MINIX
+extern int tputs __P((const char *string, int nlines, void (*outx)(int)));
+#else
+extern int tputs __P((const char *string, int nlines, int (*outx)(int)));
+#endif
+
+/* Forward declarations */
+
+/* Functions bound to keys in Readline for Bash users. */
+static int shell_expand_line __P((int, int));
+static int display_shell_version __P((int, int));
+static int operate_and_get_next __P((int, int));
+
+static int bash_ignore_filenames __P((char **));
+static int bash_ignore_everything __P((char **));
+
+#if defined (BANG_HISTORY)
+static char *history_expand_line_internal __P((char *));
+static int history_expand_line __P((int, int));
+static int tcsh_magic_space __P((int, int));
+#endif /* BANG_HISTORY */
+#ifdef ALIAS
+static int alias_expand_line __P((int, int));
+#endif
+#if defined (BANG_HISTORY) && defined (ALIAS)
+static int history_and_alias_expand_line __P((int, int));
+#endif
+
+static int bash_forward_shellword __P((int, int));
+static int bash_backward_shellword __P((int, int));
+static int bash_kill_shellword __P((int, int));
+static int bash_backward_kill_shellword __P((int, int));
+
+/* Helper functions for Readline. */
+static char *restore_tilde __P((char *, char *));
+
+static char *bash_filename_rewrite_hook __P((char *, int));
+
+static void bash_directory_expansion __P((char **));
+static int bash_filename_stat_hook __P((char **));
+static int bash_command_name_stat_hook __P((char **));
+static int bash_directory_completion_hook __P((char **));
+static int filename_completion_ignore __P((char **));
+static int bash_push_line __P((void));
+
+static int executable_completion __P((const char *, int));
+
+static rl_icppfunc_t *save_directory_hook __P((void));
+static void restore_directory_hook __P((rl_icppfunc_t));
+
+static void cleanup_expansion_error __P((void));
+static void maybe_make_readline_line __P((char *));
+static void set_up_new_line __P((char *));
+
+static int check_redir __P((int));
+static char **attempt_shell_completion __P((const char *, int, int));
+static char *variable_completion_function __P((const char *, int));
+static char *hostname_completion_function __P((const char *, int));
+static char *command_subst_completion_function __P((const char *, int));
+
+static void build_history_completion_array __P((void));
+static char *history_completion_generator __P((const char *, int));
+static int dynamic_complete_history __P((int, int));
+static int bash_dabbrev_expand __P((int, int));
+
+static void initialize_hostname_list __P((void));
+static void add_host_name __P((char *));
+static void snarf_hosts_from_file __P((char *));
+static char **hostnames_matching __P((char *));
+
+static void _ignore_completion_names __P((char **, sh_ignore_func_t *));
+static int name_is_acceptable __P((const char *));
+static int test_for_directory __P((const char *));
+static int return_zero __P((const char *));
+
+static char *bash_dequote_filename __P((char *, int));
+static char *quote_word_break_chars __P((char *));
+static void set_filename_bstab __P((const char *));
+static char *bash_quote_filename __P((char *, int, char *));
+
+#ifdef _MINIX
+static void putx __P((int));
+#else
+static int putx __P((int));
+#endif
+static int bash_execute_unix_command __P((int, int));
+static void init_unix_command_map __P((void));
+static int isolate_sequence __P((char *, int, int, int *));
+
+static int set_saved_history __P((void));
+
+#if defined (ALIAS)
+static int posix_edit_macros __P((int, int));
+#endif
+
+static int bash_event_hook __P((void));
+
+#if defined (PROGRAMMABLE_COMPLETION)
+static int find_cmd_start __P((int));
+static int find_cmd_end __P((int));
+static char *find_cmd_name __P((int, int *, int *));
+static char *prog_complete_return __P((const char *, int));
+
+static char **prog_complete_matches;
+#endif
+
+/* Variables used here but defined in other files. */
+#if defined (BANG_HISTORY)
+extern int hist_verify;
+#endif
+
+extern int current_command_line_count, saved_command_line_count;
+extern int last_command_exit_value;
+extern int array_needs_making;
+extern int posixly_correct, no_symbolic_links;
+extern char *current_prompt_string, *ps1_prompt;
+extern STRING_INT_ALIST word_token_alist[];
+extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
+
+/* SPECIFIC_COMPLETION_FUNCTIONS specifies that we have individual
+ completion functions which indicate what type of completion should be
+ done (at or before point) that can be bound to key sequences with
+ the readline library. */
+#define SPECIFIC_COMPLETION_FUNCTIONS
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+static int bash_specific_completion __P((int, rl_compentry_func_t *));
+
+static int bash_complete_filename_internal __P((int));
+static int bash_complete_username_internal __P((int));
+static int bash_complete_hostname_internal __P((int));
+static int bash_complete_variable_internal __P((int));
+static int bash_complete_command_internal __P((int));
+
+static int bash_complete_filename __P((int, int));
+static int bash_possible_filename_completions __P((int, int));
+static int bash_complete_username __P((int, int));
+static int bash_possible_username_completions __P((int, int));
+static int bash_complete_hostname __P((int, int));
+static int bash_possible_hostname_completions __P((int, int));
+static int bash_complete_variable __P((int, int));
+static int bash_possible_variable_completions __P((int, int));
+static int bash_complete_command __P((int, int));
+static int bash_possible_command_completions __P((int, int));
+
+static char *glob_complete_word __P((const char *, int));
+static int bash_glob_completion_internal __P((int));
+static int bash_glob_complete_word __P((int, int));
+static int bash_glob_expand_word __P((int, int));
+static int bash_glob_list_expansions __P((int, int));
+
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
+
+static int edit_and_execute_command __P((int, int, int, char *));
+#if defined (VI_MODE)
+static int vi_edit_and_execute_command __P((int, int));
+static int bash_vi_complete __P((int, int));
+#endif
+static int emacs_edit_and_execute_command __P((int, int));
+
+/* Non-zero once initalize_readline () has been called. */
+int bash_readline_initialized = 0;
+
+/* If non-zero, we do hostname completion, breaking words at `@' and
+ trying to complete the stuff after the `@' from our own internal
+ host list. */
+int perform_hostname_completion = 1;
+
+/* If non-zero, we don't do command completion on an empty line. */
+int no_empty_command_completion;
+
+/* Set FORCE_FIGNORE if you want to honor FIGNORE even if it ignores the
+ only possible matches. Set to 0 if you want to match filenames if they
+ are the only possible matches, even if FIGNORE says to. */
+int force_fignore = 1;
+
+/* Perform spelling correction on directory names during word completion */
+int dircomplete_spelling = 0;
+
+/* Expand directory names during word/filename completion. */
+#if DIRCOMPLETE_EXPAND_DEFAULT
+int dircomplete_expand = 1;
+int dircomplete_expand_relpath = 1;
+#else
+int dircomplete_expand = 0;
+int dircomplete_expand_relpath = 0;
+#endif
+
+/* When non-zero, perform `normal' shell quoting on completed filenames
+ even when the completed name contains a directory name with a shell
+ variable referene, so dollar signs in a filename get quoted appropriately.
+ Set to zero to remove dollar sign (and braces or parens as needed) from
+ the set of characters that will be quoted. */
+int complete_fullquote = 1;
+
+static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
+static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
+/* )) */
+
+static const char *default_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/
+static char *custom_filename_quote_characters = 0;
+static char filename_bstab[256];
+
+static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
+
+static int dot_in_path = 0;
+
+/* Set to non-zero when dabbrev-expand is running */
+static int dabbrev_expand_active = 0;
+
+/* What kind of quoting is performed by bash_quote_filename:
+ COMPLETE_DQUOTE = double-quoting the filename
+ COMPLETE_SQUOTE = single_quoting the filename
+ COMPLETE_BSQUOTE = backslash-quoting special chars in the filename
+*/
+#define COMPLETE_DQUOTE 1
+#define COMPLETE_SQUOTE 2
+#define COMPLETE_BSQUOTE 3
+static int completion_quoting_style = COMPLETE_BSQUOTE;
+
+/* Flag values for the final argument to bash_default_completion */
+#define DEFCOMP_CMDPOS 1
+
+/* Change the readline VI-mode keymaps into or out of Posix.2 compliance.
+ Called when the shell is put into or out of `posix' mode. */
+void
+posix_readline_initialize (on_or_off)
+ int on_or_off;
+{
+ if (on_or_off)
+ rl_variable_bind ("comment-begin", "#");
+#if defined (VI_MODE)
+ rl_bind_key_in_map (CTRL ('I'), on_or_off ? rl_insert : rl_complete, vi_insertion_keymap);
+#endif
+}
+
+void
+reset_completer_word_break_chars ()
+{
+ rl_completer_word_break_characters = perform_hostname_completion ? savestring (bash_completer_word_break_characters) : savestring (bash_nohostname_word_break_characters);
+}
+
+/* When this function returns, rl_completer_word_break_characters points to
+ dynamically allocated memory. */
+int
+enable_hostname_completion (on_or_off)
+ int on_or_off;
+{
+ int old_value;
+ char *at, *nv, *nval;
+
+ old_value = perform_hostname_completion;
+
+ if (on_or_off)
+ {
+ perform_hostname_completion = 1;
+ rl_special_prefixes = "$@";
+ }
+ else
+ {
+ perform_hostname_completion = 0;
+ rl_special_prefixes = "$";
+ }
+
+ /* Now we need to figure out how to appropriately modify and assign
+ rl_completer_word_break_characters depending on whether we want
+ hostname completion on or off. */
+
+ /* If this is the first time this has been called
+ (bash_readline_initialized == 0), use the sames values as before, but
+ allocate new memory for rl_completer_word_break_characters. */
+
+ if (bash_readline_initialized == 0 &&
+ (rl_completer_word_break_characters == 0 ||
+ rl_completer_word_break_characters == rl_basic_word_break_characters))
+ {
+ if (on_or_off)
+ rl_completer_word_break_characters = savestring (bash_completer_word_break_characters);
+ else
+ rl_completer_word_break_characters = savestring (bash_nohostname_word_break_characters);
+ }
+ else
+ {
+ /* See if we have anything to do. */
+ at = strchr (rl_completer_word_break_characters, '@');
+ if ((at == 0 && on_or_off == 0) || (at != 0 && on_or_off != 0))
+ return old_value;
+
+ /* We have something to do. Do it. */
+ nval = (char *)xmalloc (strlen (rl_completer_word_break_characters) + 1 + on_or_off);
+
+ if (on_or_off == 0)
+ {
+ /* Turn it off -- just remove `@' from word break chars. We want
+ to remove all occurrences of `@' from the char list, so we loop
+ rather than just copy the rest of the list over AT. */
+ for (nv = nval, at = rl_completer_word_break_characters; *at; )
+ if (*at != '@')
+ *nv++ = *at++;
+ else
+ at++;
+ *nv = '\0';
+ }
+ else
+ {
+ nval[0] = '@';
+ strcpy (nval + 1, rl_completer_word_break_characters);
+ }
+
+ free (rl_completer_word_break_characters);
+ rl_completer_word_break_characters = nval;
+ }
+
+ return (old_value);
+}
+
+/* Called once from parse.y if we are going to use readline. */
+void
+initialize_readline ()
+{
+ rl_command_func_t *func;
+ char kseq[2];
+
+ if (bash_readline_initialized)
+ return;
+
+ rl_terminal_name = get_string_value ("TERM");
+ rl_instream = stdin;
+ rl_outstream = stderr;
+
+ /* Allow conditional parsing of the ~/.inputrc file. */
+ rl_readline_name = "Bash";
+
+ /* Add bindable names before calling rl_initialize so they may be
+ referenced in the various inputrc files. */
+ rl_add_defun ("shell-expand-line", shell_expand_line, -1);
+#ifdef BANG_HISTORY
+ rl_add_defun ("history-expand-line", history_expand_line, -1);
+ rl_add_defun ("magic-space", tcsh_magic_space, -1);
+#endif
+
+ rl_add_defun ("shell-forward-word", bash_forward_shellword, -1);
+ rl_add_defun ("shell-backward-word", bash_backward_shellword, -1);
+ rl_add_defun ("shell-kill-word", bash_kill_shellword, -1);
+ rl_add_defun ("shell-backward-kill-word", bash_backward_kill_shellword, -1);
+
+#ifdef ALIAS
+ rl_add_defun ("alias-expand-line", alias_expand_line, -1);
+# ifdef BANG_HISTORY
+ rl_add_defun ("history-and-alias-expand-line", history_and_alias_expand_line, -1);
+# endif
+#endif
+
+ /* Backwards compatibility. */
+ rl_add_defun ("insert-last-argument", rl_yank_last_arg, -1);
+
+ rl_add_defun ("operate-and-get-next", operate_and_get_next, -1);
+ rl_add_defun ("display-shell-version", display_shell_version, -1);
+ rl_add_defun ("edit-and-execute-command", emacs_edit_and_execute_command, -1);
+
+#if defined (BRACE_COMPLETION)
+ rl_add_defun ("complete-into-braces", bash_brace_completion, -1);
+#endif
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+ rl_add_defun ("complete-filename", bash_complete_filename, -1);
+ rl_add_defun ("possible-filename-completions", bash_possible_filename_completions, -1);
+ rl_add_defun ("complete-username", bash_complete_username, -1);
+ rl_add_defun ("possible-username-completions", bash_possible_username_completions, -1);
+ rl_add_defun ("complete-hostname", bash_complete_hostname, -1);
+ rl_add_defun ("possible-hostname-completions", bash_possible_hostname_completions, -1);
+ rl_add_defun ("complete-variable", bash_complete_variable, -1);
+ rl_add_defun ("possible-variable-completions", bash_possible_variable_completions, -1);
+ rl_add_defun ("complete-command", bash_complete_command, -1);
+ rl_add_defun ("possible-command-completions", bash_possible_command_completions, -1);
+ rl_add_defun ("glob-complete-word", bash_glob_complete_word, -1);
+ rl_add_defun ("glob-expand-word", bash_glob_expand_word, -1);
+ rl_add_defun ("glob-list-expansions", bash_glob_list_expansions, -1);
+#endif
+
+ rl_add_defun ("dynamic-complete-history", dynamic_complete_history, -1);
+ rl_add_defun ("dabbrev-expand", bash_dabbrev_expand, -1);
+
+ /* Bind defaults before binding our custom shell keybindings. */
+ if (RL_ISSTATE(RL_STATE_INITIALIZED) == 0)
+ rl_initialize ();
+
+ /* Bind up our special shell functions. */
+ rl_bind_key_if_unbound_in_map (CTRL('E'), shell_expand_line, emacs_meta_keymap);
+
+#ifdef BANG_HISTORY
+ rl_bind_key_if_unbound_in_map ('^', history_expand_line, emacs_meta_keymap);
+#endif
+
+ rl_bind_key_if_unbound_in_map (CTRL ('O'), operate_and_get_next, emacs_standard_keymap);
+ rl_bind_key_if_unbound_in_map (CTRL ('V'), display_shell_version, emacs_ctlx_keymap);
+
+ /* In Bash, the user can switch editing modes with "set -o [vi emacs]",
+ so it is not necessary to allow C-M-j for context switching. Turn
+ off this occasionally confusing behaviour. */
+ kseq[0] = CTRL('J');
+ kseq[1] = '\0';
+ func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+ if (func == rl_vi_editing_mode)
+ rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap);
+ kseq[0] = CTRL('M');
+ func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+ if (func == rl_vi_editing_mode)
+ rl_unbind_key_in_map (CTRL('M'), emacs_meta_keymap);
+#if defined (VI_MODE)
+ rl_unbind_key_in_map (CTRL('E'), vi_movement_keymap);
+#endif
+
+#if defined (BRACE_COMPLETION)
+ rl_bind_key_if_unbound_in_map ('{', bash_brace_completion, emacs_meta_keymap); /*}*/
+#endif /* BRACE_COMPLETION */
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+ rl_bind_key_if_unbound_in_map ('/', bash_complete_filename, emacs_meta_keymap);
+ rl_bind_key_if_unbound_in_map ('/', bash_possible_filename_completions, emacs_ctlx_keymap);
+
+ /* Have to jump through hoops here because there is a default binding for
+ M-~ (rl_tilde_expand) */
+ kseq[0] = '~';
+ kseq[1] = '\0';
+ func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+ if (func == 0 || func == rl_tilde_expand)
+ rl_bind_keyseq_in_map (kseq, bash_complete_username, emacs_meta_keymap);
+
+ rl_bind_key_if_unbound_in_map ('~', bash_possible_username_completions, emacs_ctlx_keymap);
+
+ rl_bind_key_if_unbound_in_map ('@', bash_complete_hostname, emacs_meta_keymap);
+ rl_bind_key_if_unbound_in_map ('@', bash_possible_hostname_completions, emacs_ctlx_keymap);
+
+ rl_bind_key_if_unbound_in_map ('$', bash_complete_variable, emacs_meta_keymap);
+ rl_bind_key_if_unbound_in_map ('$', bash_possible_variable_completions, emacs_ctlx_keymap);
+
+ rl_bind_key_if_unbound_in_map ('!', bash_complete_command, emacs_meta_keymap);
+ rl_bind_key_if_unbound_in_map ('!', bash_possible_command_completions, emacs_ctlx_keymap);
+
+ rl_bind_key_if_unbound_in_map ('g', bash_glob_complete_word, emacs_meta_keymap);
+ rl_bind_key_if_unbound_in_map ('*', bash_glob_expand_word, emacs_ctlx_keymap);
+ rl_bind_key_if_unbound_in_map ('g', bash_glob_list_expansions, emacs_ctlx_keymap);
+
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
+
+ kseq[0] = TAB;
+ kseq[1] = '\0';
+ func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+ if (func == 0 || func == rl_tab_insert)
+ rl_bind_key_in_map (TAB, dynamic_complete_history, emacs_meta_keymap);
+
+ /* Tell the completer that we want a crack first. */
+ rl_attempted_completion_function = attempt_shell_completion;
+
+ /* Tell the completer that we might want to follow symbolic links or
+ do other expansion on directory names. */
+ set_directory_hook ();
+
+ rl_filename_rewrite_hook = bash_filename_rewrite_hook;
+
+ rl_filename_stat_hook = bash_filename_stat_hook;
+
+ /* Tell the filename completer we want a chance to ignore some names. */
+ rl_ignore_some_completions_function = filename_completion_ignore;
+
+ /* Bind C-xC-e to invoke emacs and run result as commands. */
+ rl_bind_key_if_unbound_in_map (CTRL ('E'), emacs_edit_and_execute_command, emacs_ctlx_keymap);
+#if defined (VI_MODE)
+ rl_bind_key_if_unbound_in_map ('v', vi_edit_and_execute_command, vi_movement_keymap);
+# if defined (ALIAS)
+ rl_bind_key_if_unbound_in_map ('@', posix_edit_macros, vi_movement_keymap);
+# endif
+
+ rl_bind_key_in_map ('\\', bash_vi_complete, vi_movement_keymap);
+ rl_bind_key_in_map ('*', bash_vi_complete, vi_movement_keymap);
+ rl_bind_key_in_map ('=', bash_vi_complete, vi_movement_keymap);
+#endif
+
+ rl_completer_quote_characters = "'\"";
+
+ /* This sets rl_completer_word_break_characters and rl_special_prefixes
+ to the appropriate values, depending on whether or not hostname
+ completion is enabled. */
+ enable_hostname_completion (perform_hostname_completion);
+
+ /* characters that need to be quoted when appearing in filenames. */
+ rl_filename_quote_characters = default_filename_quote_characters;
+ set_filename_bstab (rl_filename_quote_characters);
+
+ rl_filename_quoting_function = bash_quote_filename;
+ rl_filename_dequoting_function = bash_dequote_filename;
+ rl_char_is_quoted_p = char_is_quoted;
+
+#if 0
+ /* This is superfluous and makes it impossible to use tab completion in
+ vi mode even when explicitly binding it in ~/.inputrc. sv_strict_posix()
+ should already have called posix_readline_initialize() when
+ posixly_correct was set. */
+ if (posixly_correct)
+ posix_readline_initialize (1);
+#endif
+
+ bash_readline_initialized = 1;
+}
+
+void
+bashline_reinitialize ()
+{
+ bash_readline_initialized = 0;
+}
+
+void
+bashline_set_event_hook ()
+{
+ rl_signal_event_hook = bash_event_hook;
+}
+
+void
+bashline_reset_event_hook ()
+{
+ rl_signal_event_hook = 0;
+}
+
+/* On Sun systems at least, rl_attempted_completion_function can end up
+ getting set to NULL, and rl_completion_entry_function set to do command
+ word completion if Bash is interrupted while trying to complete a command
+ word. This just resets all the completion functions to the right thing.
+ It's called from throw_to_top_level(). */
+void
+bashline_reset ()
+{
+ tilde_initialize ();
+ rl_attempted_completion_function = attempt_shell_completion;
+ rl_completion_entry_function = NULL;
+ rl_ignore_some_completions_function = filename_completion_ignore;
+ rl_filename_quote_characters = default_filename_quote_characters;
+ set_filename_bstab (rl_filename_quote_characters);
+
+ set_directory_hook ();
+ rl_filename_stat_hook = bash_filename_stat_hook;
+
+ bashline_reset_event_hook ();
+}
+
+/* Contains the line to push into readline. */
+static char *push_to_readline = (char *)NULL;
+
+/* Push the contents of push_to_readline into the
+ readline buffer. */
+static int
+bash_push_line ()
+{
+ if (push_to_readline)
+ {
+ rl_insert_text (push_to_readline);
+ free (push_to_readline);
+ push_to_readline = (char *)NULL;
+ rl_startup_hook = old_rl_startup_hook;
+ }
+ return 0;
+}
+
+/* Call this to set the initial text for the next line to read
+ from readline. */
+int
+bash_re_edit (line)
+ char *line;
+{
+ FREE (push_to_readline);
+
+ push_to_readline = savestring (line);
+ old_rl_startup_hook = rl_startup_hook;
+ rl_startup_hook = bash_push_line;
+
+ return (0);
+}
+
+static int
+display_shell_version (count, c)
+ int count, c;
+{
+ rl_crlf ();
+ show_shell_version (0);
+ putc ('\r', rl_outstream);
+ fflush (rl_outstream);
+ rl_on_new_line ();
+ rl_redisplay ();
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Readline Stuff */
+/* */
+/* **************************************************************** */
+
+/* If the user requests hostname completion, then simply build a list
+ of hosts, and complete from that forever more, or at least until
+ HOSTFILE is unset. */
+
+/* THIS SHOULD BE A STRINGLIST. */
+/* The kept list of hostnames. */
+static char **hostname_list = (char **)NULL;
+
+/* The physical size of the above list. */
+static int hostname_list_size;
+
+/* The number of hostnames in the above list. */
+static int hostname_list_length;
+
+/* Whether or not HOSTNAME_LIST has been initialized. */
+int hostname_list_initialized = 0;
+
+/* Initialize the hostname completion table. */
+static void
+initialize_hostname_list ()
+{
+ char *temp;
+
+ temp = get_string_value ("HOSTFILE");
+ if (temp == 0)
+ temp = get_string_value ("hostname_completion_file");
+ if (temp == 0)
+ temp = DEFAULT_HOSTS_FILE;
+
+ snarf_hosts_from_file (temp);
+
+ if (hostname_list)
+ hostname_list_initialized++;
+}
+
+/* Add NAME to the list of hosts. */
+static void
+add_host_name (name)
+ char *name;
+{
+ if (hostname_list_length + 2 > hostname_list_size)
+ {
+ hostname_list_size = (hostname_list_size + 32) - (hostname_list_size % 32);
+ hostname_list = strvec_resize (hostname_list, hostname_list_size);
+ }
+
+ hostname_list[hostname_list_length++] = savestring (name);
+ hostname_list[hostname_list_length] = (char *)NULL;
+}
+
+#define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
+
+static void
+snarf_hosts_from_file (filename)
+ char *filename;
+{
+ FILE *file;
+ char *temp, buffer[256], name[256];
+ register int i, start;
+
+ file = fopen (filename, "r");
+ if (file == 0)
+ return;
+
+ while (temp = fgets (buffer, 255, file))
+ {
+ /* Skip to first character. */
+ for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++)
+ ;
+
+ /* If comment or blank line, ignore. */
+ if (buffer[i] == '\0' || buffer[i] == '#')
+ continue;
+
+ /* If `preprocessor' directive, do the include. */
+ if (strncmp (buffer + i, "$include ", 9) == 0)
+ {
+ char *incfile, *t;
+
+ /* Find start of filename. */
+ for (incfile = buffer + i + 9; *incfile && whitespace (*incfile); incfile++)
+ ;
+
+ /* Find end of filename. */
+ for (t = incfile; *t && cr_whitespace (*t) == 0; t++)
+ ;
+
+ *t = '\0';
+
+ snarf_hosts_from_file (incfile);
+ continue;
+ }
+
+ /* Skip internet address if present. */
+ if (DIGIT (buffer[i]))
+ for (; buffer[i] && cr_whitespace (buffer[i]) == 0; i++);
+
+ /* Gobble up names. Each name is separated with whitespace. */
+ while (buffer[i])
+ {
+ for (; cr_whitespace (buffer[i]); i++)
+ ;
+ if (buffer[i] == '\0' || buffer[i] == '#')
+ break;
+
+ /* Isolate the current word. */
+ for (start = i; buffer[i] && cr_whitespace (buffer[i]) == 0; i++)
+ ;
+ if (i == start)
+ continue;
+ strncpy (name, buffer + start, i - start);
+ name[i - start] = '\0';
+ add_host_name (name);
+ }
+ }
+ fclose (file);
+}
+
+/* Return the hostname list. */
+char **
+get_hostname_list ()
+{
+ if (hostname_list_initialized == 0)
+ initialize_hostname_list ();
+ return (hostname_list);
+}
+
+void
+clear_hostname_list ()
+{
+ register int i;
+
+ if (hostname_list_initialized == 0)
+ return;
+ for (i = 0; i < hostname_list_length; i++)
+ free (hostname_list[i]);
+ hostname_list_length = hostname_list_initialized = 0;
+}
+
+/* Return a NULL terminated list of hostnames which begin with TEXT.
+ Initialize the hostname list the first time if neccessary.
+ The array is malloc ()'ed, but not the individual strings. */
+static char **
+hostnames_matching (text)
+ char *text;
+{
+ register int i, len, nmatch, rsize;
+ char **result;
+
+ if (hostname_list_initialized == 0)
+ initialize_hostname_list ();
+
+ if (hostname_list_initialized == 0)
+ return ((char **)NULL);
+
+ /* Special case. If TEXT consists of nothing, then the whole list is
+ what is desired. */
+ if (*text == '\0')
+ {
+ result = strvec_create (1 + hostname_list_length);
+ for (i = 0; i < hostname_list_length; i++)
+ result[i] = hostname_list[i];
+ result[i] = (char *)NULL;
+ return (result);
+ }
+
+ /* Scan until found, or failure. */
+ len = strlen (text);
+ result = (char **)NULL;
+ for (i = nmatch = rsize = 0; i < hostname_list_length; i++)
+ {
+ if (STREQN (text, hostname_list[i], len) == 0)
+ continue;
+
+ /* OK, it matches. Add it to the list. */
+ if (nmatch >= (rsize - 1))
+ {
+ rsize = (rsize + 16) - (rsize % 16);
+ result = strvec_resize (result, rsize);
+ }
+
+ result[nmatch++] = hostname_list[i];
+ }
+ if (nmatch)
+ result[nmatch] = (char *)NULL;
+ return (result);
+}
+
+/* The equivalent of the Korn shell C-o operate-and-get-next-history-line
+ editing command. */
+static int saved_history_line_to_use = -1;
+static int last_saved_history_line = -1;
+
+#define HISTORY_FULL() (history_is_stifled () && history_length >= history_max_entries)
+
+static int
+set_saved_history ()
+{
+ /* XXX - compensate for assumption that history was `shuffled' if it was
+ actually not. */
+ if (HISTORY_FULL () &&
+ hist_last_line_added == 0 &&
+ saved_history_line_to_use < history_length - 1)
+ saved_history_line_to_use++;
+
+ if (saved_history_line_to_use >= 0)
+ {
+ rl_get_previous_history (history_length - saved_history_line_to_use, 0);
+ last_saved_history_line = saved_history_line_to_use;
+ }
+ saved_history_line_to_use = -1;
+ rl_startup_hook = old_rl_startup_hook;
+ return (0);
+}
+
+static int
+operate_and_get_next (count, c)
+ int count, c;
+{
+ int where;
+
+ /* Accept the current line. */
+ rl_newline (1, c);
+
+ /* Find the current line, and find the next line to use. */
+ where = where_history ();
+
+ if (HISTORY_FULL () || (where >= history_length - 1))
+ saved_history_line_to_use = where;
+ else
+ saved_history_line_to_use = where + 1;
+
+ old_rl_startup_hook = rl_startup_hook;
+ rl_startup_hook = set_saved_history;
+
+ return 0;
+}
+
+/* This vi mode command causes VI_EDIT_COMMAND to be run on the current
+ command being entered (if no explicit argument is given), otherwise on
+ a command from the history file. */
+
+#define VI_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-vi}}\""
+#define EMACS_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-emacs}}\""
+#define POSIX_VI_EDIT_COMMAND "fc -e vi"
+
+static int
+edit_and_execute_command (count, c, editing_mode, edit_command)
+ int count, c, editing_mode;
+ char *edit_command;
+{
+ char *command, *metaval;
+ int r, rrs, metaflag;
+ sh_parser_state_t ps;
+
+ rrs = rl_readline_state;
+ saved_command_line_count = current_command_line_count;
+
+ /* Accept the current line. */
+ rl_newline (1, c);
+
+ if (rl_explicit_arg)
+ {
+ command = (char *)xmalloc (strlen (edit_command) + 8);
+ sprintf (command, "%s %d", edit_command, count);
+ }
+ else
+ {
+ /* Take the command we were just editing, add it to the history file,
+ then call fc to operate on it. We have to add a dummy command to
+ the end of the history because fc ignores the last command (assumes
+ it's supposed to deal with the command before the `fc'). */
+ /* This breaks down when using command-oriented history and are not
+ finished with the command, so we should not ignore the last command */
+ using_history ();
+ current_command_line_count++; /* for rl_newline above */
+ bash_add_history (rl_line_buffer);
+ current_command_line_count = 0; /* for dummy history entry */
+ bash_add_history ("");
+ history_lines_this_session++;
+ using_history ();
+ command = savestring (edit_command);
+ }
+
+ metaval = rl_variable_value ("input-meta");
+ metaflag = RL_BOOLEAN_VARIABLE_VALUE (metaval);
+
+ /* Now, POSIX.1-2001 and SUSv3 say that the commands executed from the
+ temporary file should be placed into the history. We don't do that
+ yet. */
+ if (rl_deprep_term_function)
+ (*rl_deprep_term_function) ();
+ save_parser_state (&ps);
+ r = parse_and_execute (command, (editing_mode == VI_EDITING_MODE) ? "v" : "C-xC-e", SEVAL_NOHIST);
+ restore_parser_state (&ps);
+ if (rl_prep_term_function)
+ (*rl_prep_term_function) (metaflag);
+
+ current_command_line_count = saved_command_line_count;
+
+ /* Now erase the contents of the current line and undo the effects of the
+ rl_accept_line() above. We don't even want to make the text we just
+ executed available for undoing. */
+ rl_line_buffer[0] = '\0'; /* XXX */
+ rl_point = rl_end = 0;
+ rl_done = 0;
+ rl_readline_state = rrs;
+
+ rl_forced_update_display ();
+
+ return r;
+}
+
+#if defined (VI_MODE)
+static int
+vi_edit_and_execute_command (count, c)
+ int count, c;
+{
+ if (posixly_correct)
+ return (edit_and_execute_command (count, c, VI_EDITING_MODE, POSIX_VI_EDIT_COMMAND));
+ else
+ return (edit_and_execute_command (count, c, VI_EDITING_MODE, VI_EDIT_COMMAND));
+}
+#endif /* VI_MODE */
+
+static int
+emacs_edit_and_execute_command (count, c)
+ int count, c;
+{
+ return (edit_and_execute_command (count, c, EMACS_EDITING_MODE, EMACS_EDIT_COMMAND));
+}
+
+#if defined (ALIAS)
+static int
+posix_edit_macros (count, key)
+ int count, key;
+{
+ int c;
+ char alias_name[3], *alias_value, *macro;
+
+ c = rl_read_key ();
+ alias_name[0] = '_';
+ alias_name[1] = c;
+ alias_name[2] = '\0';
+
+ alias_value = get_alias_value (alias_name);
+ if (alias_value && *alias_value)
+ {
+ macro = savestring (alias_value);
+ rl_push_macro_input (macro);
+ }
+ return 0;
+}
+#endif
+
+/* Bindable commands that move `shell-words': that is, sequences of
+ non-unquoted-metacharacters. */
+
+#define WORDDELIM(c) (shellmeta(c) || shellblank(c))
+
+static int
+bash_forward_shellword (count, key)
+ int count, key;
+{
+ size_t slen;
+ int sindex, c, p;
+ DECLARE_MBSTATE;
+
+ if (count < 0)
+ return (bash_backward_shellword (-count, key));
+
+ /* The tricky part of this is deciding whether or not the first character
+ we're on is an unquoted metacharacter. Not completely handled yet. */
+ /* XXX - need to test this stuff with backslash-escaped shell
+ metacharacters and unclosed single- and double-quoted strings. */
+
+ p = rl_point;
+ slen = rl_end;
+
+ while (count)
+ {
+ if (p == rl_end)
+ {
+ rl_point = rl_end;
+ return 0;
+ }
+
+ /* Are we in a quoted string? If we are, move to the end of the quoted
+ string and continue the outer loop. We only want quoted strings, not
+ backslash-escaped characters, but char_is_quoted doesn't
+ differentiate. */
+ if (char_is_quoted (rl_line_buffer, p) && p > 0 && rl_line_buffer[p-1] != '\\')
+ {
+ do
+ ADVANCE_CHAR (rl_line_buffer, slen, p);
+ while (p < rl_end && char_is_quoted (rl_line_buffer, p));
+ count--;
+ continue;
+ }
+
+ /* Rest of code assumes we are not in a quoted string. */
+ /* Move forward until we hit a non-metacharacter. */
+ while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c))
+ {
+ switch (c)
+ {
+ default:
+ ADVANCE_CHAR (rl_line_buffer, slen, p);
+ continue; /* straight back to loop, don't increment p */
+ case '\\':
+ if (p < rl_end && rl_line_buffer[p])
+ ADVANCE_CHAR (rl_line_buffer, slen, p);
+ break;
+ case '\'':
+ p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP);
+ break;
+ case '"':
+ p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP);
+ break;
+ }
+
+ if (p < rl_end)
+ p++;
+ }
+
+ if (rl_line_buffer[p] == 0 || p == rl_end)
+ {
+ rl_point = rl_end;
+ rl_ding ();
+ return 0;
+ }
+
+ /* Now move forward until we hit a non-quoted metacharacter or EOL */
+ while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c) == 0)
+ {
+ switch (c)
+ {
+ default:
+ ADVANCE_CHAR (rl_line_buffer, slen, p);
+ continue; /* straight back to loop, don't increment p */
+ case '\\':
+ if (p < rl_end && rl_line_buffer[p])
+ ADVANCE_CHAR (rl_line_buffer, slen, p);
+ break;
+ case '\'':
+ p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP);
+ break;
+ case '"':
+ p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP);
+ break;
+ }
+
+ if (p < rl_end)
+ p++;
+ }
+
+ if (p == rl_end || rl_line_buffer[p] == 0)
+ {
+ rl_point = rl_end;
+ return (0);
+ }
+
+ count--;
+ }
+
+ rl_point = p;
+ return (0);
+}
+
+static int
+bash_backward_shellword (count, key)
+ int count, key;
+{
+ size_t slen;
+ int sindex, c, p;
+ DECLARE_MBSTATE;
+
+ if (count < 0)
+ return (bash_forward_shellword (-count, key));
+
+ p = rl_point;
+ slen = rl_end;
+
+ while (count)
+ {
+ if (p == 0)
+ {
+ rl_point = 0;
+ return 0;
+ }
+
+ /* Move backward until we hit a non-metacharacter. */
+ while (p > 0)
+ {
+ c = rl_line_buffer[p];
+ if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0)
+ BACKUP_CHAR (rl_line_buffer, slen, p);
+ break;
+ }
+
+ if (p == 0)
+ {
+ rl_point = 0;
+ return 0;
+ }
+
+ /* Now move backward until we hit a metacharacter or BOL. */
+ while (p > 0)
+ {
+ c = rl_line_buffer[p];
+ if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0)
+ break;
+ BACKUP_CHAR (rl_line_buffer, slen, p);
+ }
+
+ count--;
+ }
+
+ rl_point = p;
+ return 0;
+}
+
+static int
+bash_kill_shellword (count, key)
+ int count, key;
+{
+ int p;
+
+ if (count < 0)
+ return (bash_backward_kill_shellword (-count, key));
+
+ p = rl_point;
+ bash_forward_shellword (count, key);
+
+ if (rl_point != p)
+ rl_kill_text (p, rl_point);
+
+ rl_point = p;
+ if (rl_editing_mode == 1) /* 1 == emacs_mode */
+ rl_mark = rl_point;
+
+ return 0;
+}
+
+static int
+bash_backward_kill_shellword (count, key)
+ int count, key;
+{
+ int p;
+
+ if (count < 0)
+ return (bash_kill_shellword (-count, key));
+
+ p = rl_point;
+ bash_backward_shellword (count, key);
+
+ if (rl_point != p)
+ rl_kill_text (p, rl_point);
+
+ if (rl_editing_mode == 1) /* 1 == emacs_mode */
+ rl_mark = rl_point;
+
+ return 0;
+}
+
+
+/* **************************************************************** */
+/* */
+/* How To Do Shell Completion */
+/* */
+/* **************************************************************** */
+
+#define COMMAND_SEPARATORS ";|&{(`"
+/* )} */
+#define COMMAND_SEPARATORS_PLUS_WS ";|&{(` \t"
+/* )} */
+
+/* check for redirections and other character combinations that are not
+ command separators */
+static int
+check_redir (ti)
+ int ti;
+{
+ register int this_char, prev_char;
+
+ /* Handle the two character tokens `>&', `<&', and `>|'.
+ We are not in a command position after one of these. */
+ this_char = rl_line_buffer[ti];
+ prev_char = rl_line_buffer[ti - 1];
+
+ if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
+ (this_char == '|' && prev_char == '>'))
+ return (1);
+ else if (this_char == '{' && prev_char == '$') /*}*/
+ return (1);
+#if 0 /* Not yet */
+ else if (this_char == '(' && prev_char == '$') /*)*/
+ return (1);
+ else if (this_char == '(' && prev_char == '<') /*)*/
+ return (1);
+#if defined (EXTENDED_GLOB)
+ else if (extended_glob && this_char == '(' && prev_char == '!') /*)*/
+ return (1);
+#endif
+#endif
+ else if (char_is_quoted (rl_line_buffer, ti))
+ return (1);
+ return (0);
+}
+
+#if defined (PROGRAMMABLE_COMPLETION)
+/*
+ * XXX - because of the <= start test, and setting os = s+1, this can
+ * potentially return os > start. This is probably not what we want to
+ * happen, but fix later after 2.05a-release.
+ */
+static int
+find_cmd_start (start)
+ int start;
+{
+ register int s, os;
+
+ os = 0;
+ /* Flags == SD_NOJMP only because we want to skip over command substitutions
+ in assignment statements. Have to test whether this affects `standalone'
+ command substitutions as individual words. */
+ while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS, SD_NOJMP/*|SD_NOSKIPCMD*/)) <= start) &&
+ rl_line_buffer[s])
+ os = s+1;
+ return os;
+}
+
+static int
+find_cmd_end (end)
+ int end;
+{
+ register int e;
+
+ e = skip_to_delim (rl_line_buffer, end, COMMAND_SEPARATORS, SD_NOJMP);
+ return e;
+}
+
+static char *
+find_cmd_name (start, sp, ep)
+ int start;
+ int *sp, *ep;
+{
+ char *name;
+ register int s, e;
+
+ for (s = start; whitespace (rl_line_buffer[s]); s++)
+ ;
+
+ /* skip until a shell break character */
+ e = skip_to_delim (rl_line_buffer, s, "()<>;&| \t\n", SD_NOJMP);
+
+ name = substring (rl_line_buffer, s, e);
+
+ if (sp)
+ *sp = s;
+ if (ep)
+ *ep = e;
+
+ return (name);
+}
+
+static char *
+prog_complete_return (text, matchnum)
+ const char *text;
+ int matchnum;
+{
+ static int ind;
+
+ if (matchnum == 0)
+ ind = 0;
+
+ if (prog_complete_matches == 0 || prog_complete_matches[ind] == 0)
+ return (char *)NULL;
+ return (prog_complete_matches[ind++]);
+}
+
+#endif /* PROGRAMMABLE_COMPLETION */
+
+/* Do some completion on TEXT. The indices of TEXT in RL_LINE_BUFFER are
+ at START and END. Return an array of matches, or NULL if none. */
+static char **
+attempt_shell_completion (text, start, end)
+ const char *text;
+ int start, end;
+{
+ int in_command_position, ti, saveti, qc, dflags;
+ char **matches, *command_separator_chars;
+
+ command_separator_chars = COMMAND_SEPARATORS;
+ matches = (char **)NULL;
+ rl_ignore_some_completions_function = filename_completion_ignore;
+
+ rl_filename_quote_characters = default_filename_quote_characters;
+ set_filename_bstab (rl_filename_quote_characters);
+ set_directory_hook ();
+ rl_filename_stat_hook = bash_filename_stat_hook;
+
+ /* Determine if this could be a command word. It is if it appears at
+ the start of the line (ignoring preceding whitespace), or if it
+ appears after a character that separates commands. It cannot be a
+ command word if we aren't at the top-level prompt. */
+ ti = start - 1;
+ saveti = qc = -1;
+
+ while ((ti > -1) && (whitespace (rl_line_buffer[ti])))
+ ti--;
+
+#if 1
+ /* If this is an open quote, maybe we're trying to complete a quoted
+ command name. */
+ if (ti >= 0 && (rl_line_buffer[ti] == '"' || rl_line_buffer[ti] == '\''))
+ {
+ qc = rl_line_buffer[ti];
+ saveti = ti--;
+ while (ti > -1 && (whitespace (rl_line_buffer[ti])))
+ ti--;
+ }
+#endif
+
+ in_command_position = 0;
+ if (ti < 0)
+ {
+ /* Only do command completion at the start of a line when we
+ are prompting at the top level. */
+ if (current_prompt_string == ps1_prompt)
+ in_command_position++;
+ else if (parser_in_command_position ())
+ in_command_position++;
+ }
+ else if (member (rl_line_buffer[ti], command_separator_chars))
+ {
+ in_command_position++;
+
+ if (check_redir (ti) == 1)
+ in_command_position = 0;
+ }
+ else
+ {
+ /* This still could be in command position. It is possible
+ that all of the previous words on the line are variable
+ assignments. */
+ }
+
+ /* Check that we haven't incorrectly flagged a closed command substitution
+ as indicating we're in a command position. */
+ if (in_command_position && ti >= 0 && rl_line_buffer[ti] == '`' &&
+ *text != '`' && unclosed_pair (rl_line_buffer, end, "`") == 0)
+ in_command_position = 0;
+
+ /* Special handling for command substitution. If *TEXT is a backquote,
+ it can be the start or end of an old-style command substitution, or
+ unmatched. If it's unmatched, both calls to unclosed_pair will
+ succeed. Don't bother if readline found a single quote and we are
+ completing on the substring. */
+ if (*text == '`' && rl_completion_quote_character != '\'' &&
+ (in_command_position || (unclosed_pair (rl_line_buffer, start, "`") &&
+ unclosed_pair (rl_line_buffer, end, "`"))))
+ matches = rl_completion_matches (text, command_subst_completion_function);
+
+#if defined (PROGRAMMABLE_COMPLETION)
+ /* Attempt programmable completion. */
+ if (matches == 0 && (in_command_position == 0 || text[0] == '\0') &&
+ prog_completion_enabled && (progcomp_size () > 0) &&
+ current_prompt_string == ps1_prompt)
+ {
+ int s, e, s1, e1, os, foundcs;
+ char *n;
+
+ /* XXX - don't free the members */
+ if (prog_complete_matches)
+ free (prog_complete_matches);
+ prog_complete_matches = (char **)NULL;
+
+ os = start;
+ n = 0;
+ s = find_cmd_start (os);
+ e = find_cmd_end (end);
+ do
+ {
+ /* Skip over assignment statements preceding a command name. If we
+ don't find a command name at all, we can perform command name
+ completion. If we find a partial command name, we should perform
+ command name completion on it. */
+ FREE (n);
+ n = find_cmd_name (s, &s1, &e1);
+ s = e1 + 1;
+ }
+ while (assignment (n, 0));
+ s = s1; /* reset to index where name begins */
+
+ if (start == 0 && end == 0 && e != 0 && text[0] == '\0') /* beginning of non-empty line */
+ foundcs = 0;
+ else if (start == end && start == s1 && e != 0 && e1 > end) /* beginning of command name, leading whitespace */
+ foundcs = 0;
+ else if (e == 0 && e == s && text[0] == '\0') /* beginning of empty line */
+ prog_complete_matches = programmable_completions ("_EmptycmD_", text, s, e, &foundcs);
+ else if (start == end && text[0] == '\0' && s1 > start && whitespace (rl_line_buffer[start]))
+ foundcs = 0; /* whitespace before command name */
+ else if (e > s && assignment (n, 0) == 0)
+ prog_complete_matches = programmable_completions (n, text, s, e, &foundcs);
+ else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0)
+ {
+ foundcs = 0; /* empty command name following assignments */
+ in_command_position = 1;
+ }
+ else if (s == start && e == end && STREQ (n, text) && start > 0)
+ {
+ foundcs = 0; /* partial command name following assignments */
+ in_command_position = 1;
+ }
+ else
+ foundcs = 0;
+ FREE (n);
+ /* XXX - if we found a COMPSPEC for the command, just return whatever
+ the programmable completion code returns, and disable the default
+ filename completion that readline will do unless the COPT_DEFAULT
+ option has been set with the `-o default' option to complete or
+ compopt. */
+ if (foundcs)
+ {
+ pcomp_set_readline_variables (foundcs, 1);
+ /* Turn what the programmable completion code returns into what
+ readline wants. I should have made compute_lcd_of_matches
+ external... */
+ matches = rl_completion_matches (text, prog_complete_return);
+ if ((foundcs & COPT_DEFAULT) == 0)
+ rl_attempted_completion_over = 1; /* no default */
+ if (matches || ((foundcs & COPT_BASHDEFAULT) == 0))
+ return (matches);
+ }
+ }
+#endif
+
+ if (matches == 0)
+ {
+ dflags = 0;
+ if (in_command_position)
+ dflags |= DEFCOMP_CMDPOS;
+ matches = bash_default_completion (text, start, end, qc, dflags);
+ }
+
+ return matches;
+}
+
+char **
+bash_default_completion (text, start, end, qc, compflags)
+ const char *text;
+ int start, end, qc, compflags;
+{
+ char **matches, *t;
+
+ matches = (char **)NULL;
+
+ /* New posix-style command substitution or variable name? */
+ if (!matches && *text == '$')
+ {
+ if (qc != '\'' && text[1] == '(') /* ) */
+ matches = rl_completion_matches (text, command_subst_completion_function);
+ else
+ {
+ matches = rl_completion_matches (text, variable_completion_function);
+ if (matches && matches[0] && matches[1] == 0)
+ {
+ t = savestring (matches[0]);
+ bash_filename_stat_hook (&t);
+ /* doesn't use test_for_directory because that performs tilde
+ expansion */
+ if (file_isdir (t))
+ rl_completion_append_character = '/';
+ free (t);
+ }
+ }
+ }
+
+ /* If the word starts in `~', and there is no slash in the word, then
+ try completing this word as a username. */
+ if (matches == 0 && *text == '~' && mbschr (text, '/') == 0)
+ matches = rl_completion_matches (text, rl_username_completion_function);
+
+ /* Another one. Why not? If the word starts in '@', then look through
+ the world of known hostnames for completion first. */
+ if (matches == 0 && perform_hostname_completion && *text == '@')
+ matches = rl_completion_matches (text, hostname_completion_function);
+
+ /* And last, (but not least) if this word is in a command position, then
+ complete over possible command names, including aliases, functions,
+ and command names. */
+ if (matches == 0 && (compflags & DEFCOMP_CMDPOS))
+ {
+ /* If END == START and text[0] == 0, we are trying to complete an empty
+ command word. */
+ if (no_empty_command_completion && end == start && text[0] == '\0')
+ {
+ matches = (char **)NULL;
+ rl_ignore_some_completions_function = bash_ignore_everything;
+ }
+ else
+ {
+#define CMD_IS_DIR(x) (absolute_pathname(x) == 0 && absolute_program(x) == 0 && *(x) != '~' && test_for_directory (x))
+
+ dot_in_path = 0;
+ matches = rl_completion_matches (text, command_word_completion_function);
+
+ /* If we are attempting command completion and nothing matches, we
+ do not want readline to perform filename completion for us. We
+ still want to be able to complete partial pathnames, so set the
+ completion ignore function to something which will remove
+ filenames and leave directories in the match list. */
+ if (matches == (char **)NULL)
+ rl_ignore_some_completions_function = bash_ignore_filenames;
+ else if (matches[1] == 0 && CMD_IS_DIR(matches[0]) && dot_in_path == 0)
+ /* If we found a single match, without looking in the current
+ directory (because it's not in $PATH), but the found name is
+ also a command in the current directory, suppress appending any
+ terminating character, since it's ambiguous. */
+ {
+ rl_completion_suppress_append = 1;
+ rl_filename_completion_desired = 0;
+ }
+ else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) && CMD_IS_DIR (matches[0]))
+ /* There are multiple instances of the same match (duplicate
+ completions haven't yet been removed). In this case, all of
+ the matches will be the same, and the duplicate removal code
+ will distill them all down to one. We turn on
+ rl_completion_suppress_append for the same reason as above.
+ Remember: we only care if there's eventually a single unique
+ completion. If there are multiple completions this won't
+ make a difference and the problem won't occur. */
+ {
+ rl_completion_suppress_append = 1;
+ rl_filename_completion_desired = 0;
+ }
+ }
+ }
+
+ /* This could be a globbing pattern, so try to expand it using pathname
+ expansion. */
+ if (!matches && glob_pattern_p (text))
+ {
+ matches = rl_completion_matches (text, glob_complete_word);
+ /* A glob expression that matches more than one filename is problematic.
+ If we match more than one filename, punt. */
+ if (matches && matches[1] && rl_completion_type == TAB)
+ {
+ strvec_dispose (matches);
+ matches = (char **)0;
+ }
+ else if (matches && matches[1] && rl_completion_type == '!')
+ {
+ rl_completion_suppress_append = 1;
+ rl_filename_completion_desired = 0;
+ }
+ }
+
+ return (matches);
+}
+
+static int
+bash_command_name_stat_hook (name)
+ char **name;
+{
+ char *cname, *result;
+
+ cname = *name;
+ /* XXX - we could do something here with converting aliases, builtins,
+ and functions into something that came out as executable, but we don't. */
+ result = search_for_command (cname, 0);
+ if (result)
+ {
+ *name = result;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+executable_completion (filename, searching_path)
+ const char *filename;
+ int searching_path;
+{
+ char *f;
+ int r;
+
+ f = savestring (filename);
+ bash_directory_completion_hook (&f);
+
+ r = searching_path ? executable_file (f) : executable_or_directory (f);
+ free (f);
+ return r;
+}
+
+/* This is the function to call when the word to complete is in a position
+ where a command word can be found. It grovels $PATH, looking for commands
+ that match. It also scans aliases, function names, and the shell_builtin
+ table. */
+char *
+command_word_completion_function (hint_text, state)
+ const char *hint_text;
+ int state;
+{
+ static char *hint = (char *)NULL;
+ static char *path = (char *)NULL;
+ static char *val = (char *)NULL;
+ static char *filename_hint = (char *)NULL;
+ static char *dequoted_hint = (char *)NULL;
+ static char *directory_part = (char *)NULL;
+ static char **glob_matches = (char **)NULL;
+ static int path_index, hint_len, dequoted_len, istate, igncase;
+ static int mapping_over, local_index, searching_path, hint_is_dir;
+ static int old_glob_ignore_case, globpat;
+ static SHELL_VAR **varlist = (SHELL_VAR **)NULL;
+#if defined (ALIAS)
+ static alias_t **alias_list = (alias_t **)NULL;
+#endif /* ALIAS */
+ char *temp, *cval;
+
+ /* We have to map over the possibilities for command words. If we have
+ no state, then make one just for that purpose. */
+ if (state == 0)
+ {
+ rl_filename_stat_hook = bash_command_name_stat_hook;
+
+ if (dequoted_hint && dequoted_hint != hint)
+ free (dequoted_hint);
+ if (hint)
+ free (hint);
+
+ mapping_over = searching_path = 0;
+ hint_is_dir = CMD_IS_DIR (hint_text);
+ val = (char *)NULL;
+
+ temp = rl_variable_value ("completion-ignore-case");
+ igncase = RL_BOOLEAN_VARIABLE_VALUE (temp);
+
+ if (glob_matches)
+ {
+ free (glob_matches);
+ glob_matches = (char **)NULL;
+ }
+
+ globpat = glob_pattern_p (hint_text);
+
+ /* If this is an absolute program name, do not check it against
+ aliases, reserved words, functions or builtins. We must check
+ whether or not it is unique, and, if so, whether that filename
+ is executable. */
+ if (globpat || absolute_program (hint_text))
+ {
+ /* Perform tilde expansion on what's passed, so we don't end up
+ passing filenames with tildes directly to stat(). */
+ if (*hint_text == '~')
+ {
+ hint = bash_tilde_expand (hint_text, 0);
+ directory_part = savestring (hint_text);
+ temp = strchr (directory_part, '/');
+ if (temp)
+ *temp = 0;
+ else
+ {
+ free (directory_part);
+ directory_part = (char *)NULL;
+ }
+ }
+ else
+ hint = savestring (hint_text);
+
+ dequoted_hint = hint;
+ /* If readline's completer found a quote character somewhere, but
+ didn't set the quote character, there must have been a quote
+ character embedded in the filename. It can't be at the start of
+ the filename, so we need to dequote the filename before we look
+ in the file system for it. */
+ if (rl_completion_found_quote && rl_completion_quote_character == 0)
+ {
+ dequoted_hint = bash_dequote_filename (hint, 0);
+ free (hint);
+ hint = dequoted_hint;
+ }
+ dequoted_len = hint_len = strlen (hint);
+
+ if (filename_hint)
+ free (filename_hint);
+
+ filename_hint = savestring (hint);
+
+ istate = 0;
+
+ if (globpat)
+ {
+ mapping_over = 5;
+ goto globword;
+ }
+ else
+ {
+ if (dircomplete_expand && path_dot_or_dotdot (filename_hint))
+ {
+ dircomplete_expand = 0;
+ set_directory_hook ();
+ dircomplete_expand = 1;
+ }
+ mapping_over = 4;
+ goto inner;
+ }
+ }
+
+ dequoted_hint = hint = savestring (hint_text);
+ dequoted_len = hint_len = strlen (hint);
+
+ if (rl_completion_found_quote && rl_completion_quote_character == 0)
+ {
+ dequoted_hint = bash_dequote_filename (hint, 0);
+ dequoted_len = strlen (dequoted_hint);
+ }
+
+ path = get_string_value ("PATH");
+ path_index = dot_in_path = 0;
+
+ /* Initialize the variables for each type of command word. */
+ local_index = 0;
+
+ if (varlist)
+ free (varlist);
+
+ varlist = all_visible_functions ();
+
+#if defined (ALIAS)
+ if (alias_list)
+ free (alias_list);
+
+ alias_list = all_aliases ();
+#endif /* ALIAS */
+ }
+
+ /* mapping_over says what we are currently hacking. Note that every case
+ in this list must fall through when there are no more possibilities. */
+
+ switch (mapping_over)
+ {
+ case 0: /* Aliases come first. */
+#if defined (ALIAS)
+ while (alias_list && alias_list[local_index])
+ {
+ register char *alias;
+
+ alias = alias_list[local_index++]->name;
+
+ if (STREQN (alias, hint, hint_len))
+ return (savestring (alias));
+ }
+#endif /* ALIAS */
+ local_index = 0;
+ mapping_over++;
+
+ case 1: /* Then shell reserved words. */
+ {
+ while (word_token_alist[local_index].word)
+ {
+ register char *reserved_word;
+
+ reserved_word = word_token_alist[local_index++].word;
+
+ if (STREQN (reserved_word, hint, hint_len))
+ return (savestring (reserved_word));
+ }
+ local_index = 0;
+ mapping_over++;
+ }
+
+ case 2: /* Then function names. */
+ while (varlist && varlist[local_index])
+ {
+ register char *varname;
+
+ varname = varlist[local_index++]->name;
+
+ if (STREQN (varname, hint, hint_len))
+ return (savestring (varname));
+ }
+ local_index = 0;
+ mapping_over++;
+
+ case 3: /* Then shell builtins. */
+ for (; local_index < num_shell_builtins; local_index++)
+ {
+ /* Ignore it if it doesn't have a function pointer or if it
+ is not currently enabled. */
+ if (!shell_builtins[local_index].function ||
+ (shell_builtins[local_index].flags & BUILTIN_ENABLED) == 0)
+ continue;
+
+ if (STREQN (shell_builtins[local_index].name, hint, hint_len))
+ {
+ int i = local_index++;
+
+ return (savestring (shell_builtins[i].name));
+ }
+ }
+ local_index = 0;
+ mapping_over++;
+ }
+
+globword:
+ /* Limited support for completing command words with globbing chars. Only
+ a single match (multiple matches that end up reducing the number of
+ characters in the common prefix are bad) will ever be returned on
+ regular completion. */
+ if (globpat)
+ {
+ if (state == 0)
+ {
+ glob_ignore_case = igncase;
+ glob_matches = shell_glob_filename (hint);
+ glob_ignore_case = old_glob_ignore_case;
+
+ if (GLOB_FAILED (glob_matches) || glob_matches == 0)
+ {
+ glob_matches = (char **)NULL;
+ return ((char *)NULL);
+ }
+
+ local_index = 0;
+
+ if (glob_matches[1] && rl_completion_type == TAB) /* multiple matches are bad */
+ return ((char *)NULL);
+ }
+
+ while (val = glob_matches[local_index++])
+ {
+ if (executable_or_directory (val))
+ {
+ if (*hint_text == '~' && directory_part)
+ {
+ temp = restore_tilde (val, directory_part);
+ free (val);
+ val = temp;
+ }
+ return (val);
+ }
+ free (val);
+ }
+
+ glob_ignore_case = old_glob_ignore_case;
+ return ((char *)NULL);
+ }
+
+ /* If the text passed is a directory in the current directory, return it
+ as a possible match. Executables in directories in the current
+ directory can be specified using relative pathnames and successfully
+ executed even when `.' is not in $PATH. */
+ if (hint_is_dir)
+ {
+ hint_is_dir = 0; /* only return the hint text once */
+ return (savestring (hint_text));
+ }
+
+ /* Repeatedly call filename_completion_function while we have
+ members of PATH left. Question: should we stat each file?
+ Answer: we call executable_file () on each file. */
+ outer:
+
+ istate = (val != (char *)NULL);
+
+ if (istate == 0)
+ {
+ char *current_path;
+
+ /* Get the next directory from the path. If there is none, then we
+ are all done. */
+ if (path == 0 || path[path_index] == 0 ||
+ (current_path = extract_colon_unit (path, &path_index)) == 0)
+ return ((char *)NULL);
+
+ searching_path = 1;
+ if (*current_path == 0)
+ {
+ free (current_path);
+ current_path = savestring (".");
+ }
+
+ if (*current_path == '~')
+ {
+ char *t;
+
+ t = bash_tilde_expand (current_path, 0);
+ free (current_path);
+ current_path = t;
+ }
+
+ if (current_path[0] == '.' && current_path[1] == '\0')
+ dot_in_path = 1;
+
+ if (filename_hint)
+ free (filename_hint);
+
+ filename_hint = sh_makepath (current_path, hint, 0);
+ free (current_path); /* XXX */
+ }
+
+ inner:
+ val = rl_filename_completion_function (filename_hint, istate);
+ if (mapping_over == 4 && dircomplete_expand)
+ set_directory_hook ();
+
+ istate = 1;
+
+ if (val == 0)
+ {
+ /* If the hint text is an absolute program, then don't bother
+ searching through PATH. */
+ if (absolute_program (hint))
+ return ((char *)NULL);
+
+ goto outer;
+ }
+ else
+ {
+ int match, freetemp;
+
+ if (absolute_program (hint))
+ {
+ if (igncase == 0)
+ match = strncmp (val, hint, hint_len) == 0;
+ else
+ match = strncasecmp (val, hint, hint_len) == 0;
+
+ /* If we performed tilde expansion, restore the original
+ filename. */
+ if (*hint_text == '~')
+ temp = restore_tilde (val, directory_part);
+ else
+ temp = savestring (val);
+ freetemp = 1;
+ }
+ else
+ {
+ temp = strrchr (val, '/');
+
+ if (temp)
+ {
+ temp++;
+ if (igncase == 0)
+ freetemp = match = strncmp (temp, hint, hint_len) == 0;
+ else
+ freetemp = match = strncasecmp (temp, hint, hint_len) == 0;
+ if (match)
+ temp = savestring (temp);
+ }
+ else
+ freetemp = match = 0;
+ }
+
+ /* If we have found a match, and it is an executable file, return it.
+ We don't return directory names when searching $PATH, since the
+ bash execution code won't find executables in directories which
+ appear in directories in $PATH when they're specified using
+ relative pathnames. */
+#if 0
+ /* If we're not searching $PATH and we have a relative pathname, we
+ need to re-canonicalize it before testing whether or not it's an
+ executable or a directory so the shell treats .. relative to $PWD
+ according to the physical/logical option. The shell already
+ canonicalizes the directory name in order to tell readline where
+ to look, so not doing it here will be inconsistent. */
+ /* XXX -- currently not used -- will introduce more inconsistency,
+ since shell does not canonicalize ../foo before passing it to
+ shell_execve(). */
+ if (match && searching_path == 0 && *val == '.')
+ {
+ char *t, *t1;
+
+ t = get_working_directory ("command-word-completion");
+ t1 = make_absolute (val, t);
+ free (t);
+ cval = sh_canonpath (t1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+ }
+ else
+#endif
+ cval = val;
+
+ if (match && executable_completion ((searching_path ? val : cval), searching_path))
+ {
+ if (cval != val)
+ free (cval);
+ free (val);
+ val = ""; /* So it won't be NULL. */
+ return (temp);
+ }
+ else
+ {
+ if (freetemp)
+ free (temp);
+ if (cval != val)
+ free (cval);
+ free (val);
+ goto inner;
+ }
+ }
+}
+
+/* Completion inside an unterminated command substitution. */
+static char *
+command_subst_completion_function (text, state)
+ const char *text;
+ int state;
+{
+ static char **matches = (char **)NULL;
+ static const char *orig_start;
+ static char *filename_text = (char *)NULL;
+ static int cmd_index, start_len;
+ char *value;
+
+ if (state == 0)
+ {
+ if (filename_text)
+ free (filename_text);
+ orig_start = text;
+ if (*text == '`')
+ text++;
+ else if (*text == '$' && text[1] == '(') /* ) */
+ text += 2;
+ /* If the text was quoted, suppress any quote character that the
+ readline completion code would insert. */
+ rl_completion_suppress_quote = 1;
+ start_len = text - orig_start;
+ filename_text = savestring (text);
+ if (matches)
+ free (matches);
+
+ /*
+ * At this point we can entertain the idea of re-parsing
+ * `filename_text' into a (possibly incomplete) command name and
+ * arguments, and doing completion based on that. This is
+ * currently very rudimentary, but it is a small improvement.
+ */
+ for (value = filename_text + strlen (filename_text) - 1; value > filename_text; value--)
+ if (whitespace (*value) || member (*value, COMMAND_SEPARATORS))
+ break;
+ if (value <= filename_text)
+ matches = rl_completion_matches (filename_text, command_word_completion_function);
+ else
+ {
+ value++;
+ start_len += value - filename_text;
+ if (whitespace (value[-1]))
+ matches = rl_completion_matches (value, rl_filename_completion_function);
+ else
+ matches = rl_completion_matches (value, command_word_completion_function);
+ }
+
+ /* If there is more than one match, rl_completion_matches has already
+ put the lcd in matches[0]. Skip over it. */
+ cmd_index = matches && matches[0] && matches[1];
+
+ /* If there's a single match and it's a directory, set the append char
+ to the expected `/'. Otherwise, don't append anything. */
+ if (matches && matches[0] && matches[1] == 0 && test_for_directory (matches[0]))
+ rl_completion_append_character = '/';
+ else
+ rl_completion_suppress_append = 1;
+ }
+
+ if (matches == 0 || matches[cmd_index] == 0)
+ {
+ rl_filename_quoting_desired = 0; /* disable quoting */
+ return ((char *)NULL);
+ }
+ else
+ {
+ value = (char *)xmalloc (1 + start_len + strlen (matches[cmd_index]));
+
+ if (start_len == 1)
+ value[0] = *orig_start;
+ else
+ strncpy (value, orig_start, start_len);
+
+ strcpy (value + start_len, matches[cmd_index]);
+
+ cmd_index++;
+ return (value);
+ }
+}
+
+/* Okay, now we write the entry_function for variable completion. */
+static char *
+variable_completion_function (text, state)
+ const char *text;
+ int state;
+{
+ static char **varlist = (char **)NULL;
+ static int varlist_index;
+ static char *varname = (char *)NULL;
+ static int namelen;
+ static int first_char, first_char_loc;
+
+ if (!state)
+ {
+ if (varname)
+ free (varname);
+
+ first_char_loc = 0;
+ first_char = text[0];
+
+ if (first_char == '$')
+ first_char_loc++;
+
+ if (text[first_char_loc] == '{')
+ first_char_loc++;
+
+ varname = savestring (text + first_char_loc);
+
+ namelen = strlen (varname);
+ if (varlist)
+ strvec_dispose (varlist);
+
+ varlist = all_variables_matching_prefix (varname);
+ varlist_index = 0;
+ }
+
+ if (!varlist || !varlist[varlist_index])
+ {
+ return ((char *)NULL);
+ }
+ else
+ {
+ char *value;
+
+ value = (char *)xmalloc (4 + strlen (varlist[varlist_index]));
+
+ if (first_char_loc)
+ {
+ value[0] = first_char;
+ if (first_char_loc == 2)
+ value[1] = '{';
+ }
+
+ strcpy (value + first_char_loc, varlist[varlist_index]);
+ if (first_char_loc == 2)
+ strcat (value, "}");
+
+ varlist_index++;
+ return (value);
+ }
+}
+
+/* How about a completion function for hostnames? */
+static char *
+hostname_completion_function (text, state)
+ const char *text;
+ int state;
+{
+ static char **list = (char **)NULL;
+ static int list_index = 0;
+ static int first_char, first_char_loc;
+
+ /* If we don't have any state, make some. */
+ if (state == 0)
+ {
+ FREE (list);
+
+ list = (char **)NULL;
+
+ first_char_loc = 0;
+ first_char = *text;
+
+ if (first_char == '@')
+ first_char_loc++;
+
+ list = hostnames_matching ((char *)text+first_char_loc);
+ list_index = 0;
+ }
+
+ if (list && list[list_index])
+ {
+ char *t;
+
+ t = (char *)xmalloc (2 + strlen (list[list_index]));
+ *t = first_char;
+ strcpy (t + first_char_loc, list[list_index]);
+ list_index++;
+ return (t);
+ }
+
+ return ((char *)NULL);
+}
+
+/*
+ * A completion function for service names from /etc/services (or wherever).
+ */
+char *
+bash_servicename_completion_function (text, state)
+ const char *text;
+ int state;
+{
+#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GETSERVENT)
+ return ((char *)NULL);
+#else
+ static char *sname = (char *)NULL;
+ static struct servent *srvent;
+ static int snamelen, firstc;
+ char *value;
+ char **alist, *aentry;
+ int afound;
+
+ if (state == 0)
+ {
+ FREE (sname);
+ firstc = *text;
+
+ sname = savestring (text);
+ snamelen = strlen (sname);
+ setservent (0);
+ }
+
+ while (srvent = getservent ())
+ {
+ afound = 0;
+ if (snamelen == 0 || (STREQN (sname, srvent->s_name, snamelen)))
+ break;
+ /* Not primary, check aliases */
+ for (alist = srvent->s_aliases; *alist; alist++)
+ {
+ aentry = *alist;
+ if (STREQN (sname, aentry, snamelen))
+ {
+ afound = 1;
+ break;
+ }
+ }
+
+ if (afound)
+ break;
+ }
+
+ if (srvent == 0)
+ {
+ endservent ();
+ return ((char *)NULL);
+ }
+
+ value = afound ? savestring (aentry) : savestring (srvent->s_name);
+ return value;
+#endif
+}
+
+/*
+ * A completion function for group names from /etc/group (or wherever).
+ */
+char *
+bash_groupname_completion_function (text, state)
+ const char *text;
+ int state;
+{
+#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GRP_H)
+ return ((char *)NULL);
+#else
+ static char *gname = (char *)NULL;
+ static struct group *grent;
+ static int gnamelen;
+ char *value;
+
+ if (state == 0)
+ {
+ FREE (gname);
+ gname = savestring (text);
+ gnamelen = strlen (gname);
+
+ setgrent ();
+ }
+
+ while (grent = getgrent ())
+ {
+ if (gnamelen == 0 || (STREQN (gname, grent->gr_name, gnamelen)))
+ break;
+ }
+
+ if (grent == 0)
+ {
+ endgrent ();
+ return ((char *)NULL);
+ }
+
+ value = savestring (grent->gr_name);
+ return (value);
+#endif
+}
+
+/* Functions to perform history and alias expansions on the current line. */
+
+#if defined (BANG_HISTORY)
+/* Perform history expansion on the current line. If no history expansion
+ is done, pre_process_line() returns what it was passed, so we need to
+ allocate a new line here. */
+static char *
+history_expand_line_internal (line)
+ char *line;
+{
+ char *new_line;
+ int old_verify;
+
+ old_verify = hist_verify;
+ hist_verify = 0;
+ new_line = pre_process_line (line, 0, 0);
+ hist_verify = old_verify;
+
+ return (new_line == line) ? savestring (line) : new_line;
+}
+#endif
+
+/* There was an error in expansion. Let the preprocessor print
+ the error here. */
+static void
+cleanup_expansion_error ()
+{
+ char *to_free;
+#if defined (BANG_HISTORY)
+ int old_verify;
+
+ old_verify = hist_verify;
+ hist_verify = 0;
+#endif
+
+ fprintf (rl_outstream, "\r\n");
+ to_free = pre_process_line (rl_line_buffer, 1, 0);
+#if defined (BANG_HISTORY)
+ hist_verify = old_verify;
+#endif
+ if (to_free != rl_line_buffer)
+ FREE (to_free);
+ putc ('\r', rl_outstream);
+ rl_forced_update_display ();
+}
+
+/* If NEW_LINE differs from what is in the readline line buffer, add an
+ undo record to get from the readline line buffer contents to the new
+ line and make NEW_LINE the current readline line. */
+static void
+maybe_make_readline_line (new_line)
+ char *new_line;
+{
+ if (strcmp (new_line, rl_line_buffer) != 0)
+ {
+ rl_point = rl_end;
+
+ rl_add_undo (UNDO_BEGIN, 0, 0, 0);
+ rl_delete_text (0, rl_point);
+ rl_point = rl_end = rl_mark = 0;
+ rl_insert_text (new_line);
+ rl_add_undo (UNDO_END, 0, 0, 0);
+ }
+}
+
+/* Make NEW_LINE be the current readline line. This frees NEW_LINE. */
+static void
+set_up_new_line (new_line)
+ char *new_line;
+{
+ int old_point, at_end;
+
+ old_point = rl_point;
+ at_end = rl_point == rl_end;
+
+ /* If the line was history and alias expanded, then make that
+ be one thing to undo. */
+ maybe_make_readline_line (new_line);
+ free (new_line);
+
+ /* Place rl_point where we think it should go. */
+ if (at_end)
+ rl_point = rl_end;
+ else if (old_point < rl_end)
+ {
+ rl_point = old_point;
+ if (!whitespace (rl_line_buffer[rl_point]))
+ rl_forward_word (1, 0);
+ }
+}
+
+#if defined (ALIAS)
+/* Expand aliases in the current readline line. */
+static int
+alias_expand_line (count, ignore)
+ int count, ignore;
+{
+ char *new_line;
+
+ new_line = alias_expand (rl_line_buffer);
+
+ if (new_line)
+ {
+ set_up_new_line (new_line);
+ return (0);
+ }
+ else
+ {
+ cleanup_expansion_error ();
+ return (1);
+ }
+}
+#endif
+
+#if defined (BANG_HISTORY)
+/* History expand the line. */
+static int
+history_expand_line (count, ignore)
+ int count, ignore;
+{
+ char *new_line;
+
+ new_line = history_expand_line_internal (rl_line_buffer);
+
+ if (new_line)
+ {
+ set_up_new_line (new_line);
+ return (0);
+ }
+ else
+ {
+ cleanup_expansion_error ();
+ return (1);
+ }
+}
+
+/* Expand history substitutions in the current line and then insert a
+ space (hopefully close to where we were before). */
+static int
+tcsh_magic_space (count, ignore)
+ int count, ignore;
+{
+ int dist_from_end, old_point;
+
+ old_point = rl_point;
+ dist_from_end = rl_end - rl_point;
+ if (history_expand_line (count, ignore) == 0)
+ {
+ /* Try a simple heuristic from Stephen Gildea <gildea@intouchsys.com>.
+ This works if all expansions were before rl_point or if no expansions
+ were performed. */
+ rl_point = (old_point == 0) ? old_point : rl_end - dist_from_end;
+ rl_insert (1, ' ');
+ return (0);
+ }
+ else
+ return (1);
+}
+#endif /* BANG_HISTORY */
+
+/* History and alias expand the line. */
+static int
+history_and_alias_expand_line (count, ignore)
+ int count, ignore;
+{
+ char *new_line;
+
+ new_line = 0;
+#if defined (BANG_HISTORY)
+ new_line = history_expand_line_internal (rl_line_buffer);
+#endif
+
+#if defined (ALIAS)
+ if (new_line)
+ {
+ char *alias_line;
+
+ alias_line = alias_expand (new_line);
+ free (new_line);
+ new_line = alias_line;
+ }
+#endif /* ALIAS */
+
+ if (new_line)
+ {
+ set_up_new_line (new_line);
+ return (0);
+ }
+ else
+ {
+ cleanup_expansion_error ();
+ return (1);
+ }
+}
+
+/* History and alias expand the line, then perform the shell word
+ expansions by calling expand_string. This can't use set_up_new_line()
+ because we want the variable expansions as a separate undo'able
+ set of operations. */
+static int
+shell_expand_line (count, ignore)
+ int count, ignore;
+{
+ char *new_line;
+ WORD_LIST *expanded_string;
+
+ new_line = 0;
+#if defined (BANG_HISTORY)
+ new_line = history_expand_line_internal (rl_line_buffer);
+#endif
+
+#if defined (ALIAS)
+ if (new_line)
+ {
+ char *alias_line;
+
+ alias_line = alias_expand (new_line);
+ free (new_line);
+ new_line = alias_line;
+ }
+#endif /* ALIAS */
+
+ if (new_line)
+ {
+ int old_point = rl_point;
+ int at_end = rl_point == rl_end;
+
+ /* If the line was history and alias expanded, then make that
+ be one thing to undo. */
+ maybe_make_readline_line (new_line);
+ free (new_line);
+
+ /* If there is variable expansion to perform, do that as a separate
+ operation to be undone. */
+ new_line = savestring (rl_line_buffer);
+ expanded_string = expand_string (new_line, 0);
+ FREE (new_line);
+ if (expanded_string == 0)
+ {
+ new_line = (char *)xmalloc (1);
+ new_line[0] = '\0';
+ }
+ else
+ {
+ new_line = string_list (expanded_string);
+ dispose_words (expanded_string);
+ }
+
+ maybe_make_readline_line (new_line);
+ free (new_line);
+
+ /* Place rl_point where we think it should go. */
+ if (at_end)
+ rl_point = rl_end;
+ else if (old_point < rl_end)
+ {
+ rl_point = old_point;
+ if (!whitespace (rl_line_buffer[rl_point]))
+ rl_forward_word (1, 0);
+ }
+ return 0;
+ }
+ else
+ {
+ cleanup_expansion_error ();
+ return 1;
+ }
+}
+
+/* If FIGNORE is set, then don't match files with the given suffixes when
+ completing filenames. If only one of the possibilities has an acceptable
+ suffix, delete the others, else just return and let the completer
+ signal an error. It is called by the completer when real
+ completions are done on filenames by the completer's internal
+ function, not for completion lists (M-?) and not on "other"
+ completion types, such as hostnames or commands. */
+
+static struct ignorevar fignore =
+{
+ "FIGNORE",
+ (struct ign *)0,
+ 0,
+ (char *)0,
+ (sh_iv_item_func_t *) 0,
+};
+
+static void
+_ignore_completion_names (names, name_func)
+ char **names;
+ sh_ignore_func_t *name_func;
+{
+ char **newnames;
+ int idx, nidx;
+ char **oldnames;
+ int oidx;
+
+ /* If there is only one completion, see if it is acceptable. If it is
+ not, free it up. In any case, short-circuit and return. This is a
+ special case because names[0] is not the prefix of the list of names
+ if there is only one completion; it is the completion itself. */
+ if (names[1] == (char *)0)
+ {
+ if (force_fignore)
+ if ((*name_func) (names[0]) == 0)
+ {
+ free (names[0]);
+ names[0] = (char *)NULL;
+ }
+
+ return;
+ }
+
+ /* Allocate space for array to hold list of pointers to matching
+ filenames. The pointers are copied back to NAMES when done. */
+ for (nidx = 1; names[nidx]; nidx++)
+ ;
+ newnames = strvec_create (nidx + 1);
+
+ if (force_fignore == 0)
+ {
+ oldnames = strvec_create (nidx - 1);
+ oidx = 0;
+ }
+
+ newnames[0] = names[0];
+ for (idx = nidx = 1; names[idx]; idx++)
+ {
+ if ((*name_func) (names[idx]))
+ newnames[nidx++] = names[idx];
+ else if (force_fignore == 0)
+ oldnames[oidx++] = names[idx];
+ else
+ free (names[idx]);
+ }
+
+ newnames[nidx] = (char *)NULL;
+
+ /* If none are acceptable then let the completer handle it. */
+ if (nidx == 1)
+ {
+ if (force_fignore)
+ {
+ free (names[0]);
+ names[0] = (char *)NULL;
+ }
+ else
+ free (oldnames);
+
+ free (newnames);
+ return;
+ }
+
+ if (force_fignore == 0)
+ {
+ while (oidx)
+ free (oldnames[--oidx]);
+ free (oldnames);
+ }
+
+ /* If only one is acceptable, copy it to names[0] and return. */
+ if (nidx == 2)
+ {
+ free (names[0]);
+ names[0] = newnames[1];
+ names[1] = (char *)NULL;
+ free (newnames);
+ return;
+ }
+
+ /* Copy the acceptable names back to NAMES, set the new array end,
+ and return. */
+ for (nidx = 1; newnames[nidx]; nidx++)
+ names[nidx] = newnames[nidx];
+ names[nidx] = (char *)NULL;
+ free (newnames);
+}
+
+static int
+name_is_acceptable (name)
+ const char *name;
+{
+ struct ign *p;
+ int nlen;
+
+ for (nlen = strlen (name), p = fignore.ignores; p->val; p++)
+ {
+ if (nlen > p->len && p->len > 0 && STREQ (p->val, &name[nlen - p->len]))
+ return (0);
+ }
+
+ return (1);
+}
+
+#if 0
+static int
+ignore_dot_names (name)
+ char *name;
+{
+ return (name[0] != '.');
+}
+#endif
+
+static int
+filename_completion_ignore (names)
+ char **names;
+{
+#if 0
+ if (glob_dot_filenames == 0)
+ _ignore_completion_names (names, ignore_dot_names);
+#endif
+
+ setup_ignore_patterns (&fignore);
+
+ if (fignore.num_ignores == 0)
+ return 0;
+
+ _ignore_completion_names (names, name_is_acceptable);
+
+ return 0;
+}
+
+/* Return 1 if NAME is a directory. NAME undergoes tilde expansion. */
+static int
+test_for_directory (name)
+ const char *name;
+{
+ char *fn;
+ int r;
+
+ fn = bash_tilde_expand (name, 0);
+ r = file_isdir (fn);
+ free (fn);
+
+ return (r);
+}
+
+/* Remove files from NAMES, leaving directories. */
+static int
+bash_ignore_filenames (names)
+ char **names;
+{
+ _ignore_completion_names (names, test_for_directory);
+ return 0;
+}
+
+static int
+return_zero (name)
+ const char *name;
+{
+ return 0;
+}
+
+static int
+bash_ignore_everything (names)
+ char **names;
+{
+ _ignore_completion_names (names, return_zero);
+ return 0;
+}
+
+/* Replace a tilde-prefix in VAL with a `~', assuming the user typed it. VAL
+ is an expanded filename. DIRECTORY_PART is the tilde-prefix portion
+ of the un-tilde-expanded version of VAL (what the user typed). */
+static char *
+restore_tilde (val, directory_part)
+ char *val, *directory_part;
+{
+ int l, vl, dl2, xl;
+ char *dh2, *expdir, *ret;
+
+ vl = strlen (val);
+
+ /* We need to duplicate the expansions readline performs on the directory
+ portion before passing it to our completion function. */
+ dh2 = directory_part ? bash_dequote_filename (directory_part, 0) : 0;
+ bash_directory_expansion (&dh2);
+ dl2 = strlen (dh2);
+
+ expdir = bash_tilde_expand (directory_part, 0);
+ xl = strlen (expdir);
+ free (expdir);
+
+ /*
+ dh2 = unexpanded but dequoted tilde-prefix
+ dl2 = length of tilde-prefix
+ expdir = tilde-expanded tilde-prefix
+ xl = length of expanded tilde-prefix
+ l = length of remainder after tilde-prefix
+ */
+ l = (vl - xl) + 1;
+
+ ret = (char *)xmalloc (dl2 + 2 + l);
+ strcpy (ret, dh2);
+ strcpy (ret + dl2, val + xl);
+
+ free (dh2);
+ return (ret);
+}
+
+/* Simulate the expansions that will be performed by
+ rl_filename_completion_function. This must be called with the address of
+ a pointer to malloc'd memory. */
+static void
+bash_directory_expansion (dirname)
+ char **dirname;
+{
+ char *d, *nd;
+
+ d = savestring (*dirname);
+
+ if ((rl_directory_rewrite_hook) && (*rl_directory_rewrite_hook) (&d))
+ {
+ free (*dirname);
+ *dirname = d;
+ }
+ else if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&d))
+ {
+ free (*dirname);
+ *dirname = d;
+ }
+ else if (rl_completion_found_quote)
+ {
+ nd = bash_dequote_filename (d, rl_completion_quote_character);
+ free (*dirname);
+ free (d);
+ *dirname = nd;
+ }
+}
+
+/* If necessary, rewrite directory entry */
+static char *
+bash_filename_rewrite_hook (fname, fnlen)
+ char *fname;
+ int fnlen;
+{
+ char *conv;
+
+ conv = fnx_fromfs (fname, fnlen);
+ if (conv != fname)
+ conv = savestring (conv);
+ return conv;
+}
+
+/* Functions to save and restore the appropriate directory hook */
+/* This is not static so the shopt code can call it */
+void
+set_directory_hook ()
+{
+ if (dircomplete_expand)
+ {
+ rl_directory_completion_hook = bash_directory_completion_hook;
+ rl_directory_rewrite_hook = (rl_icppfunc_t *)0;
+ }
+ else
+ {
+ rl_directory_rewrite_hook = bash_directory_completion_hook;
+ rl_directory_completion_hook = (rl_icppfunc_t *)0;
+ }
+}
+
+static rl_icppfunc_t *
+save_directory_hook ()
+{
+ rl_icppfunc_t *ret;
+
+ if (dircomplete_expand)
+ {
+ ret = rl_directory_completion_hook;
+ rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
+ }
+ else
+ {
+ ret = rl_directory_rewrite_hook;
+ rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
+ }
+
+ return ret;
+}
+
+static void
+restore_directory_hook (hookf)
+ rl_icppfunc_t *hookf;
+{
+ if (dircomplete_expand)
+ rl_directory_completion_hook = hookf;
+ else
+ rl_directory_rewrite_hook = hookf;
+}
+
+/* Expand a filename before the readline completion code passes it to stat(2).
+ The filename will already have had tilde expansion performed. */
+static int
+bash_filename_stat_hook (dirname)
+ char **dirname;
+{
+ char *local_dirname, *new_dirname, *t;
+ int should_expand_dirname, return_value;
+ WORD_LIST *wl;
+ struct stat sb;
+
+ local_dirname = *dirname;
+ should_expand_dirname = return_value = 0;
+ if (t = mbschr (local_dirname, '$'))
+ should_expand_dirname = '$';
+ else if (t = mbschr (local_dirname, '`')) /* XXX */
+ should_expand_dirname = '`';
+
+#if defined (HAVE_LSTAT)
+ if (should_expand_dirname && lstat (local_dirname, &sb) == 0)
+#else
+ if (should_expand_dirname && stat (local_dirname, &sb) == 0)
+#endif
+ should_expand_dirname = 0;
+
+ if (should_expand_dirname)
+ {
+ new_dirname = savestring (local_dirname);
+ wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB); /* does the right thing */
+ if (wl)
+ {
+ free (new_dirname);
+ new_dirname = string_list (wl);
+ /* Tell the completer we actually expanded something and change
+ *dirname only if we expanded to something non-null -- stat
+ behaves unpredictably when passed null or empty strings */
+ if (new_dirname && *new_dirname)
+ {
+ free (local_dirname); /* XXX */
+ local_dirname = *dirname = new_dirname;
+ return_value = STREQ (local_dirname, *dirname) == 0;
+ }
+ else
+ free (new_dirname);
+ dispose_words (wl);
+ }
+ else
+ free (new_dirname);
+ }
+
+ /* This is very similar to the code in bash_directory_completion_hook below,
+ but without spelling correction and not worrying about whether or not
+ we change relative pathnames. */
+ if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1]))
+ {
+ char *temp1, *temp2;
+
+ t = get_working_directory ("symlink-hook");
+ temp1 = make_absolute (local_dirname, t);
+ free (t);
+ temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+
+ /* If we can't canonicalize, bail. */
+ if (temp2 == 0)
+ {
+ free (temp1);
+ return return_value;
+ }
+
+ free (local_dirname);
+ *dirname = temp2;
+ free (temp1);
+ }
+
+ return (return_value);
+}
+
+/* Handle symbolic link references and other directory name
+ expansions while hacking completion. This should return 1 if it modifies
+ the DIRNAME argument, 0 otherwise. It should make sure not to modify
+ DIRNAME if it returns 0. */
+static int
+bash_directory_completion_hook (dirname)
+ char **dirname;
+{
+ char *local_dirname, *new_dirname, *t;
+ int return_value, should_expand_dirname, nextch, closer;
+ WORD_LIST *wl;
+ struct stat sb;
+
+ return_value = should_expand_dirname = nextch = closer = 0;
+ local_dirname = *dirname;
+
+ if (t = mbschr (local_dirname, '$'))
+ {
+ should_expand_dirname = '$';
+ nextch = t[1];
+ /* Deliberately does not handle the deprecated $[...] arithmetic
+ expansion syntax */
+ if (nextch == '(')
+ closer = ')';
+ else if (nextch == '{')
+ closer = '}';
+ else
+ nextch = 0;
+ }
+ else if (local_dirname[0] == '~')
+ should_expand_dirname = '~';
+ else
+ {
+ t = mbschr (local_dirname, '`');
+ if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0)
+ should_expand_dirname = '`';
+ }
+
+#if defined (HAVE_LSTAT)
+ if (should_expand_dirname && lstat (local_dirname, &sb) == 0)
+#else
+ if (should_expand_dirname && stat (local_dirname, &sb) == 0)
+#endif
+ should_expand_dirname = 0;
+
+ if (should_expand_dirname)
+ {
+ new_dirname = savestring (local_dirname);
+ wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB); /* does the right thing */
+ if (wl)
+ {
+ *dirname = string_list (wl);
+ /* Tell the completer to replace the directory name only if we
+ actually expanded something. */
+ return_value = STREQ (local_dirname, *dirname) == 0;
+ free (local_dirname);
+ free (new_dirname);
+ dispose_words (wl);
+ local_dirname = *dirname;
+ /* XXX - change rl_filename_quote_characters here based on
+ should_expand_dirname/nextch/closer. This is the only place
+ custom_filename_quote_characters is modified. */
+ if (rl_filename_quote_characters && *rl_filename_quote_characters)
+ {
+ int i, j, c;
+ i = strlen (default_filename_quote_characters);
+ custom_filename_quote_characters = xrealloc (custom_filename_quote_characters, i+1);
+ for (i = j = 0; c = default_filename_quote_characters[i]; i++)
+ {
+ if (c == should_expand_dirname || c == nextch || c == closer)
+ continue;
+ custom_filename_quote_characters[j++] = c;
+ }
+ custom_filename_quote_characters[j] = '\0';
+ rl_filename_quote_characters = custom_filename_quote_characters;
+ set_filename_bstab (rl_filename_quote_characters);
+ }
+ }
+ else
+ {
+ free (new_dirname);
+ free (local_dirname);
+ *dirname = (char *)xmalloc (1);
+ **dirname = '\0';
+ return 1;
+ }
+ }
+ else
+ {
+ /* Dequote the filename even if we don't expand it. */
+ new_dirname = bash_dequote_filename (local_dirname, rl_completion_quote_character);
+ return_value = STREQ (local_dirname, new_dirname) == 0;
+ free (local_dirname);
+ local_dirname = *dirname = new_dirname;
+ }
+
+ /* no_symbolic_links == 0 -> use (default) logical view of the file system.
+ local_dirname[0] == '.' && local_dirname[1] == '/' means files in the
+ current directory (./).
+ local_dirname[0] == '.' && local_dirname[1] == 0 means relative pathnames
+ in the current directory (e.g., lib/sh).
+ XXX - should we do spelling correction on these? */
+
+ /* This is test as it was in bash-4.2: skip relative pathnames in current
+ directory. Change test to
+ (local_dirname[0] != '.' || (local_dirname[1] && local_dirname[1] != '/'))
+ if we want to skip paths beginning with ./ also. */
+ if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1]))
+ {
+ char *temp1, *temp2;
+ int len1, len2;
+
+ /* If we have a relative path
+ (local_dirname[0] != '/' && local_dirname[0] != '.')
+ that is canonical after appending it to the current directory, then
+ temp1 = temp2+'/'
+ That is,
+ strcmp (temp1, temp2) == 0
+ after adding a slash to temp2 below. It should be safe to not
+ change those.
+ */
+ t = get_working_directory ("symlink-hook");
+ temp1 = make_absolute (local_dirname, t);
+ free (t);
+ temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+
+ /* Try spelling correction if initial canonicalization fails. Make
+ sure we are set to replace the directory name with the results so
+ subsequent directory checks don't fail. */
+ if (temp2 == 0 && dircomplete_spelling && dircomplete_expand)
+ {
+ temp2 = dirspell (temp1);
+ if (temp2)
+ {
+ free (temp1);
+ temp1 = temp2;
+ temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+ return_value |= temp2 != 0;
+ }
+ }
+ /* If we can't canonicalize, bail. */
+ if (temp2 == 0)
+ {
+ free (temp1);
+ return return_value;
+ }
+ len1 = strlen (temp1);
+ if (temp1[len1 - 1] == '/')
+ {
+ len2 = strlen (temp2);
+ if (len2 > 2) /* don't append `/' to `/' or `//' */
+ {
+ temp2 = (char *)xrealloc (temp2, len2 + 2);
+ temp2[len2] = '/';
+ temp2[len2 + 1] = '\0';
+ }
+ }
+
+ /* dircomplete_expand_relpath == 0 means we want to leave relative
+ pathnames that are unchanged by canonicalization alone.
+ *local_dirname != '/' && *local_dirname != '.' == relative pathname
+ (consistent with general.c:absolute_pathname())
+ temp1 == temp2 (after appending a slash to temp2) means the pathname
+ is not changed by canonicalization as described above. */
+ if (dircomplete_expand_relpath || ((local_dirname[0] != '/' && local_dirname[0] != '.') && STREQ (temp1, temp2) == 0))
+ return_value |= STREQ (local_dirname, temp2) == 0;
+ free (local_dirname);
+ *dirname = temp2;
+ free (temp1);
+ }
+
+ return (return_value);
+}
+
+static char **history_completion_array = (char **)NULL;
+static int harry_size;
+static int harry_len;
+
+static void
+build_history_completion_array ()
+{
+ register int i, j;
+ HIST_ENTRY **hlist;
+ char **tokens;
+
+ /* First, clear out the current dynamic history completion list. */
+ if (harry_size)
+ {
+ strvec_dispose (history_completion_array);
+ history_completion_array = (char **)NULL;
+ harry_size = 0;
+ harry_len = 0;
+ }
+
+ /* Next, grovel each line of history, making each shell-sized token
+ a separate entry in the history_completion_array. */
+ hlist = history_list ();
+
+ if (hlist)
+ {
+ for (i = 0; hlist[i]; i++)
+ ;
+ for ( --i; i >= 0; i--)
+ {
+ /* Separate each token, and place into an array. */
+ tokens = history_tokenize (hlist[i]->line);
+
+ for (j = 0; tokens && tokens[j]; j++)
+ {
+ if (harry_len + 2 > harry_size)
+ history_completion_array = strvec_resize (history_completion_array, harry_size += 10);
+
+ history_completion_array[harry_len++] = tokens[j];
+ history_completion_array[harry_len] = (char *)NULL;
+ }
+ free (tokens);
+ }
+
+ /* Sort the complete list of tokens. */
+ if (dabbrev_expand_active == 0)
+ qsort (history_completion_array, harry_len, sizeof (char *), (QSFUNC *)strvec_strcmp);
+ }
+}
+
+static char *
+history_completion_generator (hint_text, state)
+ const char *hint_text;
+ int state;
+{
+ static int local_index, len;
+ static const char *text;
+
+ /* If this is the first call to the generator, then initialize the
+ list of strings to complete over. */
+ if (state == 0)
+ {
+ if (dabbrev_expand_active) /* This is kind of messy */
+ rl_completion_suppress_append = 1;
+ local_index = 0;
+ build_history_completion_array ();
+ text = hint_text;
+ len = strlen (text);
+ }
+
+ while (history_completion_array && history_completion_array[local_index])
+ {
+ if (strncmp (text, history_completion_array[local_index++], len) == 0)
+ return (savestring (history_completion_array[local_index - 1]));
+ }
+ return ((char *)NULL);
+}
+
+static int
+dynamic_complete_history (count, key)
+ int count, key;
+{
+ int r;
+ rl_compentry_func_t *orig_func;
+ rl_completion_func_t *orig_attempt_func;
+ rl_compignore_func_t *orig_ignore_func;
+
+ orig_func = rl_completion_entry_function;
+ orig_attempt_func = rl_attempted_completion_function;
+ orig_ignore_func = rl_ignore_some_completions_function;
+
+ rl_completion_entry_function = history_completion_generator;
+ rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+ rl_ignore_some_completions_function = filename_completion_ignore;
+
+ /* XXX - use rl_completion_mode here? */
+ if (rl_last_func == dynamic_complete_history)
+ r = rl_complete_internal ('?');
+ else
+ r = rl_complete_internal (TAB);
+
+ rl_completion_entry_function = orig_func;
+ rl_attempted_completion_function = orig_attempt_func;
+ rl_ignore_some_completions_function = orig_ignore_func;
+
+ return r;
+}
+
+static int
+bash_dabbrev_expand (count, key)
+ int count, key;
+{
+ int r, orig_suppress, orig_sort;
+ rl_compentry_func_t *orig_func;
+ rl_completion_func_t *orig_attempt_func;
+ rl_compignore_func_t *orig_ignore_func;
+
+ orig_func = rl_menu_completion_entry_function;
+ orig_attempt_func = rl_attempted_completion_function;
+ orig_ignore_func = rl_ignore_some_completions_function;
+ orig_suppress = rl_completion_suppress_append;
+ orig_sort = rl_sort_completion_matches;
+
+ rl_menu_completion_entry_function = history_completion_generator;
+ rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+ rl_ignore_some_completions_function = filename_completion_ignore;
+ rl_filename_completion_desired = 0;
+ rl_completion_suppress_append = 1;
+ rl_sort_completion_matches = 0;
+
+ /* XXX - use rl_completion_mode here? */
+ dabbrev_expand_active = 1;
+ if (rl_last_func == bash_dabbrev_expand)
+ rl_last_func = rl_menu_complete;
+ r = rl_menu_complete (count, key);
+ dabbrev_expand_active = 0;
+
+ rl_last_func = bash_dabbrev_expand;
+ rl_menu_completion_entry_function = orig_func;
+ rl_attempted_completion_function = orig_attempt_func;
+ rl_ignore_some_completions_function = orig_ignore_func;
+ rl_completion_suppress_append = orig_suppress;
+ rl_sort_completion_matches = orig_sort;
+
+ return r;
+}
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+static int
+bash_complete_username (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_username_internal (rl_completion_mode (bash_complete_username));
+}
+
+static int
+bash_possible_username_completions (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_username_internal ('?');
+}
+
+static int
+bash_complete_username_internal (what_to_do)
+ int what_to_do;
+{
+ return bash_specific_completion (what_to_do, rl_username_completion_function);
+}
+
+static int
+bash_complete_filename (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_filename_internal (rl_completion_mode (bash_complete_filename));
+}
+
+static int
+bash_possible_filename_completions (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_filename_internal ('?');
+}
+
+static int
+bash_complete_filename_internal (what_to_do)
+ int what_to_do;
+{
+ rl_compentry_func_t *orig_func;
+ rl_completion_func_t *orig_attempt_func;
+ rl_icppfunc_t *orig_dir_func;
+ rl_compignore_func_t *orig_ignore_func;
+ /*const*/ char *orig_rl_completer_word_break_characters;
+ int r;
+
+ orig_func = rl_completion_entry_function;
+ orig_attempt_func = rl_attempted_completion_function;
+ orig_ignore_func = rl_ignore_some_completions_function;
+ orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
+
+ orig_dir_func = save_directory_hook ();
+
+ rl_completion_entry_function = rl_filename_completion_function;
+ rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+ rl_ignore_some_completions_function = filename_completion_ignore;
+ rl_completer_word_break_characters = " \t\n\"\'";
+
+ r = rl_complete_internal (what_to_do);
+
+ rl_completion_entry_function = orig_func;
+ rl_attempted_completion_function = orig_attempt_func;
+ rl_ignore_some_completions_function = orig_ignore_func;
+ rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
+
+ restore_directory_hook (orig_dir_func);
+
+ return r;
+}
+
+static int
+bash_complete_hostname (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_hostname_internal (rl_completion_mode (bash_complete_hostname));
+}
+
+static int
+bash_possible_hostname_completions (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_hostname_internal ('?');
+}
+
+static int
+bash_complete_variable (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_variable_internal (rl_completion_mode (bash_complete_variable));
+}
+
+static int
+bash_possible_variable_completions (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_variable_internal ('?');
+}
+
+static int
+bash_complete_command (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_command_internal (rl_completion_mode (bash_complete_command));
+}
+
+static int
+bash_possible_command_completions (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_command_internal ('?');
+}
+
+static int
+bash_complete_hostname_internal (what_to_do)
+ int what_to_do;
+{
+ return bash_specific_completion (what_to_do, hostname_completion_function);
+}
+
+static int
+bash_complete_variable_internal (what_to_do)
+ int what_to_do;
+{
+ return bash_specific_completion (what_to_do, variable_completion_function);
+}
+
+static int
+bash_complete_command_internal (what_to_do)
+ int what_to_do;
+{
+ return bash_specific_completion (what_to_do, command_word_completion_function);
+}
+
+static char *globtext;
+static char *globorig;
+
+static char *
+glob_complete_word (text, state)
+ const char *text;
+ int state;
+{
+ static char **matches = (char **)NULL;
+ static int ind;
+ int glen;
+ char *ret, *ttext;
+
+ if (state == 0)
+ {
+ rl_filename_completion_desired = 1;
+ FREE (matches);
+ if (globorig != globtext)
+ FREE (globorig);
+ FREE (globtext);
+
+ ttext = bash_tilde_expand (text, 0);
+
+ if (rl_explicit_arg)
+ {
+ globorig = savestring (ttext);
+ glen = strlen (ttext);
+ globtext = (char *)xmalloc (glen + 2);
+ strcpy (globtext, ttext);
+ globtext[glen] = '*';
+ globtext[glen+1] = '\0';
+ }
+ else
+ globtext = globorig = savestring (ttext);
+
+ if (ttext != text)
+ free (ttext);
+
+ matches = shell_glob_filename (globtext);
+ if (GLOB_FAILED (matches))
+ matches = (char **)NULL;
+ ind = 0;
+ }
+
+ ret = matches ? matches[ind] : (char *)NULL;
+ ind++;
+ return ret;
+}
+
+static int
+bash_glob_completion_internal (what_to_do)
+ int what_to_do;
+{
+ return bash_specific_completion (what_to_do, glob_complete_word);
+}
+
+/* A special quoting function so we don't end up quoting globbing characters
+ in the word if there are no matches or multiple matches. */
+static char *
+bash_glob_quote_filename (s, rtype, qcp)
+ char *s;
+ int rtype;
+ char *qcp;
+{
+ if (globorig && qcp && *qcp == '\0' && STREQ (s, globorig))
+ return (savestring (s));
+ else
+ return (bash_quote_filename (s, rtype, qcp));
+}
+
+static int
+bash_glob_complete_word (count, key)
+ int count, key;
+{
+ int r;
+ rl_quote_func_t *orig_quoting_function;
+
+ if (rl_editing_mode == EMACS_EDITING_MODE)
+ rl_explicit_arg = 1; /* force `*' append */
+ orig_quoting_function = rl_filename_quoting_function;
+ rl_filename_quoting_function = bash_glob_quote_filename;
+
+ r = bash_glob_completion_internal (rl_completion_mode (bash_glob_complete_word));
+
+ rl_filename_quoting_function = orig_quoting_function;
+ return r;
+}
+
+static int
+bash_glob_expand_word (count, key)
+ int count, key;
+{
+ return bash_glob_completion_internal ('*');
+}
+
+static int
+bash_glob_list_expansions (count, key)
+ int count, key;
+{
+ return bash_glob_completion_internal ('?');
+}
+
+static int
+bash_specific_completion (what_to_do, generator)
+ int what_to_do;
+ rl_compentry_func_t *generator;
+{
+ rl_compentry_func_t *orig_func;
+ rl_completion_func_t *orig_attempt_func;
+ rl_compignore_func_t *orig_ignore_func;
+ int r;
+
+ orig_func = rl_completion_entry_function;
+ orig_attempt_func = rl_attempted_completion_function;
+ orig_ignore_func = rl_ignore_some_completions_function;
+ rl_completion_entry_function = generator;
+ rl_attempted_completion_function = NULL;
+ rl_ignore_some_completions_function = orig_ignore_func;
+
+ r = rl_complete_internal (what_to_do);
+
+ rl_completion_entry_function = orig_func;
+ rl_attempted_completion_function = orig_attempt_func;
+ rl_ignore_some_completions_function = orig_ignore_func;
+
+ return r;
+}
+
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
+
+#if defined (VI_MODE)
+/* Completion, from vi mode's point of view. This is a modified version of
+ rl_vi_complete which uses the bash globbing code to implement what POSIX
+ specifies, which is to append a `*' and attempt filename generation (which
+ has the side effect of expanding any globbing characters in the word). */
+static int
+bash_vi_complete (count, key)
+ int count, key;
+{
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+ int p, r;
+ char *t;
+
+ if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
+ {
+ if (!whitespace (rl_line_buffer[rl_point + 1]))
+ rl_vi_end_word (1, 'E');
+ rl_point++;
+ }
+
+ /* Find boundaries of current word, according to vi definition of a
+ `bigword'. */
+ t = 0;
+ if (rl_point > 0)
+ {
+ p = rl_point;
+ rl_vi_bWord (1, 'B');
+ r = rl_point;
+ rl_point = p;
+ p = r;
+
+ t = substring (rl_line_buffer, p, rl_point);
+ }
+
+ if (t && glob_pattern_p (t) == 0)
+ rl_explicit_arg = 1; /* XXX - force glob_complete_word to append `*' */
+ FREE (t);
+
+ if (key == '*') /* Expansion and replacement. */
+ r = bash_glob_expand_word (count, key);
+ else if (key == '=') /* List possible completions. */
+ r = bash_glob_list_expansions (count, key);
+ else if (key == '\\') /* Standard completion */
+ r = bash_glob_complete_word (count, key);
+ else
+ r = rl_complete (0, key);
+
+ if (key == '*' || key == '\\')
+ rl_vi_start_inserting (key, 1, 1);
+
+ return (r);
+#else
+ return rl_vi_complete (count, key);
+#endif /* !SPECIFIC_COMPLETION_FUNCTIONS */
+}
+#endif /* VI_MODE */
+
+/* Filename quoting for completion. */
+/* A function to strip unquoted quote characters (single quotes, double
+ quotes, and backslashes). It allows single quotes to appear
+ within double quotes, and vice versa. It should be smarter. */
+static char *
+bash_dequote_filename (text, quote_char)
+ char *text;
+ int quote_char;
+{
+ char *ret, *p, *r;
+ int l, quoted;
+
+ l = strlen (text);
+ ret = (char *)xmalloc (l + 1);
+ for (quoted = quote_char, p = text, r = ret; p && *p; p++)
+ {
+ /* Allow backslash-escaped characters to pass through unscathed. */
+ if (*p == '\\')
+ {
+ /* Backslashes are preserved within single quotes. */
+ if (quoted == '\'')
+ *r++ = *p;
+ /* Backslashes are preserved within double quotes unless the
+ character is one that is defined to be escaped */
+ else if (quoted == '"' && ((sh_syntaxtab[p[1]] & CBSDQUOTE) == 0))
+ *r++ = *p;
+
+ *r++ = *++p;
+ if (*p == '\0')
+ return ret; /* XXX - was break; */
+ continue;
+ }
+ /* Close quote. */
+ if (quoted && *p == quoted)
+ {
+ quoted = 0;
+ continue;
+ }
+ /* Open quote. */
+ if (quoted == 0 && (*p == '\'' || *p == '"'))
+ {
+ quoted = *p;
+ continue;
+ }
+ *r++ = *p;
+ }
+ *r = '\0';
+ return ret;
+}
+
+/* Quote characters that the readline completion code would treat as
+ word break characters with backslashes. Pass backslash-quoted
+ characters through without examination. */
+static char *
+quote_word_break_chars (text)
+ char *text;
+{
+ char *ret, *r, *s;
+ int l;
+
+ l = strlen (text);
+ ret = (char *)xmalloc ((2 * l) + 1);
+ for (s = text, r = ret; *s; s++)
+ {
+ /* Pass backslash-quoted characters through, including the backslash. */
+ if (*s == '\\')
+ {
+ *r++ = '\\';
+ *r++ = *++s;
+ if (*s == '\0')
+ break;
+ continue;
+ }
+ /* OK, we have an unquoted character. Check its presence in
+ rl_completer_word_break_characters. */
+ if (mbschr (rl_completer_word_break_characters, *s))
+ *r++ = '\\';
+ /* XXX -- check for standalone tildes here and backslash-quote them */
+ if (s == text && *s == '~' && file_exists (text))
+ *r++ = '\\';
+ *r++ = *s;
+ }
+ *r = '\0';
+ return ret;
+}
+
+/* Use characters in STRING to populate the table of characters that should
+ be backslash-quoted. The table will be used for sh_backslash_quote from
+ this file. */
+static void
+set_filename_bstab (string)
+ const char *string;
+{
+ const char *s;
+
+ memset (filename_bstab, 0, sizeof (filename_bstab));
+ for (s = string; s && *s; s++)
+ filename_bstab[*s] = 1;
+}
+
+/* Quote a filename using double quotes, single quotes, or backslashes
+ depending on the value of completion_quoting_style. If we're
+ completing using backslashes, we need to quote some additional
+ characters (those that readline treats as word breaks), so we call
+ quote_word_break_chars on the result. This returns newly-allocated
+ memory. */
+static char *
+bash_quote_filename (s, rtype, qcp)
+ char *s;
+ int rtype;
+ char *qcp;
+{
+ char *rtext, *mtext, *ret;
+ int rlen, cs;
+
+ rtext = (char *)NULL;
+
+ /* If RTYPE == MULT_MATCH, it means that there is
+ more than one match. In this case, we do not add
+ the closing quote or attempt to perform tilde
+ expansion. If RTYPE == SINGLE_MATCH, we try
+ to perform tilde expansion, because single and double
+ quotes inhibit tilde expansion by the shell. */
+
+ cs = completion_quoting_style;
+ /* Might need to modify the default completion style based on *qcp,
+ since it's set to any user-provided opening quote. We also change
+ to single-quoting if there is no user-provided opening quote and
+ the word being completed contains newlines, since those are not
+ quoted correctly using backslashes (a backslash-newline pair is
+ special to the shell parser). */
+ if (*qcp == '\0' && cs == COMPLETE_BSQUOTE && mbschr (s, '\n'))
+ cs = COMPLETE_SQUOTE;
+ else if (*qcp == '"')
+ cs = COMPLETE_DQUOTE;
+ else if (*qcp == '\'')
+ cs = COMPLETE_SQUOTE;
+#if defined (BANG_HISTORY)
+ else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE &&
+ history_expansion_inhibited == 0 && mbschr (s, '!'))
+ cs = COMPLETE_BSQUOTE;
+
+ if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE &&
+ history_expansion_inhibited == 0 && mbschr (s, '!'))
+ {
+ cs = COMPLETE_BSQUOTE;
+ *qcp = '\0';
+ }
+#endif
+
+ /* Don't tilde-expand backslash-quoted filenames, since only single and
+ double quotes inhibit tilde expansion. */
+ mtext = s;
+ if (mtext[0] == '~' && rtype == SINGLE_MATCH && cs != COMPLETE_BSQUOTE)
+ mtext = bash_tilde_expand (s, 0);
+
+ switch (cs)
+ {
+ case COMPLETE_DQUOTE:
+ rtext = sh_double_quote (mtext);
+ break;
+ case COMPLETE_SQUOTE:
+ rtext = sh_single_quote (mtext);
+ break;
+ case COMPLETE_BSQUOTE:
+ rtext = sh_backslash_quote (mtext, complete_fullquote ? 0 : filename_bstab, 0);
+ break;
+ }
+
+ if (mtext != s)
+ free (mtext);
+
+ /* We may need to quote additional characters: those that readline treats
+ as word breaks that are not quoted by backslash_quote. */
+ if (rtext && cs == COMPLETE_BSQUOTE)
+ {
+ mtext = quote_word_break_chars (rtext);
+ free (rtext);
+ rtext = mtext;
+ }
+
+ /* Leave the opening quote intact. The readline completion code takes
+ care of avoiding doubled opening quotes. */
+ if (rtext)
+ {
+ rlen = strlen (rtext);
+ ret = (char *)xmalloc (rlen + 1);
+ strcpy (ret, rtext);
+ }
+ else
+ {
+ ret = (char *)xmalloc (rlen = 1);
+ ret[0] = '\0';
+ }
+
+ /* If there are multiple matches, cut off the closing quote. */
+ if (rtype == MULT_MATCH && cs != COMPLETE_BSQUOTE)
+ ret[rlen - 1] = '\0';
+ free (rtext);
+ return ret;
+}
+
+/* Support for binding readline key sequences to Unix commands. */
+static Keymap cmd_xmap;
+
+#ifdef _MINIX
+static void
+#else
+static int
+#endif
+putx(c)
+ int c;
+{
+ int x;
+ x = putc (c, rl_outstream);
+#ifndef _MINIX
+ return x;
+#endif
+}
+
+static int
+bash_execute_unix_command (count, key)
+ int count; /* ignored */
+ int key;
+{
+ Keymap ckmap; /* current keymap */
+ Keymap xkmap; /* unix command executing keymap */
+ rl_command_func_t *func;
+ int type;
+ register int i, r;
+ intmax_t mi;
+ sh_parser_state_t ps;
+ char *cmd, *value, *l, *l1, *ce;
+ SHELL_VAR *v;
+ char ibuf[INT_STRLEN_BOUND(int) + 1];
+
+ /* First, we need to find the right command to execute. This is tricky,
+ because we might have already indirected into another keymap, so we
+ have to walk cmd_xmap using the entire key sequence. */
+ cmd = (char *)rl_function_of_keyseq (rl_executing_keyseq, cmd_xmap, &type);
+
+ if (cmd == 0 || type != ISMACR)
+ {
+ rl_crlf ();
+ internal_error (_("bash_execute_unix_command: cannot find keymap for command"));
+ rl_forced_update_display ();
+ return 1;
+ }
+
+ ce = rl_get_termcap ("ce");
+ if (ce) /* clear current line */
+ {
+ fprintf (rl_outstream, "\r");
+ tputs (ce, 1, putx);
+ fflush (rl_outstream);
+ }
+ else
+ rl_crlf (); /* move to a new line */
+
+ v = bind_variable ("READLINE_LINE", rl_line_buffer, 0);
+ if (v)
+ VSETATTR (v, att_exported);
+ l = v ? value_cell (v) : 0;
+ value = inttostr (rl_point, ibuf, sizeof (ibuf));
+ v = bind_int_variable ("READLINE_POINT", value);
+ if (v)
+ VSETATTR (v, att_exported);
+ array_needs_making = 1;
+
+ save_parser_state (&ps);
+ r = parse_and_execute (cmd, "bash_execute_unix_command", SEVAL_NOHIST|SEVAL_NOFREE);
+ restore_parser_state (&ps);
+
+ v = find_variable ("READLINE_LINE");
+ l1 = v ? value_cell (v) : 0;
+ if (l1 != l)
+ maybe_make_readline_line (value_cell (v));
+ v = find_variable ("READLINE_POINT");
+ if (v && legal_number (value_cell (v), &mi))
+ {
+ i = mi;
+ if (i != rl_point)
+ {
+ rl_point = i;
+ if (rl_point > rl_end)
+ rl_point = rl_end;
+ else if (rl_point < 0)
+ rl_point = 0;
+ }
+ }
+
+ unbind_variable ("READLINE_LINE");
+ unbind_variable ("READLINE_POINT");
+ array_needs_making = 1;
+
+ /* and restore the readline buffer and display after command execution. */
+ rl_forced_update_display ();
+ return 0;
+}
+
+int
+print_unix_command_map ()
+{
+ Keymap save;
+
+ save = rl_get_keymap ();
+ rl_set_keymap (cmd_xmap);
+ rl_macro_dumper (1);
+ rl_set_keymap (save);
+ return 0;
+}
+
+static void
+init_unix_command_map ()
+{
+ cmd_xmap = rl_make_bare_keymap ();
+}
+
+static int
+isolate_sequence (string, ind, need_dquote, startp)
+ char *string;
+ int ind, need_dquote, *startp;
+{
+ register int i;
+ int c, passc, delim;
+
+ for (i = ind; string[i] && whitespace (string[i]); i++)
+ ;
+ /* NEED_DQUOTE means that the first non-white character *must* be `"'. */
+ if (need_dquote && string[i] != '"')
+ {
+ builtin_error (_("%s: first non-whitespace character is not `\"'"), string);
+ return -1;
+ }
+
+ /* We can have delimited strings even if NEED_DQUOTE == 0, like the command
+ string to bind the key sequence to. */
+ delim = (string[i] == '"' || string[i] == '\'') ? string[i] : 0;
+
+ if (startp)
+ *startp = delim ? ++i : i;
+
+ for (passc = 0; c = string[i]; i++)
+ {
+ if (passc)
+ {
+ passc = 0;
+ continue;
+ }
+ if (c == '\\')
+ {
+ passc++;
+ continue;
+ }
+ if (c == delim)
+ break;
+ }
+
+ if (delim && string[i] != delim)
+ {
+ builtin_error (_("no closing `%c' in %s"), delim, string);
+ return -1;
+ }
+
+ return i;
+}
+
+int
+bind_keyseq_to_unix_command (line)
+ char *line;
+{
+ Keymap kmap;
+ char *kseq, *value;
+ int i, kstart;
+
+ if (cmd_xmap == 0)
+ init_unix_command_map ();
+
+ kmap = rl_get_keymap ();
+
+ /* We duplicate some of the work done by rl_parse_and_bind here, but
+ this code only has to handle `"keyseq": ["]command["]' and can
+ generate an error for anything else. */
+ i = isolate_sequence (line, 0, 1, &kstart);
+ if (i < 0)
+ return -1;
+
+ /* Create the key sequence string to pass to rl_generic_bind */
+ kseq = substring (line, kstart, i);
+
+ for ( ; line[i] && line[i] != ':'; i++)
+ ;
+ if (line[i] != ':')
+ {
+ builtin_error (_("%s: missing colon separator"), line);
+ FREE (kseq);
+ return -1;
+ }
+
+ i = isolate_sequence (line, i + 1, 0, &kstart);
+ if (i < 0)
+ {
+ FREE (kseq);
+ return -1;
+ }
+
+ /* Create the value string containing the command to execute. */
+ value = substring (line, kstart, i);
+
+ /* Save the command to execute and the key sequence in the CMD_XMAP */
+ rl_generic_bind (ISMACR, kseq, value, cmd_xmap);
+
+ /* and bind the key sequence in the current keymap to a function that
+ understands how to execute from CMD_XMAP */
+ rl_bind_keyseq_in_map (kseq, bash_execute_unix_command, kmap);
+
+ free (kseq);
+ return 0;
+}
+
+/* Used by the programmable completion code. Complete TEXT as a filename,
+ but return only directories as matches. Dequotes the filename before
+ attempting to find matches. */
+char **
+bash_directory_completion_matches (text)
+ const char *text;
+{
+ char **m1;
+ char *dfn;
+ int qc;
+
+ qc = rl_dispatching ? rl_completion_quote_character : 0;
+ dfn = bash_dequote_filename ((char *)text, qc);
+ m1 = rl_completion_matches (dfn, rl_filename_completion_function);
+ free (dfn);
+
+ if (m1 == 0 || m1[0] == 0)
+ return m1;
+ /* We don't bother recomputing the lcd of the matches, because it will just
+ get thrown away by the programmable completion code and recomputed
+ later. */
+ (void)bash_ignore_filenames (m1);
+ return m1;
+}
+
+char *
+bash_dequote_text (text)
+ const char *text;
+{
+ char *dtxt;
+ int qc;
+
+ qc = (text[0] == '"' || text[0] == '\'') ? text[0] : 0;
+ dtxt = bash_dequote_filename ((char *)text, qc);
+ return (dtxt);
+}
+
+/* This event hook is designed to be called after readline receives a signal
+ that interrupts read(2). It gives reasonable responsiveness to interrupts
+ and fatal signals without executing too much code in a signal handler
+ context. */
+static int
+bash_event_hook ()
+{
+ /* If we're going to longjmp to top_level, make sure we clean up readline */
+ if (interrupt_state && signal_is_trapped (SIGINT) == 0)
+ rl_cleanup_after_signal ();
+
+ bashline_reset_event_hook ();
+ check_signals_and_traps (); /* XXX */
+}
+
+#endif /* READLINE */
--- /dev/null
+/* bashline.c -- Bash's interface to the readline library. */
+
+/* Copyright (C) 1987-2013 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bash is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bash. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#if defined (READLINE)
+
+#include "bashtypes.h"
+#include "posixstat.h"
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#if defined (HAVE_GRP_H)
+# include <grp.h>
+#endif
+
+#if defined (HAVE_NETDB_H)
+# include <netdb.h>
+#endif
+
+#include <signal.h>
+
+#include <stdio.h>
+#include "chartypes.h"
+#include "bashansi.h"
+#include "bashintl.h"
+
+#include "shell.h"
+#include "input.h"
+#include "builtins.h"
+#include "bashhist.h"
+#include "bashline.h"
+#include "execute_cmd.h"
+#include "findcmd.h"
+#include "pathexp.h"
+#include "shmbutil.h"
+
+#include "builtins/common.h"
+
+#include <readline/rlconf.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include <glob/glob.h>
+
+#if defined (ALIAS)
+# include "alias.h"
+#endif
+
+#if defined (PROGRAMMABLE_COMPLETION)
+# include "pcomplete.h"
+#endif
+
+/* These should agree with the defines for emacs_mode and vi_mode in
+ rldefs.h, even though that's not a public readline header file. */
+#ifndef EMACS_EDITING_MODE
+# define NO_EDITING_MODE -1
+# define EMACS_EDITING_MODE 1
+# define VI_EDITING_MODE 0
+#endif
+
+#define RL_BOOLEAN_VARIABLE_VALUE(s) ((s)[0] == 'o' && (s)[1] == 'n' && (s)[2] == '\0')
+
+#if defined (BRACE_COMPLETION)
+extern int bash_brace_completion __P((int, int));
+#endif /* BRACE_COMPLETION */
+
+/* To avoid including curses.h/term.h/termcap.h and that whole mess. */
+#ifdef _MINIX
+extern int tputs __P((const char *string, int nlines, void (*outx)(int)));
+#else
+extern int tputs __P((const char *string, int nlines, int (*outx)(int)));
+#endif
+
+/* Forward declarations */
+
+/* Functions bound to keys in Readline for Bash users. */
+static int shell_expand_line __P((int, int));
+static int display_shell_version __P((int, int));
+static int operate_and_get_next __P((int, int));
+
+static int bash_ignore_filenames __P((char **));
+static int bash_ignore_everything __P((char **));
+
+#if defined (BANG_HISTORY)
+static char *history_expand_line_internal __P((char *));
+static int history_expand_line __P((int, int));
+static int tcsh_magic_space __P((int, int));
+#endif /* BANG_HISTORY */
+#ifdef ALIAS
+static int alias_expand_line __P((int, int));
+#endif
+#if defined (BANG_HISTORY) && defined (ALIAS)
+static int history_and_alias_expand_line __P((int, int));
+#endif
+
+static int bash_forward_shellword __P((int, int));
+static int bash_backward_shellword __P((int, int));
+static int bash_kill_shellword __P((int, int));
+static int bash_backward_kill_shellword __P((int, int));
+
+/* Helper functions for Readline. */
+static char *restore_tilde __P((char *, char *));
+
+static char *bash_filename_rewrite_hook __P((char *, int));
+
+static void bash_directory_expansion __P((char **));
+static int bash_filename_stat_hook __P((char **));
+static int bash_command_name_stat_hook __P((char **));
+static int bash_directory_completion_hook __P((char **));
+static int filename_completion_ignore __P((char **));
+static int bash_push_line __P((void));
+
+static int executable_completion __P((const char *, int));
+
+static rl_icppfunc_t *save_directory_hook __P((void));
+static void restore_directory_hook __P((rl_icppfunc_t));
+
+static void cleanup_expansion_error __P((void));
+static void maybe_make_readline_line __P((char *));
+static void set_up_new_line __P((char *));
+
+static int check_redir __P((int));
+static char **attempt_shell_completion __P((const char *, int, int));
+static char *variable_completion_function __P((const char *, int));
+static char *hostname_completion_function __P((const char *, int));
+static char *command_subst_completion_function __P((const char *, int));
+
+static void build_history_completion_array __P((void));
+static char *history_completion_generator __P((const char *, int));
+static int dynamic_complete_history __P((int, int));
+static int bash_dabbrev_expand __P((int, int));
+
+static void initialize_hostname_list __P((void));
+static void add_host_name __P((char *));
+static void snarf_hosts_from_file __P((char *));
+static char **hostnames_matching __P((char *));
+
+static void _ignore_completion_names __P((char **, sh_ignore_func_t *));
+static int name_is_acceptable __P((const char *));
+static int test_for_directory __P((const char *));
+static int return_zero __P((const char *));
+
+static char *bash_dequote_filename __P((char *, int));
+static char *quote_word_break_chars __P((char *));
+static void set_filename_bstab __P((const char *));
+static char *bash_quote_filename __P((char *, int, char *));
+
+#ifdef _MINIX
+static void putx __P((int));
+#else
+static int putx __P((int));
+#endif
+static int bash_execute_unix_command __P((int, int));
+static void init_unix_command_map __P((void));
+static int isolate_sequence __P((char *, int, int, int *));
+
+static int set_saved_history __P((void));
+
+#if defined (ALIAS)
+static int posix_edit_macros __P((int, int));
+#endif
+
+static int bash_event_hook __P((void));
+
+#if defined (PROGRAMMABLE_COMPLETION)
+static int find_cmd_start __P((int));
+static int find_cmd_end __P((int));
+static char *find_cmd_name __P((int, int *, int *));
+static char *prog_complete_return __P((const char *, int));
+
+static char **prog_complete_matches;
+#endif
+
+/* Variables used here but defined in other files. */
+#if defined (BANG_HISTORY)
+extern int hist_verify;
+#endif
+
+extern int current_command_line_count, saved_command_line_count;
+extern int last_command_exit_value;
+extern int array_needs_making;
+extern int posixly_correct, no_symbolic_links;
+extern char *current_prompt_string, *ps1_prompt;
+extern STRING_INT_ALIST word_token_alist[];
+extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
+
+/* SPECIFIC_COMPLETION_FUNCTIONS specifies that we have individual
+ completion functions which indicate what type of completion should be
+ done (at or before point) that can be bound to key sequences with
+ the readline library. */
+#define SPECIFIC_COMPLETION_FUNCTIONS
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+static int bash_specific_completion __P((int, rl_compentry_func_t *));
+
+static int bash_complete_filename_internal __P((int));
+static int bash_complete_username_internal __P((int));
+static int bash_complete_hostname_internal __P((int));
+static int bash_complete_variable_internal __P((int));
+static int bash_complete_command_internal __P((int));
+
+static int bash_complete_filename __P((int, int));
+static int bash_possible_filename_completions __P((int, int));
+static int bash_complete_username __P((int, int));
+static int bash_possible_username_completions __P((int, int));
+static int bash_complete_hostname __P((int, int));
+static int bash_possible_hostname_completions __P((int, int));
+static int bash_complete_variable __P((int, int));
+static int bash_possible_variable_completions __P((int, int));
+static int bash_complete_command __P((int, int));
+static int bash_possible_command_completions __P((int, int));
+
+static char *glob_complete_word __P((const char *, int));
+static int bash_glob_completion_internal __P((int));
+static int bash_glob_complete_word __P((int, int));
+static int bash_glob_expand_word __P((int, int));
+static int bash_glob_list_expansions __P((int, int));
+
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
+
+static int edit_and_execute_command __P((int, int, int, char *));
+#if defined (VI_MODE)
+static int vi_edit_and_execute_command __P((int, int));
+static int bash_vi_complete __P((int, int));
+#endif
+static int emacs_edit_and_execute_command __P((int, int));
+
+/* Non-zero once initalize_readline () has been called. */
+int bash_readline_initialized = 0;
+
+/* If non-zero, we do hostname completion, breaking words at `@' and
+ trying to complete the stuff after the `@' from our own internal
+ host list. */
+int perform_hostname_completion = 1;
+
+/* If non-zero, we don't do command completion on an empty line. */
+int no_empty_command_completion;
+
+/* Set FORCE_FIGNORE if you want to honor FIGNORE even if it ignores the
+ only possible matches. Set to 0 if you want to match filenames if they
+ are the only possible matches, even if FIGNORE says to. */
+int force_fignore = 1;
+
+/* Perform spelling correction on directory names during word completion */
+int dircomplete_spelling = 0;
+
+/* Expand directory names during word/filename completion. */
+#if DIRCOMPLETE_EXPAND_DEFAULT
+int dircomplete_expand = 1;
+int dircomplete_expand_relpath = 1;
+#else
+int dircomplete_expand = 0;
+int dircomplete_expand_relpath = 0;
+#endif
+
+/* When non-zero, perform `normal' shell quoting on completed filenames
+ even when the completed name contains a directory name with a shell
+ variable referene, so dollar signs in a filename get quoted appropriately.
+ Set to zero to remove dollar sign (and braces or parens as needed) from
+ the set of characters that will be quoted. */
+int complete_fullquote = 1;
+
+static char *bash_completer_word_break_characters = " \t\n\"'@><=;|&(:";
+static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
+/* )) */
+
+static const char *default_filename_quote_characters = " \t\n\\\"'@<>=;|&()#$`?*[!:{~"; /*}*/
+static char *custom_filename_quote_characters = 0;
+static char filename_bstab[256];
+
+static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
+
+static int dot_in_path = 0;
+
+/* Set to non-zero when dabbrev-expand is running */
+static int dabbrev_expand_active = 0;
+
+/* What kind of quoting is performed by bash_quote_filename:
+ COMPLETE_DQUOTE = double-quoting the filename
+ COMPLETE_SQUOTE = single_quoting the filename
+ COMPLETE_BSQUOTE = backslash-quoting special chars in the filename
+*/
+#define COMPLETE_DQUOTE 1
+#define COMPLETE_SQUOTE 2
+#define COMPLETE_BSQUOTE 3
+static int completion_quoting_style = COMPLETE_BSQUOTE;
+
+/* Flag values for the final argument to bash_default_completion */
+#define DEFCOMP_CMDPOS 1
+
+/* Change the readline VI-mode keymaps into or out of Posix.2 compliance.
+ Called when the shell is put into or out of `posix' mode. */
+void
+posix_readline_initialize (on_or_off)
+ int on_or_off;
+{
+ if (on_or_off)
+ rl_variable_bind ("comment-begin", "#");
+#if defined (VI_MODE)
+ rl_bind_key_in_map (CTRL ('I'), on_or_off ? rl_insert : rl_complete, vi_insertion_keymap);
+#endif
+}
+
+void
+reset_completer_word_break_chars ()
+{
+ rl_completer_word_break_characters = perform_hostname_completion ? savestring (bash_completer_word_break_characters) : savestring (bash_nohostname_word_break_characters);
+}
+
+/* When this function returns, rl_completer_word_break_characters points to
+ dynamically allocated memory. */
+int
+enable_hostname_completion (on_or_off)
+ int on_or_off;
+{
+ int old_value;
+ char *at, *nv, *nval;
+
+ old_value = perform_hostname_completion;
+
+ if (on_or_off)
+ {
+ perform_hostname_completion = 1;
+ rl_special_prefixes = "$@";
+ }
+ else
+ {
+ perform_hostname_completion = 0;
+ rl_special_prefixes = "$";
+ }
+
+ /* Now we need to figure out how to appropriately modify and assign
+ rl_completer_word_break_characters depending on whether we want
+ hostname completion on or off. */
+
+ /* If this is the first time this has been called
+ (bash_readline_initialized == 0), use the sames values as before, but
+ allocate new memory for rl_completer_word_break_characters. */
+
+ if (bash_readline_initialized == 0 &&
+ (rl_completer_word_break_characters == 0 ||
+ rl_completer_word_break_characters == rl_basic_word_break_characters))
+ {
+ if (on_or_off)
+ rl_completer_word_break_characters = savestring (bash_completer_word_break_characters);
+ else
+ rl_completer_word_break_characters = savestring (bash_nohostname_word_break_characters);
+ }
+ else
+ {
+ /* See if we have anything to do. */
+ at = strchr (rl_completer_word_break_characters, '@');
+ if ((at == 0 && on_or_off == 0) || (at != 0 && on_or_off != 0))
+ return old_value;
+
+ /* We have something to do. Do it. */
+ nval = (char *)xmalloc (strlen (rl_completer_word_break_characters) + 1 + on_or_off);
+
+ if (on_or_off == 0)
+ {
+ /* Turn it off -- just remove `@' from word break chars. We want
+ to remove all occurrences of `@' from the char list, so we loop
+ rather than just copy the rest of the list over AT. */
+ for (nv = nval, at = rl_completer_word_break_characters; *at; )
+ if (*at != '@')
+ *nv++ = *at++;
+ else
+ at++;
+ *nv = '\0';
+ }
+ else
+ {
+ nval[0] = '@';
+ strcpy (nval + 1, rl_completer_word_break_characters);
+ }
+
+ free (rl_completer_word_break_characters);
+ rl_completer_word_break_characters = nval;
+ }
+
+ return (old_value);
+}
+
+/* Called once from parse.y if we are going to use readline. */
+void
+initialize_readline ()
+{
+ rl_command_func_t *func;
+ char kseq[2];
+
+ if (bash_readline_initialized)
+ return;
+
+ rl_terminal_name = get_string_value ("TERM");
+ rl_instream = stdin;
+ rl_outstream = stderr;
+
+ /* Allow conditional parsing of the ~/.inputrc file. */
+ rl_readline_name = "Bash";
+
+ /* Add bindable names before calling rl_initialize so they may be
+ referenced in the various inputrc files. */
+ rl_add_defun ("shell-expand-line", shell_expand_line, -1);
+#ifdef BANG_HISTORY
+ rl_add_defun ("history-expand-line", history_expand_line, -1);
+ rl_add_defun ("magic-space", tcsh_magic_space, -1);
+#endif
+
+ rl_add_defun ("shell-forward-word", bash_forward_shellword, -1);
+ rl_add_defun ("shell-backward-word", bash_backward_shellword, -1);
+ rl_add_defun ("shell-kill-word", bash_kill_shellword, -1);
+ rl_add_defun ("shell-backward-kill-word", bash_backward_kill_shellword, -1);
+
+#ifdef ALIAS
+ rl_add_defun ("alias-expand-line", alias_expand_line, -1);
+# ifdef BANG_HISTORY
+ rl_add_defun ("history-and-alias-expand-line", history_and_alias_expand_line, -1);
+# endif
+#endif
+
+ /* Backwards compatibility. */
+ rl_add_defun ("insert-last-argument", rl_yank_last_arg, -1);
+
+ rl_add_defun ("operate-and-get-next", operate_and_get_next, -1);
+ rl_add_defun ("display-shell-version", display_shell_version, -1);
+ rl_add_defun ("edit-and-execute-command", emacs_edit_and_execute_command, -1);
+
+#if defined (BRACE_COMPLETION)
+ rl_add_defun ("complete-into-braces", bash_brace_completion, -1);
+#endif
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+ rl_add_defun ("complete-filename", bash_complete_filename, -1);
+ rl_add_defun ("possible-filename-completions", bash_possible_filename_completions, -1);
+ rl_add_defun ("complete-username", bash_complete_username, -1);
+ rl_add_defun ("possible-username-completions", bash_possible_username_completions, -1);
+ rl_add_defun ("complete-hostname", bash_complete_hostname, -1);
+ rl_add_defun ("possible-hostname-completions", bash_possible_hostname_completions, -1);
+ rl_add_defun ("complete-variable", bash_complete_variable, -1);
+ rl_add_defun ("possible-variable-completions", bash_possible_variable_completions, -1);
+ rl_add_defun ("complete-command", bash_complete_command, -1);
+ rl_add_defun ("possible-command-completions", bash_possible_command_completions, -1);
+ rl_add_defun ("glob-complete-word", bash_glob_complete_word, -1);
+ rl_add_defun ("glob-expand-word", bash_glob_expand_word, -1);
+ rl_add_defun ("glob-list-expansions", bash_glob_list_expansions, -1);
+#endif
+
+ rl_add_defun ("dynamic-complete-history", dynamic_complete_history, -1);
+ rl_add_defun ("dabbrev-expand", bash_dabbrev_expand, -1);
+
+ /* Bind defaults before binding our custom shell keybindings. */
+ if (RL_ISSTATE(RL_STATE_INITIALIZED) == 0)
+ rl_initialize ();
+
+ /* Bind up our special shell functions. */
+ rl_bind_key_if_unbound_in_map (CTRL('E'), shell_expand_line, emacs_meta_keymap);
+
+#ifdef BANG_HISTORY
+ rl_bind_key_if_unbound_in_map ('^', history_expand_line, emacs_meta_keymap);
+#endif
+
+ rl_bind_key_if_unbound_in_map (CTRL ('O'), operate_and_get_next, emacs_standard_keymap);
+ rl_bind_key_if_unbound_in_map (CTRL ('V'), display_shell_version, emacs_ctlx_keymap);
+
+ /* In Bash, the user can switch editing modes with "set -o [vi emacs]",
+ so it is not necessary to allow C-M-j for context switching. Turn
+ off this occasionally confusing behaviour. */
+ kseq[0] = CTRL('J');
+ kseq[1] = '\0';
+ func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+ if (func == rl_vi_editing_mode)
+ rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap);
+ kseq[0] = CTRL('M');
+ func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+ if (func == rl_vi_editing_mode)
+ rl_unbind_key_in_map (CTRL('M'), emacs_meta_keymap);
+#if defined (VI_MODE)
+ rl_unbind_key_in_map (CTRL('E'), vi_movement_keymap);
+#endif
+
+#if defined (BRACE_COMPLETION)
+ rl_bind_key_if_unbound_in_map ('{', bash_brace_completion, emacs_meta_keymap); /*}*/
+#endif /* BRACE_COMPLETION */
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+ rl_bind_key_if_unbound_in_map ('/', bash_complete_filename, emacs_meta_keymap);
+ rl_bind_key_if_unbound_in_map ('/', bash_possible_filename_completions, emacs_ctlx_keymap);
+
+ /* Have to jump through hoops here because there is a default binding for
+ M-~ (rl_tilde_expand) */
+ kseq[0] = '~';
+ kseq[1] = '\0';
+ func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+ if (func == 0 || func == rl_tilde_expand)
+ rl_bind_keyseq_in_map (kseq, bash_complete_username, emacs_meta_keymap);
+
+ rl_bind_key_if_unbound_in_map ('~', bash_possible_username_completions, emacs_ctlx_keymap);
+
+ rl_bind_key_if_unbound_in_map ('@', bash_complete_hostname, emacs_meta_keymap);
+ rl_bind_key_if_unbound_in_map ('@', bash_possible_hostname_completions, emacs_ctlx_keymap);
+
+ rl_bind_key_if_unbound_in_map ('$', bash_complete_variable, emacs_meta_keymap);
+ rl_bind_key_if_unbound_in_map ('$', bash_possible_variable_completions, emacs_ctlx_keymap);
+
+ rl_bind_key_if_unbound_in_map ('!', bash_complete_command, emacs_meta_keymap);
+ rl_bind_key_if_unbound_in_map ('!', bash_possible_command_completions, emacs_ctlx_keymap);
+
+ rl_bind_key_if_unbound_in_map ('g', bash_glob_complete_word, emacs_meta_keymap);
+ rl_bind_key_if_unbound_in_map ('*', bash_glob_expand_word, emacs_ctlx_keymap);
+ rl_bind_key_if_unbound_in_map ('g', bash_glob_list_expansions, emacs_ctlx_keymap);
+
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
+
+ kseq[0] = TAB;
+ kseq[1] = '\0';
+ func = rl_function_of_keyseq (kseq, emacs_meta_keymap, (int *)NULL);
+ if (func == 0 || func == rl_tab_insert)
+ rl_bind_key_in_map (TAB, dynamic_complete_history, emacs_meta_keymap);
+
+ /* Tell the completer that we want a crack first. */
+ rl_attempted_completion_function = attempt_shell_completion;
+
+ /* Tell the completer that we might want to follow symbolic links or
+ do other expansion on directory names. */
+ set_directory_hook ();
+
+ rl_filename_rewrite_hook = bash_filename_rewrite_hook;
+
+ rl_filename_stat_hook = bash_filename_stat_hook;
+
+ /* Tell the filename completer we want a chance to ignore some names. */
+ rl_ignore_some_completions_function = filename_completion_ignore;
+
+ /* Bind C-xC-e to invoke emacs and run result as commands. */
+ rl_bind_key_if_unbound_in_map (CTRL ('E'), emacs_edit_and_execute_command, emacs_ctlx_keymap);
+#if defined (VI_MODE)
+ rl_bind_key_if_unbound_in_map ('v', vi_edit_and_execute_command, vi_movement_keymap);
+# if defined (ALIAS)
+ rl_bind_key_if_unbound_in_map ('@', posix_edit_macros, vi_movement_keymap);
+# endif
+
+ rl_bind_key_in_map ('\\', bash_vi_complete, vi_movement_keymap);
+ rl_bind_key_in_map ('*', bash_vi_complete, vi_movement_keymap);
+ rl_bind_key_in_map ('=', bash_vi_complete, vi_movement_keymap);
+#endif
+
+ rl_completer_quote_characters = "'\"";
+
+ /* This sets rl_completer_word_break_characters and rl_special_prefixes
+ to the appropriate values, depending on whether or not hostname
+ completion is enabled. */
+ enable_hostname_completion (perform_hostname_completion);
+
+ /* characters that need to be quoted when appearing in filenames. */
+ rl_filename_quote_characters = default_filename_quote_characters;
+ set_filename_bstab (rl_filename_quote_characters);
+
+ rl_filename_quoting_function = bash_quote_filename;
+ rl_filename_dequoting_function = bash_dequote_filename;
+ rl_char_is_quoted_p = char_is_quoted;
+
+#if 0
+ /* This is superfluous and makes it impossible to use tab completion in
+ vi mode even when explicitly binding it in ~/.inputrc. sv_strict_posix()
+ should already have called posix_readline_initialize() when
+ posixly_correct was set. */
+ if (posixly_correct)
+ posix_readline_initialize (1);
+#endif
+
+ bash_readline_initialized = 1;
+}
+
+void
+bashline_reinitialize ()
+{
+ bash_readline_initialized = 0;
+}
+
+void
+bashline_set_event_hook ()
+{
+ rl_signal_event_hook = bash_event_hook;
+}
+
+void
+bashline_reset_event_hook ()
+{
+ rl_signal_event_hook = 0;
+}
+
+/* On Sun systems at least, rl_attempted_completion_function can end up
+ getting set to NULL, and rl_completion_entry_function set to do command
+ word completion if Bash is interrupted while trying to complete a command
+ word. This just resets all the completion functions to the right thing.
+ It's called from throw_to_top_level(). */
+void
+bashline_reset ()
+{
+ tilde_initialize ();
+ rl_attempted_completion_function = attempt_shell_completion;
+ rl_completion_entry_function = NULL;
+ rl_ignore_some_completions_function = filename_completion_ignore;
+ rl_filename_quote_characters = default_filename_quote_characters;
+ set_filename_bstab (rl_filename_quote_characters);
+
+ set_directory_hook ();
+ rl_filename_stat_hook = bash_filename_stat_hook;
+
+ bashline_reset_event_hook ();
+}
+
+/* Contains the line to push into readline. */
+static char *push_to_readline = (char *)NULL;
+
+/* Push the contents of push_to_readline into the
+ readline buffer. */
+static int
+bash_push_line ()
+{
+ if (push_to_readline)
+ {
+ rl_insert_text (push_to_readline);
+ free (push_to_readline);
+ push_to_readline = (char *)NULL;
+ rl_startup_hook = old_rl_startup_hook;
+ }
+ return 0;
+}
+
+/* Call this to set the initial text for the next line to read
+ from readline. */
+int
+bash_re_edit (line)
+ char *line;
+{
+ FREE (push_to_readline);
+
+ push_to_readline = savestring (line);
+ old_rl_startup_hook = rl_startup_hook;
+ rl_startup_hook = bash_push_line;
+
+ return (0);
+}
+
+static int
+display_shell_version (count, c)
+ int count, c;
+{
+ rl_crlf ();
+ show_shell_version (0);
+ putc ('\r', rl_outstream);
+ fflush (rl_outstream);
+ rl_on_new_line ();
+ rl_redisplay ();
+ return 0;
+}
+
+/* **************************************************************** */
+/* */
+/* Readline Stuff */
+/* */
+/* **************************************************************** */
+
+/* If the user requests hostname completion, then simply build a list
+ of hosts, and complete from that forever more, or at least until
+ HOSTFILE is unset. */
+
+/* THIS SHOULD BE A STRINGLIST. */
+/* The kept list of hostnames. */
+static char **hostname_list = (char **)NULL;
+
+/* The physical size of the above list. */
+static int hostname_list_size;
+
+/* The number of hostnames in the above list. */
+static int hostname_list_length;
+
+/* Whether or not HOSTNAME_LIST has been initialized. */
+int hostname_list_initialized = 0;
+
+/* Initialize the hostname completion table. */
+static void
+initialize_hostname_list ()
+{
+ char *temp;
+
+ temp = get_string_value ("HOSTFILE");
+ if (temp == 0)
+ temp = get_string_value ("hostname_completion_file");
+ if (temp == 0)
+ temp = DEFAULT_HOSTS_FILE;
+
+ snarf_hosts_from_file (temp);
+
+ if (hostname_list)
+ hostname_list_initialized++;
+}
+
+/* Add NAME to the list of hosts. */
+static void
+add_host_name (name)
+ char *name;
+{
+ if (hostname_list_length + 2 > hostname_list_size)
+ {
+ hostname_list_size = (hostname_list_size + 32) - (hostname_list_size % 32);
+ hostname_list = strvec_resize (hostname_list, hostname_list_size);
+ }
+
+ hostname_list[hostname_list_length++] = savestring (name);
+ hostname_list[hostname_list_length] = (char *)NULL;
+}
+
+#define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
+
+static void
+snarf_hosts_from_file (filename)
+ char *filename;
+{
+ FILE *file;
+ char *temp, buffer[256], name[256];
+ register int i, start;
+
+ file = fopen (filename, "r");
+ if (file == 0)
+ return;
+
+ while (temp = fgets (buffer, 255, file))
+ {
+ /* Skip to first character. */
+ for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++)
+ ;
+
+ /* If comment or blank line, ignore. */
+ if (buffer[i] == '\0' || buffer[i] == '#')
+ continue;
+
+ /* If `preprocessor' directive, do the include. */
+ if (strncmp (buffer + i, "$include ", 9) == 0)
+ {
+ char *incfile, *t;
+
+ /* Find start of filename. */
+ for (incfile = buffer + i + 9; *incfile && whitespace (*incfile); incfile++)
+ ;
+
+ /* Find end of filename. */
+ for (t = incfile; *t && cr_whitespace (*t) == 0; t++)
+ ;
+
+ *t = '\0';
+
+ snarf_hosts_from_file (incfile);
+ continue;
+ }
+
+ /* Skip internet address if present. */
+ if (DIGIT (buffer[i]))
+ for (; buffer[i] && cr_whitespace (buffer[i]) == 0; i++);
+
+ /* Gobble up names. Each name is separated with whitespace. */
+ while (buffer[i])
+ {
+ for (; cr_whitespace (buffer[i]); i++)
+ ;
+ if (buffer[i] == '\0' || buffer[i] == '#')
+ break;
+
+ /* Isolate the current word. */
+ for (start = i; buffer[i] && cr_whitespace (buffer[i]) == 0; i++)
+ ;
+ if (i == start)
+ continue;
+ strncpy (name, buffer + start, i - start);
+ name[i - start] = '\0';
+ add_host_name (name);
+ }
+ }
+ fclose (file);
+}
+
+/* Return the hostname list. */
+char **
+get_hostname_list ()
+{
+ if (hostname_list_initialized == 0)
+ initialize_hostname_list ();
+ return (hostname_list);
+}
+
+void
+clear_hostname_list ()
+{
+ register int i;
+
+ if (hostname_list_initialized == 0)
+ return;
+ for (i = 0; i < hostname_list_length; i++)
+ free (hostname_list[i]);
+ hostname_list_length = hostname_list_initialized = 0;
+}
+
+/* Return a NULL terminated list of hostnames which begin with TEXT.
+ Initialize the hostname list the first time if neccessary.
+ The array is malloc ()'ed, but not the individual strings. */
+static char **
+hostnames_matching (text)
+ char *text;
+{
+ register int i, len, nmatch, rsize;
+ char **result;
+
+ if (hostname_list_initialized == 0)
+ initialize_hostname_list ();
+
+ if (hostname_list_initialized == 0)
+ return ((char **)NULL);
+
+ /* Special case. If TEXT consists of nothing, then the whole list is
+ what is desired. */
+ if (*text == '\0')
+ {
+ result = strvec_create (1 + hostname_list_length);
+ for (i = 0; i < hostname_list_length; i++)
+ result[i] = hostname_list[i];
+ result[i] = (char *)NULL;
+ return (result);
+ }
+
+ /* Scan until found, or failure. */
+ len = strlen (text);
+ result = (char **)NULL;
+ for (i = nmatch = rsize = 0; i < hostname_list_length; i++)
+ {
+ if (STREQN (text, hostname_list[i], len) == 0)
+ continue;
+
+ /* OK, it matches. Add it to the list. */
+ if (nmatch >= (rsize - 1))
+ {
+ rsize = (rsize + 16) - (rsize % 16);
+ result = strvec_resize (result, rsize);
+ }
+
+ result[nmatch++] = hostname_list[i];
+ }
+ if (nmatch)
+ result[nmatch] = (char *)NULL;
+ return (result);
+}
+
+/* The equivalent of the Korn shell C-o operate-and-get-next-history-line
+ editing command. */
+static int saved_history_line_to_use = -1;
+static int last_saved_history_line = -1;
+
+#define HISTORY_FULL() (history_is_stifled () && history_length >= history_max_entries)
+
+static int
+set_saved_history ()
+{
+ /* XXX - compensate for assumption that history was `shuffled' if it was
+ actually not. */
+ if (HISTORY_FULL () &&
+ hist_last_line_added == 0 &&
+ saved_history_line_to_use < history_length - 1)
+ saved_history_line_to_use++;
+
+ if (saved_history_line_to_use >= 0)
+ {
+ rl_get_previous_history (history_length - saved_history_line_to_use, 0);
+ last_saved_history_line = saved_history_line_to_use;
+ }
+ saved_history_line_to_use = -1;
+ rl_startup_hook = old_rl_startup_hook;
+ return (0);
+}
+
+static int
+operate_and_get_next (count, c)
+ int count, c;
+{
+ int where;
+
+ /* Accept the current line. */
+ rl_newline (1, c);
+
+ /* Find the current line, and find the next line to use. */
+ where = where_history ();
+
+ if (HISTORY_FULL () || (where >= history_length - 1))
+ saved_history_line_to_use = where;
+ else
+ saved_history_line_to_use = where + 1;
+
+ old_rl_startup_hook = rl_startup_hook;
+ rl_startup_hook = set_saved_history;
+
+ return 0;
+}
+
+/* This vi mode command causes VI_EDIT_COMMAND to be run on the current
+ command being entered (if no explicit argument is given), otherwise on
+ a command from the history file. */
+
+#define VI_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-vi}}\""
+#define EMACS_EDIT_COMMAND "fc -e \"${VISUAL:-${EDITOR:-emacs}}\""
+#define POSIX_VI_EDIT_COMMAND "fc -e vi"
+
+static int
+edit_and_execute_command (count, c, editing_mode, edit_command)
+ int count, c, editing_mode;
+ char *edit_command;
+{
+ char *command, *metaval;
+ int r, rrs, metaflag;
+ sh_parser_state_t ps;
+
+ rrs = rl_readline_state;
+ saved_command_line_count = current_command_line_count;
+
+ /* Accept the current line. */
+ rl_newline (1, c);
+
+ if (rl_explicit_arg)
+ {
+ command = (char *)xmalloc (strlen (edit_command) + 8);
+ sprintf (command, "%s %d", edit_command, count);
+ }
+ else
+ {
+ /* Take the command we were just editing, add it to the history file,
+ then call fc to operate on it. We have to add a dummy command to
+ the end of the history because fc ignores the last command (assumes
+ it's supposed to deal with the command before the `fc'). */
+ /* This breaks down when using command-oriented history and are not
+ finished with the command, so we should not ignore the last command */
+ using_history ();
+ current_command_line_count++; /* for rl_newline above */
+ bash_add_history (rl_line_buffer);
+ current_command_line_count = 0; /* for dummy history entry */
+ bash_add_history ("");
+ history_lines_this_session++;
+ using_history ();
+ command = savestring (edit_command);
+ }
+
+ metaval = rl_variable_value ("input-meta");
+ metaflag = RL_BOOLEAN_VARIABLE_VALUE (metaval);
+
+ /* Now, POSIX.1-2001 and SUSv3 say that the commands executed from the
+ temporary file should be placed into the history. We don't do that
+ yet. */
+ if (rl_deprep_term_function)
+ (*rl_deprep_term_function) ();
+ save_parser_state (&ps);
+ r = parse_and_execute (command, (editing_mode == VI_EDITING_MODE) ? "v" : "C-xC-e", SEVAL_NOHIST);
+ restore_parser_state (&ps);
+ if (rl_prep_term_function)
+ (*rl_prep_term_function) (metaflag);
+
+ current_command_line_count = saved_command_line_count;
+
+ /* Now erase the contents of the current line and undo the effects of the
+ rl_accept_line() above. We don't even want to make the text we just
+ executed available for undoing. */
+ rl_line_buffer[0] = '\0'; /* XXX */
+ rl_point = rl_end = 0;
+ rl_done = 0;
+ rl_readline_state = rrs;
+
+ rl_forced_update_display ();
+
+ return r;
+}
+
+#if defined (VI_MODE)
+static int
+vi_edit_and_execute_command (count, c)
+ int count, c;
+{
+ if (posixly_correct)
+ return (edit_and_execute_command (count, c, VI_EDITING_MODE, POSIX_VI_EDIT_COMMAND));
+ else
+ return (edit_and_execute_command (count, c, VI_EDITING_MODE, VI_EDIT_COMMAND));
+}
+#endif /* VI_MODE */
+
+static int
+emacs_edit_and_execute_command (count, c)
+ int count, c;
+{
+ return (edit_and_execute_command (count, c, EMACS_EDITING_MODE, EMACS_EDIT_COMMAND));
+}
+
+#if defined (ALIAS)
+static int
+posix_edit_macros (count, key)
+ int count, key;
+{
+ int c;
+ char alias_name[3], *alias_value, *macro;
+
+ c = rl_read_key ();
+ alias_name[0] = '_';
+ alias_name[1] = c;
+ alias_name[2] = '\0';
+
+ alias_value = get_alias_value (alias_name);
+ if (alias_value && *alias_value)
+ {
+ macro = savestring (alias_value);
+ rl_push_macro_input (macro);
+ }
+ return 0;
+}
+#endif
+
+/* Bindable commands that move `shell-words': that is, sequences of
+ non-unquoted-metacharacters. */
+
+#define WORDDELIM(c) (shellmeta(c) || shellblank(c))
+
+static int
+bash_forward_shellword (count, key)
+ int count, key;
+{
+ size_t slen;
+ int sindex, c, p;
+ DECLARE_MBSTATE;
+
+ if (count < 0)
+ return (bash_backward_shellword (-count, key));
+
+ /* The tricky part of this is deciding whether or not the first character
+ we're on is an unquoted metacharacter. Not completely handled yet. */
+ /* XXX - need to test this stuff with backslash-escaped shell
+ metacharacters and unclosed single- and double-quoted strings. */
+
+ p = rl_point;
+ slen = rl_end;
+
+ while (count)
+ {
+ if (p == rl_end)
+ {
+ rl_point = rl_end;
+ return 0;
+ }
+
+ /* Are we in a quoted string? If we are, move to the end of the quoted
+ string and continue the outer loop. We only want quoted strings, not
+ backslash-escaped characters, but char_is_quoted doesn't
+ differentiate. */
+ if (char_is_quoted (rl_line_buffer, p) && p > 0 && rl_line_buffer[p-1] != '\\')
+ {
+ do
+ ADVANCE_CHAR (rl_line_buffer, slen, p);
+ while (p < rl_end && char_is_quoted (rl_line_buffer, p));
+ count--;
+ continue;
+ }
+
+ /* Rest of code assumes we are not in a quoted string. */
+ /* Move forward until we hit a non-metacharacter. */
+ while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c))
+ {
+ switch (c)
+ {
+ default:
+ ADVANCE_CHAR (rl_line_buffer, slen, p);
+ continue; /* straight back to loop, don't increment p */
+ case '\\':
+ if (p < rl_end && rl_line_buffer[p])
+ ADVANCE_CHAR (rl_line_buffer, slen, p);
+ break;
+ case '\'':
+ p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP);
+ break;
+ case '"':
+ p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP);
+ break;
+ }
+
+ if (p < rl_end)
+ p++;
+ }
+
+ if (rl_line_buffer[p] == 0 || p == rl_end)
+ {
+ rl_point = rl_end;
+ rl_ding ();
+ return 0;
+ }
+
+ /* Now move forward until we hit a non-quoted metacharacter or EOL */
+ while (p < rl_end && (c = rl_line_buffer[p]) && WORDDELIM (c) == 0)
+ {
+ switch (c)
+ {
+ default:
+ ADVANCE_CHAR (rl_line_buffer, slen, p);
+ continue; /* straight back to loop, don't increment p */
+ case '\\':
+ if (p < rl_end && rl_line_buffer[p])
+ ADVANCE_CHAR (rl_line_buffer, slen, p);
+ break;
+ case '\'':
+ p = skip_to_delim (rl_line_buffer, ++p, "'", SD_NOJMP);
+ break;
+ case '"':
+ p = skip_to_delim (rl_line_buffer, ++p, "\"", SD_NOJMP);
+ break;
+ }
+
+ if (p < rl_end)
+ p++;
+ }
+
+ if (p == rl_end || rl_line_buffer[p] == 0)
+ {
+ rl_point = rl_end;
+ return (0);
+ }
+
+ count--;
+ }
+
+ rl_point = p;
+ return (0);
+}
+
+static int
+bash_backward_shellword (count, key)
+ int count, key;
+{
+ size_t slen;
+ int sindex, c, p;
+ DECLARE_MBSTATE;
+
+ if (count < 0)
+ return (bash_forward_shellword (-count, key));
+
+ p = rl_point;
+ slen = rl_end;
+
+ while (count)
+ {
+ if (p == 0)
+ {
+ rl_point = 0;
+ return 0;
+ }
+
+ /* Move backward until we hit a non-metacharacter. */
+ while (p > 0)
+ {
+ c = rl_line_buffer[p];
+ if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0)
+ BACKUP_CHAR (rl_line_buffer, slen, p);
+ break;
+ }
+
+ if (p == 0)
+ {
+ rl_point = 0;
+ return 0;
+ }
+
+ /* Now move backward until we hit a metacharacter or BOL. */
+ while (p > 0)
+ {
+ c = rl_line_buffer[p];
+ if (WORDDELIM (c) && char_is_quoted (rl_line_buffer, p) == 0)
+ break;
+ BACKUP_CHAR (rl_line_buffer, slen, p);
+ }
+
+ count--;
+ }
+
+ rl_point = p;
+ return 0;
+}
+
+static int
+bash_kill_shellword (count, key)
+ int count, key;
+{
+ int p;
+
+ if (count < 0)
+ return (bash_backward_kill_shellword (-count, key));
+
+ p = rl_point;
+ bash_forward_shellword (count, key);
+
+ if (rl_point != p)
+ rl_kill_text (p, rl_point);
+
+ rl_point = p;
+ if (rl_editing_mode == 1) /* 1 == emacs_mode */
+ rl_mark = rl_point;
+
+ return 0;
+}
+
+static int
+bash_backward_kill_shellword (count, key)
+ int count, key;
+{
+ int p;
+
+ if (count < 0)
+ return (bash_kill_shellword (-count, key));
+
+ p = rl_point;
+ bash_backward_shellword (count, key);
+
+ if (rl_point != p)
+ rl_kill_text (p, rl_point);
+
+ if (rl_editing_mode == 1) /* 1 == emacs_mode */
+ rl_mark = rl_point;
+
+ return 0;
+}
+
+
+/* **************************************************************** */
+/* */
+/* How To Do Shell Completion */
+/* */
+/* **************************************************************** */
+
+#define COMMAND_SEPARATORS ";|&{(`"
+/* )} */
+#define COMMAND_SEPARATORS_PLUS_WS ";|&{(` \t"
+/* )} */
+
+/* check for redirections and other character combinations that are not
+ command separators */
+static int
+check_redir (ti)
+ int ti;
+{
+ register int this_char, prev_char;
+
+ /* Handle the two character tokens `>&', `<&', and `>|'.
+ We are not in a command position after one of these. */
+ this_char = rl_line_buffer[ti];
+ prev_char = rl_line_buffer[ti - 1];
+
+ if ((this_char == '&' && (prev_char == '<' || prev_char == '>')) ||
+ (this_char == '|' && prev_char == '>'))
+ return (1);
+ else if (this_char == '{' && prev_char == '$') /*}*/
+ return (1);
+#if 0 /* Not yet */
+ else if (this_char == '(' && prev_char == '$') /*)*/
+ return (1);
+ else if (this_char == '(' && prev_char == '<') /*)*/
+ return (1);
+#if defined (EXTENDED_GLOB)
+ else if (extended_glob && this_char == '(' && prev_char == '!') /*)*/
+ return (1);
+#endif
+#endif
+ else if (char_is_quoted (rl_line_buffer, ti))
+ return (1);
+ return (0);
+}
+
+#if defined (PROGRAMMABLE_COMPLETION)
+/*
+ * XXX - because of the <= start test, and setting os = s+1, this can
+ * potentially return os > start. This is probably not what we want to
+ * happen, but fix later after 2.05a-release.
+ */
+static int
+find_cmd_start (start)
+ int start;
+{
+ register int s, os;
+
+ os = 0;
+ /* Flags == SD_NOJMP only because we want to skip over command substitutions
+ in assignment statements. Have to test whether this affects `standalone'
+ command substitutions as individual words. */
+ while (((s = skip_to_delim (rl_line_buffer, os, COMMAND_SEPARATORS, SD_NOJMP/*|SD_NOSKIPCMD*/)) <= start) &&
+ rl_line_buffer[s])
+ os = s+1;
+ return os;
+}
+
+static int
+find_cmd_end (end)
+ int end;
+{
+ register int e;
+
+ e = skip_to_delim (rl_line_buffer, end, COMMAND_SEPARATORS, SD_NOJMP);
+ return e;
+}
+
+static char *
+find_cmd_name (start, sp, ep)
+ int start;
+ int *sp, *ep;
+{
+ char *name;
+ register int s, e;
+
+ for (s = start; whitespace (rl_line_buffer[s]); s++)
+ ;
+
+ /* skip until a shell break character */
+ e = skip_to_delim (rl_line_buffer, s, "()<>;&| \t\n", SD_NOJMP);
+
+ name = substring (rl_line_buffer, s, e);
+
+ if (sp)
+ *sp = s;
+ if (ep)
+ *ep = e;
+
+ return (name);
+}
+
+static char *
+prog_complete_return (text, matchnum)
+ const char *text;
+ int matchnum;
+{
+ static int ind;
+
+ if (matchnum == 0)
+ ind = 0;
+
+ if (prog_complete_matches == 0 || prog_complete_matches[ind] == 0)
+ return (char *)NULL;
+ return (prog_complete_matches[ind++]);
+}
+
+#endif /* PROGRAMMABLE_COMPLETION */
+
+/* Do some completion on TEXT. The indices of TEXT in RL_LINE_BUFFER are
+ at START and END. Return an array of matches, or NULL if none. */
+static char **
+attempt_shell_completion (text, start, end)
+ const char *text;
+ int start, end;
+{
+ int in_command_position, ti, saveti, qc, dflags;
+ char **matches, *command_separator_chars;
+#if defined (PROGRAMMABLE_COMPLETION)
+ int have_progcomps, was_assignment;
+#endif
+
+ command_separator_chars = COMMAND_SEPARATORS;
+ matches = (char **)NULL;
+ rl_ignore_some_completions_function = filename_completion_ignore;
+
+ rl_filename_quote_characters = default_filename_quote_characters;
+ set_filename_bstab (rl_filename_quote_characters);
+ set_directory_hook ();
+ rl_filename_stat_hook = bash_filename_stat_hook;
+
+ /* Determine if this could be a command word. It is if it appears at
+ the start of the line (ignoring preceding whitespace), or if it
+ appears after a character that separates commands. It cannot be a
+ command word if we aren't at the top-level prompt. */
+ ti = start - 1;
+ saveti = qc = -1;
+
+ while ((ti > -1) && (whitespace (rl_line_buffer[ti])))
+ ti--;
+
+#if 1
+ /* If this is an open quote, maybe we're trying to complete a quoted
+ command name. */
+ if (ti >= 0 && (rl_line_buffer[ti] == '"' || rl_line_buffer[ti] == '\''))
+ {
+ qc = rl_line_buffer[ti];
+ saveti = ti--;
+ while (ti > -1 && (whitespace (rl_line_buffer[ti])))
+ ti--;
+ }
+#endif
+
+ in_command_position = 0;
+ if (ti < 0)
+ {
+ /* Only do command completion at the start of a line when we
+ are prompting at the top level. */
+ if (current_prompt_string == ps1_prompt)
+ in_command_position++;
+ else if (parser_in_command_position ())
+ in_command_position++;
+ }
+ else if (member (rl_line_buffer[ti], command_separator_chars))
+ {
+ in_command_position++;
+
+ if (check_redir (ti) == 1)
+ in_command_position = 0;
+ }
+ else
+ {
+ /* This still could be in command position. It is possible
+ that all of the previous words on the line are variable
+ assignments. */
+ }
+
+ /* Check that we haven't incorrectly flagged a closed command substitution
+ as indicating we're in a command position. */
+ if (in_command_position && ti >= 0 && rl_line_buffer[ti] == '`' &&
+ *text != '`' && unclosed_pair (rl_line_buffer, end, "`") == 0)
+ in_command_position = 0;
+
+ /* Special handling for command substitution. If *TEXT is a backquote,
+ it can be the start or end of an old-style command substitution, or
+ unmatched. If it's unmatched, both calls to unclosed_pair will
+ succeed. Don't bother if readline found a single quote and we are
+ completing on the substring. */
+ if (*text == '`' && rl_completion_quote_character != '\'' &&
+ (in_command_position || (unclosed_pair (rl_line_buffer, start, "`") &&
+ unclosed_pair (rl_line_buffer, end, "`"))))
+ matches = rl_completion_matches (text, command_subst_completion_function);
+
+#if defined (PROGRAMMABLE_COMPLETION)
+ /* Attempt programmable completion. */
+ have_progcomps = prog_completion_enabled && (progcomp_size () > 0);
+ if (matches == 0 && (in_command_position == 0 || text[0] == '\0') &&
+ current_prompt_string == ps1_prompt)
+ {
+ int s, e, s1, e1, os, foundcs;
+ char *n;
+
+ /* XXX - don't free the members */
+ if (prog_complete_matches)
+ free (prog_complete_matches);
+ prog_complete_matches = (char **)NULL;
+
+ os = start;
+ n = 0;
+ s = find_cmd_start (os);
+ e = find_cmd_end (end);
+ do
+ {
+ /* Skip over assignment statements preceding a command name. If we
+ don't find a command name at all, we can perform command name
+ completion. If we find a partial command name, we should perform
+ command name completion on it. */
+ FREE (n);
+ n = find_cmd_name (s, &s1, &e1);
+ s = e1 + 1;
+ }
+ while (was_assignment = assignment (n, 0));
+ s = s1; /* reset to index where name begins */
+
+ /* s == index of where command name begins (reset above)
+ e == end of current command, may be end of line
+ s1 = index of where command name begins
+ e1 == index of where command name ends
+ start == index of where word to be completed begins
+ end == index of where word to be completed ends
+ if (s == start) we are doing command word completion for sure
+ if (e1 == end) we are at the end of the command name and completing it */
+ if (start == 0 && end == 0 && e != 0 && text[0] == '\0') /* beginning of non-empty line */
+ foundcs = 0;
+ else if (start == end && start == s1 && e != 0 && e1 > end) /* beginning of command name, leading whitespace */
+ foundcs = 0;
+ else if (e == 0 && e == s && text[0] == '\0' && have_progcomps) /* beginning of empty line */
+ prog_complete_matches = programmable_completions ("_EmptycmD_", text, s, e, &foundcs);
+ else if (start == end && text[0] == '\0' && s1 > start && whitespace (rl_line_buffer[start]))
+ foundcs = 0; /* whitespace before command name */
+ else if (e > s && was_assignment == 0 && e1 == end && rl_line_buffer[e] == 0 && whitespace (rl_line_buffer[e-1]) == 0)
+ {
+ /* not assignment statement, but still want to perform command
+ completion if we are composing command word. */
+ foundcs = 0;
+ in_command_position = s == start && STREQ (n, text); /* XXX */
+ }
+ else if (e > s && was_assignment == 0 && have_progcomps)
+ {
+ prog_complete_matches = programmable_completions (n, text, s, e, &foundcs);
+ /* command completion if programmable completion fails */
+ in_command_position = s == start && STREQ (n, text); /* XXX */
+ }
+ else if (s >= e && n[0] == '\0' && text[0] == '\0' && start > 0)
+ {
+ foundcs = 0; /* empty command name following assignments */
+ in_command_position = was_assignment;
+ }
+ else if (s == start && e == end && STREQ (n, text) && start > 0)
+ {
+ foundcs = 0; /* partial command name following assignments */
+ in_command_position = 1;
+ }
+ else
+ foundcs = 0;
+ FREE (n);
+ /* XXX - if we found a COMPSPEC for the command, just return whatever
+ the programmable completion code returns, and disable the default
+ filename completion that readline will do unless the COPT_DEFAULT
+ option has been set with the `-o default' option to complete or
+ compopt. */
+ if (foundcs)
+ {
+ pcomp_set_readline_variables (foundcs, 1);
+ /* Turn what the programmable completion code returns into what
+ readline wants. I should have made compute_lcd_of_matches
+ external... */
+ matches = rl_completion_matches (text, prog_complete_return);
+ if ((foundcs & COPT_DEFAULT) == 0)
+ rl_attempted_completion_over = 1; /* no default */
+ if (matches || ((foundcs & COPT_BASHDEFAULT) == 0))
+ return (matches);
+ }
+ }
+#endif
+
+ if (matches == 0)
+ {
+ dflags = 0;
+ if (in_command_position)
+ dflags |= DEFCOMP_CMDPOS;
+ matches = bash_default_completion (text, start, end, qc, dflags);
+ }
+
+ return matches;
+}
+
+char **
+bash_default_completion (text, start, end, qc, compflags)
+ const char *text;
+ int start, end, qc, compflags;
+{
+ char **matches, *t;
+
+ matches = (char **)NULL;
+
+ /* New posix-style command substitution or variable name? */
+ if (!matches && *text == '$')
+ {
+ if (qc != '\'' && text[1] == '(') /* ) */
+ matches = rl_completion_matches (text, command_subst_completion_function);
+ else
+ {
+ matches = rl_completion_matches (text, variable_completion_function);
+ if (matches && matches[0] && matches[1] == 0)
+ {
+ t = savestring (matches[0]);
+ bash_filename_stat_hook (&t);
+ /* doesn't use test_for_directory because that performs tilde
+ expansion */
+ if (file_isdir (t))
+ rl_completion_append_character = '/';
+ free (t);
+ }
+ }
+ }
+
+ /* If the word starts in `~', and there is no slash in the word, then
+ try completing this word as a username. */
+ if (matches == 0 && *text == '~' && mbschr (text, '/') == 0)
+ matches = rl_completion_matches (text, rl_username_completion_function);
+
+ /* Another one. Why not? If the word starts in '@', then look through
+ the world of known hostnames for completion first. */
+ if (matches == 0 && perform_hostname_completion && *text == '@')
+ matches = rl_completion_matches (text, hostname_completion_function);
+
+ /* And last, (but not least) if this word is in a command position, then
+ complete over possible command names, including aliases, functions,
+ and command names. */
+ if (matches == 0 && (compflags & DEFCOMP_CMDPOS))
+ {
+ /* If END == START and text[0] == 0, we are trying to complete an empty
+ command word. */
+ if (no_empty_command_completion && end == start && text[0] == '\0')
+ {
+ matches = (char **)NULL;
+ rl_ignore_some_completions_function = bash_ignore_everything;
+ }
+ else
+ {
+#define CMD_IS_DIR(x) (absolute_pathname(x) == 0 && absolute_program(x) == 0 && *(x) != '~' && test_for_directory (x))
+
+ dot_in_path = 0;
+ matches = rl_completion_matches (text, command_word_completion_function);
+
+ /* If we are attempting command completion and nothing matches, we
+ do not want readline to perform filename completion for us. We
+ still want to be able to complete partial pathnames, so set the
+ completion ignore function to something which will remove
+ filenames and leave directories in the match list. */
+ if (matches == (char **)NULL)
+ rl_ignore_some_completions_function = bash_ignore_filenames;
+ else if (matches[1] == 0 && CMD_IS_DIR(matches[0]) && dot_in_path == 0)
+ /* If we found a single match, without looking in the current
+ directory (because it's not in $PATH), but the found name is
+ also a command in the current directory, suppress appending any
+ terminating character, since it's ambiguous. */
+ {
+ rl_completion_suppress_append = 1;
+ rl_filename_completion_desired = 0;
+ }
+ else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) && CMD_IS_DIR (matches[0]))
+ /* There are multiple instances of the same match (duplicate
+ completions haven't yet been removed). In this case, all of
+ the matches will be the same, and the duplicate removal code
+ will distill them all down to one. We turn on
+ rl_completion_suppress_append for the same reason as above.
+ Remember: we only care if there's eventually a single unique
+ completion. If there are multiple completions this won't
+ make a difference and the problem won't occur. */
+ {
+ rl_completion_suppress_append = 1;
+ rl_filename_completion_desired = 0;
+ }
+ }
+ }
+
+ /* This could be a globbing pattern, so try to expand it using pathname
+ expansion. */
+ if (!matches && glob_pattern_p (text))
+ {
+ matches = rl_completion_matches (text, glob_complete_word);
+ /* A glob expression that matches more than one filename is problematic.
+ If we match more than one filename, punt. */
+ if (matches && matches[1] && rl_completion_type == TAB)
+ {
+ strvec_dispose (matches);
+ matches = (char **)0;
+ }
+ else if (matches && matches[1] && rl_completion_type == '!')
+ {
+ rl_completion_suppress_append = 1;
+ rl_filename_completion_desired = 0;
+ }
+ }
+
+ return (matches);
+}
+
+static int
+bash_command_name_stat_hook (name)
+ char **name;
+{
+ char *cname, *result;
+
+ if (absolute_program (*name))
+ return (bash_filename_stat_hook (name));
+
+ cname = *name;
+ /* XXX - we could do something here with converting aliases, builtins,
+ and functions into something that came out as executable, but we don't. */
+ result = search_for_command (cname, 0);
+ if (result)
+ {
+ *name = result;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+executable_completion (filename, searching_path)
+ const char *filename;
+ int searching_path;
+{
+ char *f;
+ int r;
+
+ f = savestring (filename);
+ bash_directory_completion_hook (&f);
+
+ r = searching_path ? executable_file (f) : executable_or_directory (f);
+ free (f);
+ return r;
+}
+
+/* This is the function to call when the word to complete is in a position
+ where a command word can be found. It grovels $PATH, looking for commands
+ that match. It also scans aliases, function names, and the shell_builtin
+ table. */
+char *
+command_word_completion_function (hint_text, state)
+ const char *hint_text;
+ int state;
+{
+ static char *hint = (char *)NULL;
+ static char *path = (char *)NULL;
+ static char *val = (char *)NULL;
+ static char *filename_hint = (char *)NULL;
+ static char *dequoted_hint = (char *)NULL;
+ static char *directory_part = (char *)NULL;
+ static char **glob_matches = (char **)NULL;
+ static int path_index, hint_len, dequoted_len, istate, igncase;
+ static int mapping_over, local_index, searching_path, hint_is_dir;
+ static int old_glob_ignore_case, globpat;
+ static SHELL_VAR **varlist = (SHELL_VAR **)NULL;
+#if defined (ALIAS)
+ static alias_t **alias_list = (alias_t **)NULL;
+#endif /* ALIAS */
+ char *temp, *cval;
+
+ /* We have to map over the possibilities for command words. If we have
+ no state, then make one just for that purpose. */
+ if (state == 0)
+ {
+ rl_filename_stat_hook = bash_command_name_stat_hook;
+
+ if (dequoted_hint && dequoted_hint != hint)
+ free (dequoted_hint);
+ if (hint)
+ free (hint);
+
+ mapping_over = searching_path = 0;
+ hint_is_dir = CMD_IS_DIR (hint_text);
+ val = (char *)NULL;
+
+ temp = rl_variable_value ("completion-ignore-case");
+ igncase = RL_BOOLEAN_VARIABLE_VALUE (temp);
+
+ if (glob_matches)
+ {
+ free (glob_matches);
+ glob_matches = (char **)NULL;
+ }
+
+ globpat = glob_pattern_p (hint_text);
+
+ /* If this is an absolute program name, do not check it against
+ aliases, reserved words, functions or builtins. We must check
+ whether or not it is unique, and, if so, whether that filename
+ is executable. */
+ if (globpat || absolute_program (hint_text))
+ {
+ /* Perform tilde expansion on what's passed, so we don't end up
+ passing filenames with tildes directly to stat(). */
+ if (*hint_text == '~')
+ {
+ hint = bash_tilde_expand (hint_text, 0);
+ directory_part = savestring (hint_text);
+ temp = strchr (directory_part, '/');
+ if (temp)
+ *temp = 0;
+ else
+ {
+ free (directory_part);
+ directory_part = (char *)NULL;
+ }
+ }
+ else
+ hint = savestring (hint_text);
+
+ dequoted_hint = hint;
+ /* If readline's completer found a quote character somewhere, but
+ didn't set the quote character, there must have been a quote
+ character embedded in the filename. It can't be at the start of
+ the filename, so we need to dequote the filename before we look
+ in the file system for it. */
+ if (rl_completion_found_quote && rl_completion_quote_character == 0)
+ {
+ dequoted_hint = bash_dequote_filename (hint, 0);
+ free (hint);
+ hint = dequoted_hint;
+ }
+ dequoted_len = hint_len = strlen (hint);
+
+ if (filename_hint)
+ free (filename_hint);
+
+ filename_hint = savestring (hint);
+
+ istate = 0;
+
+ if (globpat)
+ {
+ mapping_over = 5;
+ goto globword;
+ }
+ else
+ {
+ if (dircomplete_expand && path_dot_or_dotdot (filename_hint))
+ {
+ dircomplete_expand = 0;
+ set_directory_hook ();
+ dircomplete_expand = 1;
+ }
+ mapping_over = 4;
+ goto inner;
+ }
+ }
+
+ dequoted_hint = hint = savestring (hint_text);
+ dequoted_len = hint_len = strlen (hint);
+
+ if (rl_completion_found_quote && rl_completion_quote_character == 0)
+ {
+ dequoted_hint = bash_dequote_filename (hint, 0);
+ dequoted_len = strlen (dequoted_hint);
+ }
+
+ path = get_string_value ("PATH");
+ path_index = dot_in_path = 0;
+
+ /* Initialize the variables for each type of command word. */
+ local_index = 0;
+
+ if (varlist)
+ free (varlist);
+
+ varlist = all_visible_functions ();
+
+#if defined (ALIAS)
+ if (alias_list)
+ free (alias_list);
+
+ alias_list = all_aliases ();
+#endif /* ALIAS */
+ }
+
+ /* mapping_over says what we are currently hacking. Note that every case
+ in this list must fall through when there are no more possibilities. */
+
+ switch (mapping_over)
+ {
+ case 0: /* Aliases come first. */
+#if defined (ALIAS)
+ while (alias_list && alias_list[local_index])
+ {
+ register char *alias;
+
+ alias = alias_list[local_index++]->name;
+
+ if (STREQN (alias, hint, hint_len))
+ return (savestring (alias));
+ }
+#endif /* ALIAS */
+ local_index = 0;
+ mapping_over++;
+
+ case 1: /* Then shell reserved words. */
+ {
+ while (word_token_alist[local_index].word)
+ {
+ register char *reserved_word;
+
+ reserved_word = word_token_alist[local_index++].word;
+
+ if (STREQN (reserved_word, hint, hint_len))
+ return (savestring (reserved_word));
+ }
+ local_index = 0;
+ mapping_over++;
+ }
+
+ case 2: /* Then function names. */
+ while (varlist && varlist[local_index])
+ {
+ register char *varname;
+
+ varname = varlist[local_index++]->name;
+
+ if (STREQN (varname, hint, hint_len))
+ return (savestring (varname));
+ }
+ local_index = 0;
+ mapping_over++;
+
+ case 3: /* Then shell builtins. */
+ for (; local_index < num_shell_builtins; local_index++)
+ {
+ /* Ignore it if it doesn't have a function pointer or if it
+ is not currently enabled. */
+ if (!shell_builtins[local_index].function ||
+ (shell_builtins[local_index].flags & BUILTIN_ENABLED) == 0)
+ continue;
+
+ if (STREQN (shell_builtins[local_index].name, hint, hint_len))
+ {
+ int i = local_index++;
+
+ return (savestring (shell_builtins[i].name));
+ }
+ }
+ local_index = 0;
+ mapping_over++;
+ }
+
+globword:
+ /* Limited support for completing command words with globbing chars. Only
+ a single match (multiple matches that end up reducing the number of
+ characters in the common prefix are bad) will ever be returned on
+ regular completion. */
+ if (globpat)
+ {
+ if (state == 0)
+ {
+ glob_ignore_case = igncase;
+ glob_matches = shell_glob_filename (hint);
+ glob_ignore_case = old_glob_ignore_case;
+
+ if (GLOB_FAILED (glob_matches) || glob_matches == 0)
+ {
+ glob_matches = (char **)NULL;
+ return ((char *)NULL);
+ }
+
+ local_index = 0;
+
+ if (glob_matches[1] && rl_completion_type == TAB) /* multiple matches are bad */
+ return ((char *)NULL);
+ }
+
+ while (val = glob_matches[local_index++])
+ {
+ if (executable_or_directory (val))
+ {
+ if (*hint_text == '~' && directory_part)
+ {
+ temp = restore_tilde (val, directory_part);
+ free (val);
+ val = temp;
+ }
+ return (val);
+ }
+ free (val);
+ }
+
+ glob_ignore_case = old_glob_ignore_case;
+ return ((char *)NULL);
+ }
+
+ /* If the text passed is a directory in the current directory, return it
+ as a possible match. Executables in directories in the current
+ directory can be specified using relative pathnames and successfully
+ executed even when `.' is not in $PATH. */
+ if (hint_is_dir)
+ {
+ hint_is_dir = 0; /* only return the hint text once */
+ return (savestring (hint_text));
+ }
+
+ /* Repeatedly call filename_completion_function while we have
+ members of PATH left. Question: should we stat each file?
+ Answer: we call executable_file () on each file. */
+ outer:
+
+ istate = (val != (char *)NULL);
+
+ if (istate == 0)
+ {
+ char *current_path;
+
+ /* Get the next directory from the path. If there is none, then we
+ are all done. */
+ if (path == 0 || path[path_index] == 0 ||
+ (current_path = extract_colon_unit (path, &path_index)) == 0)
+ return ((char *)NULL);
+
+ searching_path = 1;
+ if (*current_path == 0)
+ {
+ free (current_path);
+ current_path = savestring (".");
+ }
+
+ if (*current_path == '~')
+ {
+ char *t;
+
+ t = bash_tilde_expand (current_path, 0);
+ free (current_path);
+ current_path = t;
+ }
+
+ if (current_path[0] == '.' && current_path[1] == '\0')
+ dot_in_path = 1;
+
+ if (filename_hint)
+ free (filename_hint);
+
+ filename_hint = sh_makepath (current_path, hint, 0);
+ free (current_path); /* XXX */
+ }
+
+ inner:
+ val = rl_filename_completion_function (filename_hint, istate);
+ if (mapping_over == 4 && dircomplete_expand)
+ set_directory_hook ();
+
+ istate = 1;
+
+ if (val == 0)
+ {
+ /* If the hint text is an absolute program, then don't bother
+ searching through PATH. */
+ if (absolute_program (hint))
+ return ((char *)NULL);
+
+ goto outer;
+ }
+ else
+ {
+ int match, freetemp;
+
+ if (absolute_program (hint))
+ {
+ if (igncase == 0)
+ match = strncmp (val, hint, hint_len) == 0;
+ else
+ match = strncasecmp (val, hint, hint_len) == 0;
+
+ /* If we performed tilde expansion, restore the original
+ filename. */
+ if (*hint_text == '~')
+ temp = restore_tilde (val, directory_part);
+ else
+ temp = savestring (val);
+ freetemp = 1;
+ }
+ else
+ {
+ temp = strrchr (val, '/');
+
+ if (temp)
+ {
+ temp++;
+ if (igncase == 0)
+ freetemp = match = strncmp (temp, hint, hint_len) == 0;
+ else
+ freetemp = match = strncasecmp (temp, hint, hint_len) == 0;
+ if (match)
+ temp = savestring (temp);
+ }
+ else
+ freetemp = match = 0;
+ }
+
+ /* If we have found a match, and it is an executable file, return it.
+ We don't return directory names when searching $PATH, since the
+ bash execution code won't find executables in directories which
+ appear in directories in $PATH when they're specified using
+ relative pathnames. */
+#if 0
+ /* If we're not searching $PATH and we have a relative pathname, we
+ need to re-canonicalize it before testing whether or not it's an
+ executable or a directory so the shell treats .. relative to $PWD
+ according to the physical/logical option. The shell already
+ canonicalizes the directory name in order to tell readline where
+ to look, so not doing it here will be inconsistent. */
+ /* XXX -- currently not used -- will introduce more inconsistency,
+ since shell does not canonicalize ../foo before passing it to
+ shell_execve(). */
+ if (match && searching_path == 0 && *val == '.')
+ {
+ char *t, *t1;
+
+ t = get_working_directory ("command-word-completion");
+ t1 = make_absolute (val, t);
+ free (t);
+ cval = sh_canonpath (t1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+ }
+ else
+#endif
+ cval = val;
+
+ if (match && executable_completion ((searching_path ? val : cval), searching_path))
+ {
+ if (cval != val)
+ free (cval);
+ free (val);
+ val = ""; /* So it won't be NULL. */
+ return (temp);
+ }
+ else
+ {
+ if (freetemp)
+ free (temp);
+ if (cval != val)
+ free (cval);
+ free (val);
+ goto inner;
+ }
+ }
+}
+
+/* Completion inside an unterminated command substitution. */
+static char *
+command_subst_completion_function (text, state)
+ const char *text;
+ int state;
+{
+ static char **matches = (char **)NULL;
+ static const char *orig_start;
+ static char *filename_text = (char *)NULL;
+ static int cmd_index, start_len;
+ char *value;
+
+ if (state == 0)
+ {
+ if (filename_text)
+ free (filename_text);
+ orig_start = text;
+ if (*text == '`')
+ text++;
+ else if (*text == '$' && text[1] == '(') /* ) */
+ text += 2;
+ /* If the text was quoted, suppress any quote character that the
+ readline completion code would insert. */
+ rl_completion_suppress_quote = 1;
+ start_len = text - orig_start;
+ filename_text = savestring (text);
+ if (matches)
+ free (matches);
+
+ /*
+ * At this point we can entertain the idea of re-parsing
+ * `filename_text' into a (possibly incomplete) command name and
+ * arguments, and doing completion based on that. This is
+ * currently very rudimentary, but it is a small improvement.
+ */
+ for (value = filename_text + strlen (filename_text) - 1; value > filename_text; value--)
+ if (whitespace (*value) || member (*value, COMMAND_SEPARATORS))
+ break;
+ if (value <= filename_text)
+ matches = rl_completion_matches (filename_text, command_word_completion_function);
+ else
+ {
+ value++;
+ start_len += value - filename_text;
+ if (whitespace (value[-1]))
+ matches = rl_completion_matches (value, rl_filename_completion_function);
+ else
+ matches = rl_completion_matches (value, command_word_completion_function);
+ }
+
+ /* If there is more than one match, rl_completion_matches has already
+ put the lcd in matches[0]. Skip over it. */
+ cmd_index = matches && matches[0] && matches[1];
+
+ /* If there's a single match and it's a directory, set the append char
+ to the expected `/'. Otherwise, don't append anything. */
+ if (matches && matches[0] && matches[1] == 0 && test_for_directory (matches[0]))
+ rl_completion_append_character = '/';
+ else
+ rl_completion_suppress_append = 1;
+ }
+
+ if (matches == 0 || matches[cmd_index] == 0)
+ {
+ rl_filename_quoting_desired = 0; /* disable quoting */
+ return ((char *)NULL);
+ }
+ else
+ {
+ value = (char *)xmalloc (1 + start_len + strlen (matches[cmd_index]));
+
+ if (start_len == 1)
+ value[0] = *orig_start;
+ else
+ strncpy (value, orig_start, start_len);
+
+ strcpy (value + start_len, matches[cmd_index]);
+
+ cmd_index++;
+ return (value);
+ }
+}
+
+/* Okay, now we write the entry_function for variable completion. */
+static char *
+variable_completion_function (text, state)
+ const char *text;
+ int state;
+{
+ static char **varlist = (char **)NULL;
+ static int varlist_index;
+ static char *varname = (char *)NULL;
+ static int namelen;
+ static int first_char, first_char_loc;
+
+ if (!state)
+ {
+ if (varname)
+ free (varname);
+
+ first_char_loc = 0;
+ first_char = text[0];
+
+ if (first_char == '$')
+ first_char_loc++;
+
+ if (text[first_char_loc] == '{')
+ first_char_loc++;
+
+ varname = savestring (text + first_char_loc);
+
+ namelen = strlen (varname);
+ if (varlist)
+ strvec_dispose (varlist);
+
+ varlist = all_variables_matching_prefix (varname);
+ varlist_index = 0;
+ }
+
+ if (!varlist || !varlist[varlist_index])
+ {
+ return ((char *)NULL);
+ }
+ else
+ {
+ char *value;
+
+ value = (char *)xmalloc (4 + strlen (varlist[varlist_index]));
+
+ if (first_char_loc)
+ {
+ value[0] = first_char;
+ if (first_char_loc == 2)
+ value[1] = '{';
+ }
+
+ strcpy (value + first_char_loc, varlist[varlist_index]);
+ if (first_char_loc == 2)
+ strcat (value, "}");
+
+ varlist_index++;
+ return (value);
+ }
+}
+
+/* How about a completion function for hostnames? */
+static char *
+hostname_completion_function (text, state)
+ const char *text;
+ int state;
+{
+ static char **list = (char **)NULL;
+ static int list_index = 0;
+ static int first_char, first_char_loc;
+
+ /* If we don't have any state, make some. */
+ if (state == 0)
+ {
+ FREE (list);
+
+ list = (char **)NULL;
+
+ first_char_loc = 0;
+ first_char = *text;
+
+ if (first_char == '@')
+ first_char_loc++;
+
+ list = hostnames_matching ((char *)text+first_char_loc);
+ list_index = 0;
+ }
+
+ if (list && list[list_index])
+ {
+ char *t;
+
+ t = (char *)xmalloc (2 + strlen (list[list_index]));
+ *t = first_char;
+ strcpy (t + first_char_loc, list[list_index]);
+ list_index++;
+ return (t);
+ }
+
+ return ((char *)NULL);
+}
+
+/*
+ * A completion function for service names from /etc/services (or wherever).
+ */
+char *
+bash_servicename_completion_function (text, state)
+ const char *text;
+ int state;
+{
+#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GETSERVENT)
+ return ((char *)NULL);
+#else
+ static char *sname = (char *)NULL;
+ static struct servent *srvent;
+ static int snamelen, firstc;
+ char *value;
+ char **alist, *aentry;
+ int afound;
+
+ if (state == 0)
+ {
+ FREE (sname);
+ firstc = *text;
+
+ sname = savestring (text);
+ snamelen = strlen (sname);
+ setservent (0);
+ }
+
+ while (srvent = getservent ())
+ {
+ afound = 0;
+ if (snamelen == 0 || (STREQN (sname, srvent->s_name, snamelen)))
+ break;
+ /* Not primary, check aliases */
+ for (alist = srvent->s_aliases; *alist; alist++)
+ {
+ aentry = *alist;
+ if (STREQN (sname, aentry, snamelen))
+ {
+ afound = 1;
+ break;
+ }
+ }
+
+ if (afound)
+ break;
+ }
+
+ if (srvent == 0)
+ {
+ endservent ();
+ return ((char *)NULL);
+ }
+
+ value = afound ? savestring (aentry) : savestring (srvent->s_name);
+ return value;
+#endif
+}
+
+/*
+ * A completion function for group names from /etc/group (or wherever).
+ */
+char *
+bash_groupname_completion_function (text, state)
+ const char *text;
+ int state;
+{
+#if defined (__WIN32__) || defined (__OPENNT) || !defined (HAVE_GRP_H)
+ return ((char *)NULL);
+#else
+ static char *gname = (char *)NULL;
+ static struct group *grent;
+ static int gnamelen;
+ char *value;
+
+ if (state == 0)
+ {
+ FREE (gname);
+ gname = savestring (text);
+ gnamelen = strlen (gname);
+
+ setgrent ();
+ }
+
+ while (grent = getgrent ())
+ {
+ if (gnamelen == 0 || (STREQN (gname, grent->gr_name, gnamelen)))
+ break;
+ }
+
+ if (grent == 0)
+ {
+ endgrent ();
+ return ((char *)NULL);
+ }
+
+ value = savestring (grent->gr_name);
+ return (value);
+#endif
+}
+
+/* Functions to perform history and alias expansions on the current line. */
+
+#if defined (BANG_HISTORY)
+/* Perform history expansion on the current line. If no history expansion
+ is done, pre_process_line() returns what it was passed, so we need to
+ allocate a new line here. */
+static char *
+history_expand_line_internal (line)
+ char *line;
+{
+ char *new_line;
+ int old_verify;
+
+ old_verify = hist_verify;
+ hist_verify = 0;
+ new_line = pre_process_line (line, 0, 0);
+ hist_verify = old_verify;
+
+ return (new_line == line) ? savestring (line) : new_line;
+}
+#endif
+
+/* There was an error in expansion. Let the preprocessor print
+ the error here. */
+static void
+cleanup_expansion_error ()
+{
+ char *to_free;
+#if defined (BANG_HISTORY)
+ int old_verify;
+
+ old_verify = hist_verify;
+ hist_verify = 0;
+#endif
+
+ fprintf (rl_outstream, "\r\n");
+ to_free = pre_process_line (rl_line_buffer, 1, 0);
+#if defined (BANG_HISTORY)
+ hist_verify = old_verify;
+#endif
+ if (to_free != rl_line_buffer)
+ FREE (to_free);
+ putc ('\r', rl_outstream);
+ rl_forced_update_display ();
+}
+
+/* If NEW_LINE differs from what is in the readline line buffer, add an
+ undo record to get from the readline line buffer contents to the new
+ line and make NEW_LINE the current readline line. */
+static void
+maybe_make_readline_line (new_line)
+ char *new_line;
+{
+ if (strcmp (new_line, rl_line_buffer) != 0)
+ {
+ rl_point = rl_end;
+
+ rl_add_undo (UNDO_BEGIN, 0, 0, 0);
+ rl_delete_text (0, rl_point);
+ rl_point = rl_end = rl_mark = 0;
+ rl_insert_text (new_line);
+ rl_add_undo (UNDO_END, 0, 0, 0);
+ }
+}
+
+/* Make NEW_LINE be the current readline line. This frees NEW_LINE. */
+static void
+set_up_new_line (new_line)
+ char *new_line;
+{
+ int old_point, at_end;
+
+ old_point = rl_point;
+ at_end = rl_point == rl_end;
+
+ /* If the line was history and alias expanded, then make that
+ be one thing to undo. */
+ maybe_make_readline_line (new_line);
+ free (new_line);
+
+ /* Place rl_point where we think it should go. */
+ if (at_end)
+ rl_point = rl_end;
+ else if (old_point < rl_end)
+ {
+ rl_point = old_point;
+ if (!whitespace (rl_line_buffer[rl_point]))
+ rl_forward_word (1, 0);
+ }
+}
+
+#if defined (ALIAS)
+/* Expand aliases in the current readline line. */
+static int
+alias_expand_line (count, ignore)
+ int count, ignore;
+{
+ char *new_line;
+
+ new_line = alias_expand (rl_line_buffer);
+
+ if (new_line)
+ {
+ set_up_new_line (new_line);
+ return (0);
+ }
+ else
+ {
+ cleanup_expansion_error ();
+ return (1);
+ }
+}
+#endif
+
+#if defined (BANG_HISTORY)
+/* History expand the line. */
+static int
+history_expand_line (count, ignore)
+ int count, ignore;
+{
+ char *new_line;
+
+ new_line = history_expand_line_internal (rl_line_buffer);
+
+ if (new_line)
+ {
+ set_up_new_line (new_line);
+ return (0);
+ }
+ else
+ {
+ cleanup_expansion_error ();
+ return (1);
+ }
+}
+
+/* Expand history substitutions in the current line and then insert a
+ space (hopefully close to where we were before). */
+static int
+tcsh_magic_space (count, ignore)
+ int count, ignore;
+{
+ int dist_from_end, old_point;
+
+ old_point = rl_point;
+ dist_from_end = rl_end - rl_point;
+ if (history_expand_line (count, ignore) == 0)
+ {
+ /* Try a simple heuristic from Stephen Gildea <gildea@intouchsys.com>.
+ This works if all expansions were before rl_point or if no expansions
+ were performed. */
+ rl_point = (old_point == 0) ? old_point : rl_end - dist_from_end;
+ rl_insert (1, ' ');
+ return (0);
+ }
+ else
+ return (1);
+}
+#endif /* BANG_HISTORY */
+
+/* History and alias expand the line. */
+static int
+history_and_alias_expand_line (count, ignore)
+ int count, ignore;
+{
+ char *new_line;
+
+ new_line = 0;
+#if defined (BANG_HISTORY)
+ new_line = history_expand_line_internal (rl_line_buffer);
+#endif
+
+#if defined (ALIAS)
+ if (new_line)
+ {
+ char *alias_line;
+
+ alias_line = alias_expand (new_line);
+ free (new_line);
+ new_line = alias_line;
+ }
+#endif /* ALIAS */
+
+ if (new_line)
+ {
+ set_up_new_line (new_line);
+ return (0);
+ }
+ else
+ {
+ cleanup_expansion_error ();
+ return (1);
+ }
+}
+
+/* History and alias expand the line, then perform the shell word
+ expansions by calling expand_string. This can't use set_up_new_line()
+ because we want the variable expansions as a separate undo'able
+ set of operations. */
+static int
+shell_expand_line (count, ignore)
+ int count, ignore;
+{
+ char *new_line;
+ WORD_LIST *expanded_string;
+
+ new_line = 0;
+#if defined (BANG_HISTORY)
+ new_line = history_expand_line_internal (rl_line_buffer);
+#endif
+
+#if defined (ALIAS)
+ if (new_line)
+ {
+ char *alias_line;
+
+ alias_line = alias_expand (new_line);
+ free (new_line);
+ new_line = alias_line;
+ }
+#endif /* ALIAS */
+
+ if (new_line)
+ {
+ int old_point = rl_point;
+ int at_end = rl_point == rl_end;
+
+ /* If the line was history and alias expanded, then make that
+ be one thing to undo. */
+ maybe_make_readline_line (new_line);
+ free (new_line);
+
+ /* If there is variable expansion to perform, do that as a separate
+ operation to be undone. */
+ new_line = savestring (rl_line_buffer);
+ expanded_string = expand_string (new_line, 0);
+ FREE (new_line);
+ if (expanded_string == 0)
+ {
+ new_line = (char *)xmalloc (1);
+ new_line[0] = '\0';
+ }
+ else
+ {
+ new_line = string_list (expanded_string);
+ dispose_words (expanded_string);
+ }
+
+ maybe_make_readline_line (new_line);
+ free (new_line);
+
+ /* Place rl_point where we think it should go. */
+ if (at_end)
+ rl_point = rl_end;
+ else if (old_point < rl_end)
+ {
+ rl_point = old_point;
+ if (!whitespace (rl_line_buffer[rl_point]))
+ rl_forward_word (1, 0);
+ }
+ return 0;
+ }
+ else
+ {
+ cleanup_expansion_error ();
+ return 1;
+ }
+}
+
+/* If FIGNORE is set, then don't match files with the given suffixes when
+ completing filenames. If only one of the possibilities has an acceptable
+ suffix, delete the others, else just return and let the completer
+ signal an error. It is called by the completer when real
+ completions are done on filenames by the completer's internal
+ function, not for completion lists (M-?) and not on "other"
+ completion types, such as hostnames or commands. */
+
+static struct ignorevar fignore =
+{
+ "FIGNORE",
+ (struct ign *)0,
+ 0,
+ (char *)0,
+ (sh_iv_item_func_t *) 0,
+};
+
+static void
+_ignore_completion_names (names, name_func)
+ char **names;
+ sh_ignore_func_t *name_func;
+{
+ char **newnames;
+ int idx, nidx;
+ char **oldnames;
+ int oidx;
+
+ /* If there is only one completion, see if it is acceptable. If it is
+ not, free it up. In any case, short-circuit and return. This is a
+ special case because names[0] is not the prefix of the list of names
+ if there is only one completion; it is the completion itself. */
+ if (names[1] == (char *)0)
+ {
+ if (force_fignore)
+ if ((*name_func) (names[0]) == 0)
+ {
+ free (names[0]);
+ names[0] = (char *)NULL;
+ }
+
+ return;
+ }
+
+ /* Allocate space for array to hold list of pointers to matching
+ filenames. The pointers are copied back to NAMES when done. */
+ for (nidx = 1; names[nidx]; nidx++)
+ ;
+ newnames = strvec_create (nidx + 1);
+
+ if (force_fignore == 0)
+ {
+ oldnames = strvec_create (nidx - 1);
+ oidx = 0;
+ }
+
+ newnames[0] = names[0];
+ for (idx = nidx = 1; names[idx]; idx++)
+ {
+ if ((*name_func) (names[idx]))
+ newnames[nidx++] = names[idx];
+ else if (force_fignore == 0)
+ oldnames[oidx++] = names[idx];
+ else
+ free (names[idx]);
+ }
+
+ newnames[nidx] = (char *)NULL;
+
+ /* If none are acceptable then let the completer handle it. */
+ if (nidx == 1)
+ {
+ if (force_fignore)
+ {
+ free (names[0]);
+ names[0] = (char *)NULL;
+ }
+ else
+ free (oldnames);
+
+ free (newnames);
+ return;
+ }
+
+ if (force_fignore == 0)
+ {
+ while (oidx)
+ free (oldnames[--oidx]);
+ free (oldnames);
+ }
+
+ /* If only one is acceptable, copy it to names[0] and return. */
+ if (nidx == 2)
+ {
+ free (names[0]);
+ names[0] = newnames[1];
+ names[1] = (char *)NULL;
+ free (newnames);
+ return;
+ }
+
+ /* Copy the acceptable names back to NAMES, set the new array end,
+ and return. */
+ for (nidx = 1; newnames[nidx]; nidx++)
+ names[nidx] = newnames[nidx];
+ names[nidx] = (char *)NULL;
+ free (newnames);
+}
+
+static int
+name_is_acceptable (name)
+ const char *name;
+{
+ struct ign *p;
+ int nlen;
+
+ for (nlen = strlen (name), p = fignore.ignores; p->val; p++)
+ {
+ if (nlen > p->len && p->len > 0 && STREQ (p->val, &name[nlen - p->len]))
+ return (0);
+ }
+
+ return (1);
+}
+
+#if 0
+static int
+ignore_dot_names (name)
+ char *name;
+{
+ return (name[0] != '.');
+}
+#endif
+
+static int
+filename_completion_ignore (names)
+ char **names;
+{
+#if 0
+ if (glob_dot_filenames == 0)
+ _ignore_completion_names (names, ignore_dot_names);
+#endif
+
+ setup_ignore_patterns (&fignore);
+
+ if (fignore.num_ignores == 0)
+ return 0;
+
+ _ignore_completion_names (names, name_is_acceptable);
+
+ return 0;
+}
+
+/* Return 1 if NAME is a directory. NAME undergoes tilde expansion. */
+static int
+test_for_directory (name)
+ const char *name;
+{
+ char *fn;
+ int r;
+
+ fn = bash_tilde_expand (name, 0);
+ r = file_isdir (fn);
+ free (fn);
+
+ return (r);
+}
+
+/* Remove files from NAMES, leaving directories. */
+static int
+bash_ignore_filenames (names)
+ char **names;
+{
+ _ignore_completion_names (names, test_for_directory);
+ return 0;
+}
+
+static int
+return_zero (name)
+ const char *name;
+{
+ return 0;
+}
+
+static int
+bash_ignore_everything (names)
+ char **names;
+{
+ _ignore_completion_names (names, return_zero);
+ return 0;
+}
+
+/* Replace a tilde-prefix in VAL with a `~', assuming the user typed it. VAL
+ is an expanded filename. DIRECTORY_PART is the tilde-prefix portion
+ of the un-tilde-expanded version of VAL (what the user typed). */
+static char *
+restore_tilde (val, directory_part)
+ char *val, *directory_part;
+{
+ int l, vl, dl2, xl;
+ char *dh2, *expdir, *ret;
+
+ vl = strlen (val);
+
+ /* We need to duplicate the expansions readline performs on the directory
+ portion before passing it to our completion function. */
+ dh2 = directory_part ? bash_dequote_filename (directory_part, 0) : 0;
+ bash_directory_expansion (&dh2);
+ dl2 = strlen (dh2);
+
+ expdir = bash_tilde_expand (directory_part, 0);
+ xl = strlen (expdir);
+ free (expdir);
+
+ /*
+ dh2 = unexpanded but dequoted tilde-prefix
+ dl2 = length of tilde-prefix
+ expdir = tilde-expanded tilde-prefix
+ xl = length of expanded tilde-prefix
+ l = length of remainder after tilde-prefix
+ */
+ l = (vl - xl) + 1;
+
+ ret = (char *)xmalloc (dl2 + 2 + l);
+ strcpy (ret, dh2);
+ strcpy (ret + dl2, val + xl);
+
+ free (dh2);
+ return (ret);
+}
+
+/* Simulate the expansions that will be performed by
+ rl_filename_completion_function. This must be called with the address of
+ a pointer to malloc'd memory. */
+static void
+bash_directory_expansion (dirname)
+ char **dirname;
+{
+ char *d, *nd;
+
+ d = savestring (*dirname);
+
+ if ((rl_directory_rewrite_hook) && (*rl_directory_rewrite_hook) (&d))
+ {
+ free (*dirname);
+ *dirname = d;
+ }
+ else if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&d))
+ {
+ free (*dirname);
+ *dirname = d;
+ }
+ else if (rl_completion_found_quote)
+ {
+ nd = bash_dequote_filename (d, rl_completion_quote_character);
+ free (*dirname);
+ free (d);
+ *dirname = nd;
+ }
+}
+
+/* If necessary, rewrite directory entry */
+static char *
+bash_filename_rewrite_hook (fname, fnlen)
+ char *fname;
+ int fnlen;
+{
+ char *conv;
+
+ conv = fnx_fromfs (fname, fnlen);
+ if (conv != fname)
+ conv = savestring (conv);
+ return conv;
+}
+
+/* Functions to save and restore the appropriate directory hook */
+/* This is not static so the shopt code can call it */
+void
+set_directory_hook ()
+{
+ if (dircomplete_expand)
+ {
+ rl_directory_completion_hook = bash_directory_completion_hook;
+ rl_directory_rewrite_hook = (rl_icppfunc_t *)0;
+ }
+ else
+ {
+ rl_directory_rewrite_hook = bash_directory_completion_hook;
+ rl_directory_completion_hook = (rl_icppfunc_t *)0;
+ }
+}
+
+static rl_icppfunc_t *
+save_directory_hook ()
+{
+ rl_icppfunc_t *ret;
+
+ if (dircomplete_expand)
+ {
+ ret = rl_directory_completion_hook;
+ rl_directory_completion_hook = (rl_icppfunc_t *)NULL;
+ }
+ else
+ {
+ ret = rl_directory_rewrite_hook;
+ rl_directory_rewrite_hook = (rl_icppfunc_t *)NULL;
+ }
+
+ return ret;
+}
+
+static void
+restore_directory_hook (hookf)
+ rl_icppfunc_t *hookf;
+{
+ if (dircomplete_expand)
+ rl_directory_completion_hook = hookf;
+ else
+ rl_directory_rewrite_hook = hookf;
+}
+
+/* Expand a filename before the readline completion code passes it to stat(2).
+ The filename will already have had tilde expansion performed. */
+static int
+bash_filename_stat_hook (dirname)
+ char **dirname;
+{
+ char *local_dirname, *new_dirname, *t;
+ int should_expand_dirname, return_value;
+ WORD_LIST *wl;
+ struct stat sb;
+
+ local_dirname = *dirname;
+ should_expand_dirname = return_value = 0;
+ if (t = mbschr (local_dirname, '$'))
+ should_expand_dirname = '$';
+ else if (t = mbschr (local_dirname, '`')) /* XXX */
+ should_expand_dirname = '`';
+
+#if defined (HAVE_LSTAT)
+ if (should_expand_dirname && lstat (local_dirname, &sb) == 0)
+#else
+ if (should_expand_dirname && stat (local_dirname, &sb) == 0)
+#endif
+ should_expand_dirname = 0;
+
+ if (should_expand_dirname)
+ {
+ new_dirname = savestring (local_dirname);
+ wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB); /* does the right thing */
+ if (wl)
+ {
+ free (new_dirname);
+ new_dirname = string_list (wl);
+ /* Tell the completer we actually expanded something and change
+ *dirname only if we expanded to something non-null -- stat
+ behaves unpredictably when passed null or empty strings */
+ if (new_dirname && *new_dirname)
+ {
+ free (local_dirname); /* XXX */
+ local_dirname = *dirname = new_dirname;
+ return_value = STREQ (local_dirname, *dirname) == 0;
+ }
+ else
+ free (new_dirname);
+ dispose_words (wl);
+ }
+ else
+ free (new_dirname);
+ }
+
+ /* This is very similar to the code in bash_directory_completion_hook below,
+ but without spelling correction and not worrying about whether or not
+ we change relative pathnames. */
+ if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1]))
+ {
+ char *temp1, *temp2;
+
+ t = get_working_directory ("symlink-hook");
+ temp1 = make_absolute (local_dirname, t);
+ free (t);
+ temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+
+ /* If we can't canonicalize, bail. */
+ if (temp2 == 0)
+ {
+ free (temp1);
+ return return_value;
+ }
+
+ free (local_dirname);
+ *dirname = temp2;
+ free (temp1);
+ }
+
+ return (return_value);
+}
+
+/* Handle symbolic link references and other directory name
+ expansions while hacking completion. This should return 1 if it modifies
+ the DIRNAME argument, 0 otherwise. It should make sure not to modify
+ DIRNAME if it returns 0. */
+static int
+bash_directory_completion_hook (dirname)
+ char **dirname;
+{
+ char *local_dirname, *new_dirname, *t;
+ int return_value, should_expand_dirname, nextch, closer;
+ WORD_LIST *wl;
+ struct stat sb;
+
+ return_value = should_expand_dirname = nextch = closer = 0;
+ local_dirname = *dirname;
+
+ if (t = mbschr (local_dirname, '$'))
+ {
+ should_expand_dirname = '$';
+ nextch = t[1];
+ /* Deliberately does not handle the deprecated $[...] arithmetic
+ expansion syntax */
+ if (nextch == '(')
+ closer = ')';
+ else if (nextch == '{')
+ closer = '}';
+ else
+ nextch = 0;
+ }
+ else if (local_dirname[0] == '~')
+ should_expand_dirname = '~';
+ else
+ {
+ t = mbschr (local_dirname, '`');
+ if (t && unclosed_pair (local_dirname, strlen (local_dirname), "`") == 0)
+ should_expand_dirname = '`';
+ }
+
+#if defined (HAVE_LSTAT)
+ if (should_expand_dirname && lstat (local_dirname, &sb) == 0)
+#else
+ if (should_expand_dirname && stat (local_dirname, &sb) == 0)
+#endif
+ should_expand_dirname = 0;
+
+ if (should_expand_dirname)
+ {
+ new_dirname = savestring (local_dirname);
+ wl = expand_prompt_string (new_dirname, 0, W_NOCOMSUB); /* does the right thing */
+ if (wl)
+ {
+ *dirname = string_list (wl);
+ /* Tell the completer to replace the directory name only if we
+ actually expanded something. */
+ return_value = STREQ (local_dirname, *dirname) == 0;
+ free (local_dirname);
+ free (new_dirname);
+ dispose_words (wl);
+ local_dirname = *dirname;
+ /* XXX - change rl_filename_quote_characters here based on
+ should_expand_dirname/nextch/closer. This is the only place
+ custom_filename_quote_characters is modified. */
+ if (rl_filename_quote_characters && *rl_filename_quote_characters)
+ {
+ int i, j, c;
+ i = strlen (default_filename_quote_characters);
+ custom_filename_quote_characters = xrealloc (custom_filename_quote_characters, i+1);
+ for (i = j = 0; c = default_filename_quote_characters[i]; i++)
+ {
+ if (c == should_expand_dirname || c == nextch || c == closer)
+ continue;
+ custom_filename_quote_characters[j++] = c;
+ }
+ custom_filename_quote_characters[j] = '\0';
+ rl_filename_quote_characters = custom_filename_quote_characters;
+ set_filename_bstab (rl_filename_quote_characters);
+ }
+ }
+ else
+ {
+ free (new_dirname);
+ free (local_dirname);
+ *dirname = (char *)xmalloc (1);
+ **dirname = '\0';
+ return 1;
+ }
+ }
+ else
+ {
+ /* Dequote the filename even if we don't expand it. */
+ new_dirname = bash_dequote_filename (local_dirname, rl_completion_quote_character);
+ return_value = STREQ (local_dirname, new_dirname) == 0;
+ free (local_dirname);
+ local_dirname = *dirname = new_dirname;
+ }
+
+ /* no_symbolic_links == 0 -> use (default) logical view of the file system.
+ local_dirname[0] == '.' && local_dirname[1] == '/' means files in the
+ current directory (./).
+ local_dirname[0] == '.' && local_dirname[1] == 0 means relative pathnames
+ in the current directory (e.g., lib/sh).
+ XXX - should we do spelling correction on these? */
+
+ /* This is test as it was in bash-4.2: skip relative pathnames in current
+ directory. Change test to
+ (local_dirname[0] != '.' || (local_dirname[1] && local_dirname[1] != '/'))
+ if we want to skip paths beginning with ./ also. */
+ if (no_symbolic_links == 0 && (local_dirname[0] != '.' || local_dirname[1]))
+ {
+ char *temp1, *temp2;
+ int len1, len2;
+
+ /* If we have a relative path
+ (local_dirname[0] != '/' && local_dirname[0] != '.')
+ that is canonical after appending it to the current directory, then
+ temp1 = temp2+'/'
+ That is,
+ strcmp (temp1, temp2) == 0
+ after adding a slash to temp2 below. It should be safe to not
+ change those.
+ */
+ t = get_working_directory ("symlink-hook");
+ temp1 = make_absolute (local_dirname, t);
+ free (t);
+ temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+
+ /* Try spelling correction if initial canonicalization fails. Make
+ sure we are set to replace the directory name with the results so
+ subsequent directory checks don't fail. */
+ if (temp2 == 0 && dircomplete_spelling && dircomplete_expand)
+ {
+ temp2 = dirspell (temp1);
+ if (temp2)
+ {
+ free (temp1);
+ temp1 = temp2;
+ temp2 = sh_canonpath (temp1, PATH_CHECKDOTDOT|PATH_CHECKEXISTS);
+ return_value |= temp2 != 0;
+ }
+ }
+ /* If we can't canonicalize, bail. */
+ if (temp2 == 0)
+ {
+ free (temp1);
+ return return_value;
+ }
+ len1 = strlen (temp1);
+ if (temp1[len1 - 1] == '/')
+ {
+ len2 = strlen (temp2);
+ if (len2 > 2) /* don't append `/' to `/' or `//' */
+ {
+ temp2 = (char *)xrealloc (temp2, len2 + 2);
+ temp2[len2] = '/';
+ temp2[len2 + 1] = '\0';
+ }
+ }
+
+ /* dircomplete_expand_relpath == 0 means we want to leave relative
+ pathnames that are unchanged by canonicalization alone.
+ *local_dirname != '/' && *local_dirname != '.' == relative pathname
+ (consistent with general.c:absolute_pathname())
+ temp1 == temp2 (after appending a slash to temp2) means the pathname
+ is not changed by canonicalization as described above. */
+ if (dircomplete_expand_relpath || ((local_dirname[0] != '/' && local_dirname[0] != '.') && STREQ (temp1, temp2) == 0))
+ return_value |= STREQ (local_dirname, temp2) == 0;
+ free (local_dirname);
+ *dirname = temp2;
+ free (temp1);
+ }
+
+ return (return_value);
+}
+
+static char **history_completion_array = (char **)NULL;
+static int harry_size;
+static int harry_len;
+
+static void
+build_history_completion_array ()
+{
+ register int i, j;
+ HIST_ENTRY **hlist;
+ char **tokens;
+
+ /* First, clear out the current dynamic history completion list. */
+ if (harry_size)
+ {
+ strvec_dispose (history_completion_array);
+ history_completion_array = (char **)NULL;
+ harry_size = 0;
+ harry_len = 0;
+ }
+
+ /* Next, grovel each line of history, making each shell-sized token
+ a separate entry in the history_completion_array. */
+ hlist = history_list ();
+
+ if (hlist)
+ {
+ for (i = 0; hlist[i]; i++)
+ ;
+ for ( --i; i >= 0; i--)
+ {
+ /* Separate each token, and place into an array. */
+ tokens = history_tokenize (hlist[i]->line);
+
+ for (j = 0; tokens && tokens[j]; j++)
+ {
+ if (harry_len + 2 > harry_size)
+ history_completion_array = strvec_resize (history_completion_array, harry_size += 10);
+
+ history_completion_array[harry_len++] = tokens[j];
+ history_completion_array[harry_len] = (char *)NULL;
+ }
+ free (tokens);
+ }
+
+ /* Sort the complete list of tokens. */
+ if (dabbrev_expand_active == 0)
+ qsort (history_completion_array, harry_len, sizeof (char *), (QSFUNC *)strvec_strcmp);
+ }
+}
+
+static char *
+history_completion_generator (hint_text, state)
+ const char *hint_text;
+ int state;
+{
+ static int local_index, len;
+ static const char *text;
+
+ /* If this is the first call to the generator, then initialize the
+ list of strings to complete over. */
+ if (state == 0)
+ {
+ if (dabbrev_expand_active) /* This is kind of messy */
+ rl_completion_suppress_append = 1;
+ local_index = 0;
+ build_history_completion_array ();
+ text = hint_text;
+ len = strlen (text);
+ }
+
+ while (history_completion_array && history_completion_array[local_index])
+ {
+ if (strncmp (text, history_completion_array[local_index++], len) == 0)
+ return (savestring (history_completion_array[local_index - 1]));
+ }
+ return ((char *)NULL);
+}
+
+static int
+dynamic_complete_history (count, key)
+ int count, key;
+{
+ int r;
+ rl_compentry_func_t *orig_func;
+ rl_completion_func_t *orig_attempt_func;
+ rl_compignore_func_t *orig_ignore_func;
+
+ orig_func = rl_completion_entry_function;
+ orig_attempt_func = rl_attempted_completion_function;
+ orig_ignore_func = rl_ignore_some_completions_function;
+
+ rl_completion_entry_function = history_completion_generator;
+ rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+ rl_ignore_some_completions_function = filename_completion_ignore;
+
+ /* XXX - use rl_completion_mode here? */
+ if (rl_last_func == dynamic_complete_history)
+ r = rl_complete_internal ('?');
+ else
+ r = rl_complete_internal (TAB);
+
+ rl_completion_entry_function = orig_func;
+ rl_attempted_completion_function = orig_attempt_func;
+ rl_ignore_some_completions_function = orig_ignore_func;
+
+ return r;
+}
+
+static int
+bash_dabbrev_expand (count, key)
+ int count, key;
+{
+ int r, orig_suppress, orig_sort;
+ rl_compentry_func_t *orig_func;
+ rl_completion_func_t *orig_attempt_func;
+ rl_compignore_func_t *orig_ignore_func;
+
+ orig_func = rl_menu_completion_entry_function;
+ orig_attempt_func = rl_attempted_completion_function;
+ orig_ignore_func = rl_ignore_some_completions_function;
+ orig_suppress = rl_completion_suppress_append;
+ orig_sort = rl_sort_completion_matches;
+
+ rl_menu_completion_entry_function = history_completion_generator;
+ rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+ rl_ignore_some_completions_function = filename_completion_ignore;
+ rl_filename_completion_desired = 0;
+ rl_completion_suppress_append = 1;
+ rl_sort_completion_matches = 0;
+
+ /* XXX - use rl_completion_mode here? */
+ dabbrev_expand_active = 1;
+ if (rl_last_func == bash_dabbrev_expand)
+ rl_last_func = rl_menu_complete;
+ r = rl_menu_complete (count, key);
+ dabbrev_expand_active = 0;
+
+ rl_last_func = bash_dabbrev_expand;
+ rl_menu_completion_entry_function = orig_func;
+ rl_attempted_completion_function = orig_attempt_func;
+ rl_ignore_some_completions_function = orig_ignore_func;
+ rl_completion_suppress_append = orig_suppress;
+ rl_sort_completion_matches = orig_sort;
+
+ return r;
+}
+
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+static int
+bash_complete_username (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_username_internal (rl_completion_mode (bash_complete_username));
+}
+
+static int
+bash_possible_username_completions (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_username_internal ('?');
+}
+
+static int
+bash_complete_username_internal (what_to_do)
+ int what_to_do;
+{
+ return bash_specific_completion (what_to_do, rl_username_completion_function);
+}
+
+static int
+bash_complete_filename (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_filename_internal (rl_completion_mode (bash_complete_filename));
+}
+
+static int
+bash_possible_filename_completions (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_filename_internal ('?');
+}
+
+static int
+bash_complete_filename_internal (what_to_do)
+ int what_to_do;
+{
+ rl_compentry_func_t *orig_func;
+ rl_completion_func_t *orig_attempt_func;
+ rl_icppfunc_t *orig_dir_func;
+ rl_compignore_func_t *orig_ignore_func;
+ /*const*/ char *orig_rl_completer_word_break_characters;
+ int r;
+
+ orig_func = rl_completion_entry_function;
+ orig_attempt_func = rl_attempted_completion_function;
+ orig_ignore_func = rl_ignore_some_completions_function;
+ orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
+
+ orig_dir_func = save_directory_hook ();
+
+ rl_completion_entry_function = rl_filename_completion_function;
+ rl_attempted_completion_function = (rl_completion_func_t *)NULL;
+ rl_ignore_some_completions_function = filename_completion_ignore;
+ rl_completer_word_break_characters = " \t\n\"\'";
+
+ r = rl_complete_internal (what_to_do);
+
+ rl_completion_entry_function = orig_func;
+ rl_attempted_completion_function = orig_attempt_func;
+ rl_ignore_some_completions_function = orig_ignore_func;
+ rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
+
+ restore_directory_hook (orig_dir_func);
+
+ return r;
+}
+
+static int
+bash_complete_hostname (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_hostname_internal (rl_completion_mode (bash_complete_hostname));
+}
+
+static int
+bash_possible_hostname_completions (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_hostname_internal ('?');
+}
+
+static int
+bash_complete_variable (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_variable_internal (rl_completion_mode (bash_complete_variable));
+}
+
+static int
+bash_possible_variable_completions (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_variable_internal ('?');
+}
+
+static int
+bash_complete_command (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_command_internal (rl_completion_mode (bash_complete_command));
+}
+
+static int
+bash_possible_command_completions (ignore, ignore2)
+ int ignore, ignore2;
+{
+ return bash_complete_command_internal ('?');
+}
+
+static int
+bash_complete_hostname_internal (what_to_do)
+ int what_to_do;
+{
+ return bash_specific_completion (what_to_do, hostname_completion_function);
+}
+
+static int
+bash_complete_variable_internal (what_to_do)
+ int what_to_do;
+{
+ return bash_specific_completion (what_to_do, variable_completion_function);
+}
+
+static int
+bash_complete_command_internal (what_to_do)
+ int what_to_do;
+{
+ return bash_specific_completion (what_to_do, command_word_completion_function);
+}
+
+static char *globtext;
+static char *globorig;
+
+static char *
+glob_complete_word (text, state)
+ const char *text;
+ int state;
+{
+ static char **matches = (char **)NULL;
+ static int ind;
+ int glen;
+ char *ret, *ttext;
+
+ if (state == 0)
+ {
+ rl_filename_completion_desired = 1;
+ FREE (matches);
+ if (globorig != globtext)
+ FREE (globorig);
+ FREE (globtext);
+
+ ttext = bash_tilde_expand (text, 0);
+
+ if (rl_explicit_arg)
+ {
+ globorig = savestring (ttext);
+ glen = strlen (ttext);
+ globtext = (char *)xmalloc (glen + 2);
+ strcpy (globtext, ttext);
+ globtext[glen] = '*';
+ globtext[glen+1] = '\0';
+ }
+ else
+ globtext = globorig = savestring (ttext);
+
+ if (ttext != text)
+ free (ttext);
+
+ matches = shell_glob_filename (globtext);
+ if (GLOB_FAILED (matches))
+ matches = (char **)NULL;
+ ind = 0;
+ }
+
+ ret = matches ? matches[ind] : (char *)NULL;
+ ind++;
+ return ret;
+}
+
+static int
+bash_glob_completion_internal (what_to_do)
+ int what_to_do;
+{
+ return bash_specific_completion (what_to_do, glob_complete_word);
+}
+
+/* A special quoting function so we don't end up quoting globbing characters
+ in the word if there are no matches or multiple matches. */
+static char *
+bash_glob_quote_filename (s, rtype, qcp)
+ char *s;
+ int rtype;
+ char *qcp;
+{
+ if (globorig && qcp && *qcp == '\0' && STREQ (s, globorig))
+ return (savestring (s));
+ else
+ return (bash_quote_filename (s, rtype, qcp));
+}
+
+static int
+bash_glob_complete_word (count, key)
+ int count, key;
+{
+ int r;
+ rl_quote_func_t *orig_quoting_function;
+
+ if (rl_editing_mode == EMACS_EDITING_MODE)
+ rl_explicit_arg = 1; /* force `*' append */
+ orig_quoting_function = rl_filename_quoting_function;
+ rl_filename_quoting_function = bash_glob_quote_filename;
+
+ r = bash_glob_completion_internal (rl_completion_mode (bash_glob_complete_word));
+
+ rl_filename_quoting_function = orig_quoting_function;
+ return r;
+}
+
+static int
+bash_glob_expand_word (count, key)
+ int count, key;
+{
+ return bash_glob_completion_internal ('*');
+}
+
+static int
+bash_glob_list_expansions (count, key)
+ int count, key;
+{
+ return bash_glob_completion_internal ('?');
+}
+
+static int
+bash_specific_completion (what_to_do, generator)
+ int what_to_do;
+ rl_compentry_func_t *generator;
+{
+ rl_compentry_func_t *orig_func;
+ rl_completion_func_t *orig_attempt_func;
+ rl_compignore_func_t *orig_ignore_func;
+ int r;
+
+ orig_func = rl_completion_entry_function;
+ orig_attempt_func = rl_attempted_completion_function;
+ orig_ignore_func = rl_ignore_some_completions_function;
+ rl_completion_entry_function = generator;
+ rl_attempted_completion_function = NULL;
+ rl_ignore_some_completions_function = orig_ignore_func;
+
+ r = rl_complete_internal (what_to_do);
+
+ rl_completion_entry_function = orig_func;
+ rl_attempted_completion_function = orig_attempt_func;
+ rl_ignore_some_completions_function = orig_ignore_func;
+
+ return r;
+}
+
+#endif /* SPECIFIC_COMPLETION_FUNCTIONS */
+
+#if defined (VI_MODE)
+/* Completion, from vi mode's point of view. This is a modified version of
+ rl_vi_complete which uses the bash globbing code to implement what POSIX
+ specifies, which is to append a `*' and attempt filename generation (which
+ has the side effect of expanding any globbing characters in the word). */
+static int
+bash_vi_complete (count, key)
+ int count, key;
+{
+#if defined (SPECIFIC_COMPLETION_FUNCTIONS)
+ int p, r;
+ char *t;
+
+ if ((rl_point < rl_end) && (!whitespace (rl_line_buffer[rl_point])))
+ {
+ if (!whitespace (rl_line_buffer[rl_point + 1]))
+ rl_vi_end_word (1, 'E');
+ rl_point++;
+ }
+
+ /* Find boundaries of current word, according to vi definition of a
+ `bigword'. */
+ t = 0;
+ if (rl_point > 0)
+ {
+ p = rl_point;
+ rl_vi_bWord (1, 'B');
+ r = rl_point;
+ rl_point = p;
+ p = r;
+
+ t = substring (rl_line_buffer, p, rl_point);
+ }
+
+ if (t && glob_pattern_p (t) == 0)
+ rl_explicit_arg = 1; /* XXX - force glob_complete_word to append `*' */
+ FREE (t);
+
+ if (key == '*') /* Expansion and replacement. */
+ r = bash_glob_expand_word (count, key);
+ else if (key == '=') /* List possible completions. */
+ r = bash_glob_list_expansions (count, key);
+ else if (key == '\\') /* Standard completion */
+ r = bash_glob_complete_word (count, key);
+ else
+ r = rl_complete (0, key);
+
+ if (key == '*' || key == '\\')
+ rl_vi_start_inserting (key, 1, 1);
+
+ return (r);
+#else
+ return rl_vi_complete (count, key);
+#endif /* !SPECIFIC_COMPLETION_FUNCTIONS */
+}
+#endif /* VI_MODE */
+
+/* Filename quoting for completion. */
+/* A function to strip unquoted quote characters (single quotes, double
+ quotes, and backslashes). It allows single quotes to appear
+ within double quotes, and vice versa. It should be smarter. */
+static char *
+bash_dequote_filename (text, quote_char)
+ char *text;
+ int quote_char;
+{
+ char *ret, *p, *r;
+ int l, quoted;
+
+ l = strlen (text);
+ ret = (char *)xmalloc (l + 1);
+ for (quoted = quote_char, p = text, r = ret; p && *p; p++)
+ {
+ /* Allow backslash-escaped characters to pass through unscathed. */
+ if (*p == '\\')
+ {
+ /* Backslashes are preserved within single quotes. */
+ if (quoted == '\'')
+ *r++ = *p;
+ /* Backslashes are preserved within double quotes unless the
+ character is one that is defined to be escaped */
+ else if (quoted == '"' && ((sh_syntaxtab[p[1]] & CBSDQUOTE) == 0))
+ *r++ = *p;
+
+ *r++ = *++p;
+ if (*p == '\0')
+ return ret; /* XXX - was break; */
+ continue;
+ }
+ /* Close quote. */
+ if (quoted && *p == quoted)
+ {
+ quoted = 0;
+ continue;
+ }
+ /* Open quote. */
+ if (quoted == 0 && (*p == '\'' || *p == '"'))
+ {
+ quoted = *p;
+ continue;
+ }
+ *r++ = *p;
+ }
+ *r = '\0';
+ return ret;
+}
+
+/* Quote characters that the readline completion code would treat as
+ word break characters with backslashes. Pass backslash-quoted
+ characters through without examination. */
+static char *
+quote_word_break_chars (text)
+ char *text;
+{
+ char *ret, *r, *s;
+ int l;
+
+ l = strlen (text);
+ ret = (char *)xmalloc ((2 * l) + 1);
+ for (s = text, r = ret; *s; s++)
+ {
+ /* Pass backslash-quoted characters through, including the backslash. */
+ if (*s == '\\')
+ {
+ *r++ = '\\';
+ *r++ = *++s;
+ if (*s == '\0')
+ break;
+ continue;
+ }
+ /* OK, we have an unquoted character. Check its presence in
+ rl_completer_word_break_characters. */
+ if (mbschr (rl_completer_word_break_characters, *s))
+ *r++ = '\\';
+ /* XXX -- check for standalone tildes here and backslash-quote them */
+ if (s == text && *s == '~' && file_exists (text))
+ *r++ = '\\';
+ *r++ = *s;
+ }
+ *r = '\0';
+ return ret;
+}
+
+/* Use characters in STRING to populate the table of characters that should
+ be backslash-quoted. The table will be used for sh_backslash_quote from
+ this file. */
+static void
+set_filename_bstab (string)
+ const char *string;
+{
+ const char *s;
+
+ memset (filename_bstab, 0, sizeof (filename_bstab));
+ for (s = string; s && *s; s++)
+ filename_bstab[*s] = 1;
+}
+
+/* Quote a filename using double quotes, single quotes, or backslashes
+ depending on the value of completion_quoting_style. If we're
+ completing using backslashes, we need to quote some additional
+ characters (those that readline treats as word breaks), so we call
+ quote_word_break_chars on the result. This returns newly-allocated
+ memory. */
+static char *
+bash_quote_filename (s, rtype, qcp)
+ char *s;
+ int rtype;
+ char *qcp;
+{
+ char *rtext, *mtext, *ret;
+ int rlen, cs;
+
+ rtext = (char *)NULL;
+
+ /* If RTYPE == MULT_MATCH, it means that there is
+ more than one match. In this case, we do not add
+ the closing quote or attempt to perform tilde
+ expansion. If RTYPE == SINGLE_MATCH, we try
+ to perform tilde expansion, because single and double
+ quotes inhibit tilde expansion by the shell. */
+
+ cs = completion_quoting_style;
+ /* Might need to modify the default completion style based on *qcp,
+ since it's set to any user-provided opening quote. We also change
+ to single-quoting if there is no user-provided opening quote and
+ the word being completed contains newlines, since those are not
+ quoted correctly using backslashes (a backslash-newline pair is
+ special to the shell parser). */
+ if (*qcp == '\0' && cs == COMPLETE_BSQUOTE && mbschr (s, '\n'))
+ cs = COMPLETE_SQUOTE;
+ else if (*qcp == '"')
+ cs = COMPLETE_DQUOTE;
+ else if (*qcp == '\'')
+ cs = COMPLETE_SQUOTE;
+#if defined (BANG_HISTORY)
+ else if (*qcp == '\0' && history_expansion && cs == COMPLETE_DQUOTE &&
+ history_expansion_inhibited == 0 && mbschr (s, '!'))
+ cs = COMPLETE_BSQUOTE;
+
+ if (*qcp == '"' && history_expansion && cs == COMPLETE_DQUOTE &&
+ history_expansion_inhibited == 0 && mbschr (s, '!'))
+ {
+ cs = COMPLETE_BSQUOTE;
+ *qcp = '\0';
+ }
+#endif
+
+ /* Don't tilde-expand backslash-quoted filenames, since only single and
+ double quotes inhibit tilde expansion. */
+ mtext = s;
+ if (mtext[0] == '~' && rtype == SINGLE_MATCH && cs != COMPLETE_BSQUOTE)
+ mtext = bash_tilde_expand (s, 0);
+
+ switch (cs)
+ {
+ case COMPLETE_DQUOTE:
+ rtext = sh_double_quote (mtext);
+ break;
+ case COMPLETE_SQUOTE:
+ rtext = sh_single_quote (mtext);
+ break;
+ case COMPLETE_BSQUOTE:
+ rtext = sh_backslash_quote (mtext, complete_fullquote ? 0 : filename_bstab, 0);
+ break;
+ }
+
+ if (mtext != s)
+ free (mtext);
+
+ /* We may need to quote additional characters: those that readline treats
+ as word breaks that are not quoted by backslash_quote. */
+ if (rtext && cs == COMPLETE_BSQUOTE)
+ {
+ mtext = quote_word_break_chars (rtext);
+ free (rtext);
+ rtext = mtext;
+ }
+
+ /* Leave the opening quote intact. The readline completion code takes
+ care of avoiding doubled opening quotes. */
+ if (rtext)
+ {
+ rlen = strlen (rtext);
+ ret = (char *)xmalloc (rlen + 1);
+ strcpy (ret, rtext);
+ }
+ else
+ {
+ ret = (char *)xmalloc (rlen = 1);
+ ret[0] = '\0';
+ }
+
+ /* If there are multiple matches, cut off the closing quote. */
+ if (rtype == MULT_MATCH && cs != COMPLETE_BSQUOTE)
+ ret[rlen - 1] = '\0';
+ free (rtext);
+ return ret;
+}
+
+/* Support for binding readline key sequences to Unix commands. */
+static Keymap cmd_xmap;
+
+#ifdef _MINIX
+static void
+#else
+static int
+#endif
+putx(c)
+ int c;
+{
+ int x;
+ x = putc (c, rl_outstream);
+#ifndef _MINIX
+ return x;
+#endif
+}
+
+static int
+bash_execute_unix_command (count, key)
+ int count; /* ignored */
+ int key;
+{
+ Keymap ckmap; /* current keymap */
+ Keymap xkmap; /* unix command executing keymap */
+ rl_command_func_t *func;
+ int type;
+ register int i, r;
+ intmax_t mi;
+ sh_parser_state_t ps;
+ char *cmd, *value, *l, *l1, *ce;
+ SHELL_VAR *v;
+ char ibuf[INT_STRLEN_BOUND(int) + 1];
+
+ /* First, we need to find the right command to execute. This is tricky,
+ because we might have already indirected into another keymap, so we
+ have to walk cmd_xmap using the entire key sequence. */
+ cmd = (char *)rl_function_of_keyseq (rl_executing_keyseq, cmd_xmap, &type);
+
+ if (cmd == 0 || type != ISMACR)
+ {
+ rl_crlf ();
+ internal_error (_("bash_execute_unix_command: cannot find keymap for command"));
+ rl_forced_update_display ();
+ return 1;
+ }
+
+ ce = rl_get_termcap ("ce");
+ if (ce) /* clear current line */
+ {
+ fprintf (rl_outstream, "\r");
+ tputs (ce, 1, putx);
+ fflush (rl_outstream);
+ }
+ else
+ rl_crlf (); /* move to a new line */
+
+ v = bind_variable ("READLINE_LINE", rl_line_buffer, 0);
+ if (v)
+ VSETATTR (v, att_exported);
+ l = v ? value_cell (v) : 0;
+ value = inttostr (rl_point, ibuf, sizeof (ibuf));
+ v = bind_int_variable ("READLINE_POINT", value);
+ if (v)
+ VSETATTR (v, att_exported);
+ array_needs_making = 1;
+
+ save_parser_state (&ps);
+ r = parse_and_execute (cmd, "bash_execute_unix_command", SEVAL_NOHIST|SEVAL_NOFREE);
+ restore_parser_state (&ps);
+
+ v = find_variable ("READLINE_LINE");
+ l1 = v ? value_cell (v) : 0;
+ if (l1 != l)
+ maybe_make_readline_line (value_cell (v));
+ v = find_variable ("READLINE_POINT");
+ if (v && legal_number (value_cell (v), &mi))
+ {
+ i = mi;
+ if (i != rl_point)
+ {
+ rl_point = i;
+ if (rl_point > rl_end)
+ rl_point = rl_end;
+ else if (rl_point < 0)
+ rl_point = 0;
+ }
+ }
+
+ unbind_variable ("READLINE_LINE");
+ unbind_variable ("READLINE_POINT");
+ array_needs_making = 1;
+
+ /* and restore the readline buffer and display after command execution. */
+ rl_forced_update_display ();
+ return 0;
+}
+
+int
+print_unix_command_map ()
+{
+ Keymap save;
+
+ save = rl_get_keymap ();
+ rl_set_keymap (cmd_xmap);
+ rl_macro_dumper (1);
+ rl_set_keymap (save);
+ return 0;
+}
+
+static void
+init_unix_command_map ()
+{
+ cmd_xmap = rl_make_bare_keymap ();
+}
+
+static int
+isolate_sequence (string, ind, need_dquote, startp)
+ char *string;
+ int ind, need_dquote, *startp;
+{
+ register int i;
+ int c, passc, delim;
+
+ for (i = ind; string[i] && whitespace (string[i]); i++)
+ ;
+ /* NEED_DQUOTE means that the first non-white character *must* be `"'. */
+ if (need_dquote && string[i] != '"')
+ {
+ builtin_error (_("%s: first non-whitespace character is not `\"'"), string);
+ return -1;
+ }
+
+ /* We can have delimited strings even if NEED_DQUOTE == 0, like the command
+ string to bind the key sequence to. */
+ delim = (string[i] == '"' || string[i] == '\'') ? string[i] : 0;
+
+ if (startp)
+ *startp = delim ? ++i : i;
+
+ for (passc = 0; c = string[i]; i++)
+ {
+ if (passc)
+ {
+ passc = 0;
+ continue;
+ }
+ if (c == '\\')
+ {
+ passc++;
+ continue;
+ }
+ if (c == delim)
+ break;
+ }
+
+ if (delim && string[i] != delim)
+ {
+ builtin_error (_("no closing `%c' in %s"), delim, string);
+ return -1;
+ }
+
+ return i;
+}
+
+int
+bind_keyseq_to_unix_command (line)
+ char *line;
+{
+ Keymap kmap;
+ char *kseq, *value;
+ int i, kstart;
+
+ if (cmd_xmap == 0)
+ init_unix_command_map ();
+
+ kmap = rl_get_keymap ();
+
+ /* We duplicate some of the work done by rl_parse_and_bind here, but
+ this code only has to handle `"keyseq": ["]command["]' and can
+ generate an error for anything else. */
+ i = isolate_sequence (line, 0, 1, &kstart);
+ if (i < 0)
+ return -1;
+
+ /* Create the key sequence string to pass to rl_generic_bind */
+ kseq = substring (line, kstart, i);
+
+ for ( ; line[i] && line[i] != ':'; i++)
+ ;
+ if (line[i] != ':')
+ {
+ builtin_error (_("%s: missing colon separator"), line);
+ FREE (kseq);
+ return -1;
+ }
+
+ i = isolate_sequence (line, i + 1, 0, &kstart);
+ if (i < 0)
+ {
+ FREE (kseq);
+ return -1;
+ }
+
+ /* Create the value string containing the command to execute. */
+ value = substring (line, kstart, i);
+
+ /* Save the command to execute and the key sequence in the CMD_XMAP */
+ rl_generic_bind (ISMACR, kseq, value, cmd_xmap);
+
+ /* and bind the key sequence in the current keymap to a function that
+ understands how to execute from CMD_XMAP */
+ rl_bind_keyseq_in_map (kseq, bash_execute_unix_command, kmap);
+
+ free (kseq);
+ return 0;
+}
+
+/* Used by the programmable completion code. Complete TEXT as a filename,
+ but return only directories as matches. Dequotes the filename before
+ attempting to find matches. */
+char **
+bash_directory_completion_matches (text)
+ const char *text;
+{
+ char **m1;
+ char *dfn;
+ int qc;
+
+ qc = rl_dispatching ? rl_completion_quote_character : 0;
+ dfn = bash_dequote_filename ((char *)text, qc);
+ m1 = rl_completion_matches (dfn, rl_filename_completion_function);
+ free (dfn);
+
+ if (m1 == 0 || m1[0] == 0)
+ return m1;
+ /* We don't bother recomputing the lcd of the matches, because it will just
+ get thrown away by the programmable completion code and recomputed
+ later. */
+ (void)bash_ignore_filenames (m1);
+ return m1;
+}
+
+char *
+bash_dequote_text (text)
+ const char *text;
+{
+ char *dtxt;
+ int qc;
+
+ qc = (text[0] == '"' || text[0] == '\'') ? text[0] : 0;
+ dtxt = bash_dequote_filename ((char *)text, qc);
+ return (dtxt);
+}
+
+/* This event hook is designed to be called after readline receives a signal
+ that interrupts read(2). It gives reasonable responsiveness to interrupts
+ and fatal signals without executing too much code in a signal handler
+ context. */
+static int
+bash_event_hook ()
+{
+ /* If we're going to longjmp to top_level, make sure we clean up readline */
+ if (interrupt_state && signal_is_trapped (SIGINT) == 0)
+ rl_cleanup_after_signal ();
+
+ bashline_reset_event_hook ();
+ check_signals_and_traps (); /* XXX */
+}
+
+#endif /* READLINE */
from the table of active jobs.
If
.I jobspec
-is not present, and neither \fB\-a\fP nor \fB\-r\fP is supplied,
-the shell's notion of the \fIcurrent job\fP is used.
+is not present, and neither the \fB\-a\fP nor the \fB\-r\fP option
+is supplied, the \fIcurrent job\fP is used.
If the \fB\-h\fP option is given, each
.I jobspec
is not removed from the table, but is marked so that
.BR SIGHUP .
If no
.I jobspec
-is present, and neither the
-.B \-a
-nor the
-.B \-r
-option is supplied, the \fIcurrent job\fP is used.
-If no
-.I jobspec
is supplied, the
.B \-a
option means to remove or mark all jobs; the
\entry{caller}{48}{\code {caller}}
\entry{command}{49}{\code {command}}
\entry{declare}{49}{\code {declare}}
-\entry{echo}{50}{\code {echo}}
+\entry{echo}{51}{\code {echo}}
\entry{enable}{51}{\code {enable}}
\entry{help}{52}{\code {help}}
\entry{let}{52}{\code {let}}
\entry{shopt}{61}{\code {shopt}}
\entry{dirs}{90}{\code {dirs}}
\entry{popd}{90}{\code {popd}}
-\entry{pushd}{90}{\code {pushd}}
+\entry{pushd}{91}{\code {pushd}}
\entry{bg}{98}{\code {bg}}
\entry{fg}{98}{\code {fg}}
\entry{jobs}{98}{\code {jobs}}
\entry {\code {dirs}}{90}
\entry {\code {disown}}{99}
\initial {E}
-\entry {\code {echo}}{50}
+\entry {\code {echo}}{51}
\entry {\code {enable}}{51}
\entry {\code {eval}}{41}
\entry {\code {exec}}{41}
\initial {P}
\entry {\code {popd}}{90}
\entry {\code {printf}}{53}
-\entry {\code {pushd}}{90}
+\entry {\code {pushd}}{91}
\entry {\code {pwd}}{43}
\initial {R}
\entry {\code {read}}{54}
-This is TeX, Version 3.1415926 (TeX Live 2011/Fink) (format=tex 2012.4.18) 8 MAR 2013 15:57
+This is TeX, Version 3.1415926 (TeX Live 2011/Fink) (format=tex 2012.4.18) 19 AUG 2013 15:43
**/usr/homes/chet/src/bash/src/doc/bashref.texi
(/usr/homes/chet/src/bash/src/doc/bashref.texi (./texinfo.tex
Loading texinfo [version 2009-01-18.17]:
[16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30]
[31] [32] [33] [34] [35] [36] [37] [38] Chapter 4 [39] [40] [41] [42] [43]
[44] [45] [46]
-Underfull \hbox (badness 5231) in paragraph at lines 3760--3773
+Underfull \hbox (badness 5231) in paragraph at lines 3762--3775
@texttt emacs-meta[]@textrm , @texttt emacs-ctlx[]@textrm , @texttt vi[]@textr
m , @texttt vi-move[]@textrm , @texttt vi-command[]@textrm , and
.etc.
[47] [48] [49] [50] [51] [52] [53] [54] [55] [56] [57] [58] [59] [60] [61]
-[62] [63] [64]
-Underfull \hbox (badness 5460) in paragraph at lines 5047--5053
- []@textrm If set, range ex-pres-sions used in pat-tern match-ing (see
-
-@hbox(8.2125+2.73749)x433.62, glue set 3.79674
-.@glue(@leftskip) 115.63242
-.@hbox(0.0+0.0)x0.0
-.@textrm I
-.@textrm f
-.@glue 3.65 plus 1.825 minus 1.21666
-.etc.
-
-[65] [66] Chapter 5 [67] [68] [69] [70] [71] [72] [73] [74] [75] [76] [77]
-Chapter 6 [78]
-Overfull \hbox (51.96864pt too wide) in paragraph at lines 5972--5972
+[62] [63] [64] [65] [66] Chapter 5 [67] [68] [69] [70] [71] [72] [73] [74]
+[75] [76] [77] Chapter 6 [78]
+Overfull \hbox (51.96864pt too wide) in paragraph at lines 5979--5979
[]@texttt bash [long-opt] [-ir] [-abefhkmnptuvxdBCDHP] [-o @textttsl op-tion@t
exttt ] [-O @textttsl shopt_option@texttt ] [@textttsl ar-
.etc.
-Overfull \hbox (76.23077pt too wide) in paragraph at lines 5973--5973
+Overfull \hbox (76.23077pt too wide) in paragraph at lines 5980--5980
[]@texttt bash [long-opt] [-abefhkmnptuvxdBCDHP] [-o @textttsl op-tion@texttt
] [-O @textttsl shopt_option@texttt ] -c @textttsl string @texttt [@textttsl ar
-
.etc.
-Overfull \hbox (34.72258pt too wide) in paragraph at lines 5974--5974
+Overfull \hbox (34.72258pt too wide) in paragraph at lines 5981--5981
[]@texttt bash [long-opt] -s [-abefhkmnptuvxdBCDHP] [-o @textttsl op-tion@text
tt ] [-O @textttsl shopt_option@texttt ] [@textttsl ar-
.etc.
[79] [80]
-Underfull \hbox (badness 2245) in paragraph at lines 6146--6148
+Underfull \hbox (badness 2245) in paragraph at lines 6153--6155
[]@textrm When a lo-gin shell ex-its, Bash reads and ex-e-cutes com-mands from
the file
.@textrm n
.etc.
-[81] [82] [83] [84] [85] [86] [87] [88] [89] [90] [91] [92] [93] [94]
-Underfull \hbox (badness 2521) in paragraph at lines 7358--7361
+[81] [82] [83] [84] [85] [86] [87] [88] [89] [90] [91] [92] [93] [94] [95]
+Underfull \hbox (badness 2521) in paragraph at lines 7371--7374
@textrm `@texttt --enable-strict-posix-default[]@textrm '[] to @texttt configur
e[] @textrm when build-ing (see Sec-tion 10.8
.@texttt n
.etc.
-Chapter 7 [95] [96] [97] [98] [99]
+Chapter 7 [96] [97] [98] [99]
(/usr/homes/chet/src/bash/src/lib/readline/doc/rluser.texi Chapter 8 [100]
[101] [102] [103] [104] [105] [106]
Underfull \hbox (badness 5231) in paragraph at lines 565--581
[131]) (/usr/homes/chet/src/bash/src/lib/readline/doc/hsuser.texi Chapter 9
[132] [133] [134] [135] [136]) Chapter 10 [137] [138] [139] [140]
-Underfull \hbox (badness 2772) in paragraph at lines 7966--7970
+Underfull \hbox (badness 2772) in paragraph at lines 7979--7983
[]@textrm Enable sup-port for large files (@texttt http://www.sas.com/standard
s/large_
Here is how much of TeX's memory you used:
2085 strings out of 497974
28645 string characters out of 3220833
- 66392 words of memory out of 3000000
+ 66401 words of memory out of 3000000
2901 multiletter control sequences out of 15000+200000
32127 words of font info for 112 fonts, out of 3000000 for 9000
51 hyphenation exceptions out of 8191
16i,6n,14p,319b,705s stack positions out of 5000i,500n,10000p,200000b,50000s
-Output written on bashref.dvi (172 pages, 717824 bytes).
+Output written on bashref.dvi (172 pages, 719444 bytes).
If the @option{-h} option is given, the job is not removed from the table,
but is marked so that @code{SIGHUP} is not sent to the job if the shell
receives a @code{SIGHUP}.
-If @var{jobspec} is not present, and neither the @option{-a} nor @option{-r}
-option is supplied, the current job is used.
+If @var{jobspec} is not present, and neither the @option{-a} nor the
+@option{-r} option is supplied, the current job is used.
If no @var{jobspec} is supplied, the @option{-a} option means to remove or
mark all jobs; the @option{-r} option without a @var{jobspec}
argument restricts operation to running jobs.
static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
-static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
+static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t *));
static void
save_tty_chars (tiop)
static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
-static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
+static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t *));
static void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE));
#if defined (FLUSHO)
--- /dev/null
+/* rltty.c -- functions to prepare and restore the terminal for readline's
+ use. */
+
+/* Copyright (C) 1992-2005 Free Software Foundation, Inc.
+
+ This file is part of the GNU Readline Library (Readline), a library
+ for reading lines of text with interactive input and history editing.
+
+ Readline is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Readline is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Readline. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define READLINE_LIBRARY
+
+#if defined (HAVE_CONFIG_H)
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdio.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+
+#include "rldefs.h"
+
+#if defined (GWINSZ_IN_SYS_IOCTL)
+# include <sys/ioctl.h>
+#endif /* GWINSZ_IN_SYS_IOCTL */
+
+#include "rltty.h"
+#include "readline.h"
+#include "rlprivate.h"
+
+#if !defined (errno)
+extern int errno;
+#endif /* !errno */
+
+rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal;
+rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal;
+
+static void set_winsize PARAMS((int));
+
+/* **************************************************************** */
+/* */
+/* Saving and Restoring the TTY */
+/* */
+/* **************************************************************** */
+
+/* Non-zero means that the terminal is in a prepped state. */
+static int terminal_prepped;
+
+static _RL_TTY_CHARS _rl_tty_chars, _rl_last_tty_chars;
+
+/* If non-zero, means that this process has called tcflow(fd, TCOOFF)
+ and output is suspended. */
+#if defined (__ksr1__)
+static int ksrflow;
+#endif
+
+/* Dummy call to force a backgrounded readline to stop before it tries
+ to get the tty settings. */
+static void
+set_winsize (tty)
+ int tty;
+{
+#if defined (TIOCGWINSZ)
+ struct winsize w;
+
+ if (ioctl (tty, TIOCGWINSZ, &w) == 0)
+ (void) ioctl (tty, TIOCSWINSZ, &w);
+#endif /* TIOCGWINSZ */
+}
+
+#if defined (NO_TTY_DRIVER)
+/* Nothing */
+#elif defined (NEW_TTY_DRIVER)
+
+/* Values for the `flags' field of a struct bsdtty. This tells which
+ elements of the struct bsdtty have been fetched from the system and
+ are valid. */
+#define SGTTY_SET 0x01
+#define LFLAG_SET 0x02
+#define TCHARS_SET 0x04
+#define LTCHARS_SET 0x08
+
+struct bsdtty {
+ struct sgttyb sgttyb; /* Basic BSD tty driver information. */
+ int lflag; /* Local mode flags, like LPASS8. */
+#if defined (TIOCGETC)
+ struct tchars tchars; /* Terminal special characters, including ^S and ^Q. */
+#endif
+#if defined (TIOCGLTC)
+ struct ltchars ltchars; /* 4.2 BSD editing characters */
+#endif
+ int flags; /* Bitmap saying which parts of the struct are valid. */
+};
+
+#define TIOTYPE struct bsdtty
+
+static TIOTYPE otio;
+
+static void save_tty_chars PARAMS((TIOTYPE *));
+static int _get_tty_settings PARAMS((int, TIOTYPE *));
+static int get_tty_settings PARAMS((int, TIOTYPE *));
+static int _set_tty_settings PARAMS((int, TIOTYPE *));
+static int set_tty_settings PARAMS((int, TIOTYPE *));
+
+static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
+
+static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
+
+static void
+save_tty_chars (tiop)
+ TIOTYPE *tiop;
+{
+ _rl_last_tty_chars = _rl_tty_chars;
+
+ if (tiop->flags & SGTTY_SET)
+ {
+ _rl_tty_chars.t_erase = tiop->sgttyb.sg_erase;
+ _rl_tty_chars.t_kill = tiop->sgttyb.sg_kill;
+ }
+
+ if (tiop->flags & TCHARS_SET)
+ {
+ _rl_intr_char = _rl_tty_chars.t_intr = tiop->tchars.t_intrc;
+ _rl_quit_char = _rl_tty_chars.t_quit = tiop->tchars.t_quitc;
+
+ _rl_tty_chars.t_start = tiop->tchars.t_startc;
+ _rl_tty_chars.t_stop = tiop->tchars.t_stopc;
+ _rl_tty_chars.t_eof = tiop->tchars.t_eofc;
+ _rl_tty_chars.t_eol = '\n';
+ _rl_tty_chars.t_eol2 = tiop->tchars.t_brkc;
+ }
+
+ if (tiop->flags & LTCHARS_SET)
+ {
+ _rl_susp_char = _rl_tty_chars.t_susp = tiop->ltchars.t_suspc;
+
+ _rl_tty_chars.t_dsusp = tiop->ltchars.t_dsuspc;
+ _rl_tty_chars.t_reprint = tiop->ltchars.t_rprntc;
+ _rl_tty_chars.t_flush = tiop->ltchars.t_flushc;
+ _rl_tty_chars.t_werase = tiop->ltchars.t_werasc;
+ _rl_tty_chars.t_lnext = tiop->ltchars.t_lnextc;
+ }
+
+ _rl_tty_chars.t_status = -1;
+}
+
+static int
+get_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ set_winsize (tty);
+
+ tiop->flags = tiop->lflag = 0;
+
+ errno = 0;
+ if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0)
+ return -1;
+ tiop->flags |= SGTTY_SET;
+
+#if defined (TIOCLGET)
+ if (ioctl (tty, TIOCLGET, &(tiop->lflag)) == 0)
+ tiop->flags |= LFLAG_SET;
+#endif
+
+#if defined (TIOCGETC)
+ if (ioctl (tty, TIOCGETC, &(tiop->tchars)) == 0)
+ tiop->flags |= TCHARS_SET;
+#endif
+
+#if defined (TIOCGLTC)
+ if (ioctl (tty, TIOCGLTC, &(tiop->ltchars)) == 0)
+ tiop->flags |= LTCHARS_SET;
+#endif
+
+ return 0;
+}
+
+static int
+set_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ if (tiop->flags & SGTTY_SET)
+ {
+ ioctl (tty, TIOCSETN, &(tiop->sgttyb));
+ tiop->flags &= ~SGTTY_SET;
+ }
+ _rl_echoing_p = 1;
+
+#if defined (TIOCLSET)
+ if (tiop->flags & LFLAG_SET)
+ {
+ ioctl (tty, TIOCLSET, &(tiop->lflag));
+ tiop->flags &= ~LFLAG_SET;
+ }
+#endif
+
+#if defined (TIOCSETC)
+ if (tiop->flags & TCHARS_SET)
+ {
+ ioctl (tty, TIOCSETC, &(tiop->tchars));
+ tiop->flags &= ~TCHARS_SET;
+ }
+#endif
+
+#if defined (TIOCSLTC)
+ if (tiop->flags & LTCHARS_SET)
+ {
+ ioctl (tty, TIOCSLTC, &(tiop->ltchars));
+ tiop->flags &= ~LTCHARS_SET;
+ }
+#endif
+
+ return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, oldtio, tiop)
+ int meta_flag;
+ TIOTYPE oldtio, *tiop;
+{
+ _rl_echoing_p = (oldtio.sgttyb.sg_flags & ECHO);
+ _rl_echoctl = (oldtio.sgttyb.sg_flags & ECHOCTL);
+
+ /* Copy the original settings to the structure we're going to use for
+ our settings. */
+ tiop->sgttyb = oldtio.sgttyb;
+ tiop->lflag = oldtio.lflag;
+#if defined (TIOCGETC)
+ tiop->tchars = oldtio.tchars;
+#endif
+#if defined (TIOCGLTC)
+ tiop->ltchars = oldtio.ltchars;
+#endif
+ tiop->flags = oldtio.flags;
+
+ /* First, the basic settings to put us into character-at-a-time, no-echo
+ input mode. */
+ tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
+ tiop->sgttyb.sg_flags |= CBREAK;
+
+ /* If this terminal doesn't care how the 8th bit is used, then we can
+ use it for the meta-key. If only one of even or odd parity is
+ specified, then the terminal is using parity, and we cannot. */
+#if !defined (ANYP)
+# define ANYP (EVENP | ODDP)
+#endif
+ if (((oldtio.sgttyb.sg_flags & ANYP) == ANYP) ||
+ ((oldtio.sgttyb.sg_flags & ANYP) == 0))
+ {
+ tiop->sgttyb.sg_flags |= ANYP;
+
+ /* Hack on local mode flags if we can. */
+#if defined (TIOCLGET)
+# if defined (LPASS8)
+ tiop->lflag |= LPASS8;
+# endif /* LPASS8 */
+#endif /* TIOCLGET */
+ }
+
+#if defined (TIOCGETC)
+# if defined (USE_XON_XOFF)
+ /* Get rid of terminal output start and stop characters. */
+ tiop->tchars.t_stopc = -1; /* C-s */
+ tiop->tchars.t_startc = -1; /* C-q */
+
+ /* If there is an XON character, bind it to restart the output. */
+ if (oldtio.tchars.t_startc != -1)
+ rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
+# endif /* USE_XON_XOFF */
+
+ /* If there is an EOF char, bind _rl_eof_char to it. */
+ if (oldtio.tchars.t_eofc != -1)
+ _rl_eof_char = oldtio.tchars.t_eofc;
+
+# if defined (NO_KILL_INTR)
+ /* Get rid of terminal-generated SIGQUIT and SIGINT. */
+ tiop->tchars.t_quitc = -1; /* C-\ */
+ tiop->tchars.t_intrc = -1; /* C-c */
+# endif /* NO_KILL_INTR */
+#endif /* TIOCGETC */
+
+#if defined (TIOCGLTC)
+ /* Make the interrupt keys go away. Just enough to make people happy. */
+ tiop->ltchars.t_dsuspc = -1; /* C-y */
+ tiop->ltchars.t_lnextc = -1; /* C-v */
+#endif /* TIOCGLTC */
+}
+
+#else /* !defined (NEW_TTY_DRIVER) */
+
+#if !defined (VMIN)
+# define VMIN VEOF
+#endif
+
+#if !defined (VTIME)
+# define VTIME VEOL
+#endif
+
+#if defined (TERMIOS_TTY_DRIVER)
+# define TIOTYPE struct termios
+# define DRAIN_OUTPUT(fd) tcdrain (fd)
+# define GETATTR(tty, tiop) (tcgetattr (tty, tiop))
+# ifdef M_UNIX
+# define SETATTR(tty, tiop) (tcsetattr (tty, TCSANOW, tiop))
+# else
+# define SETATTR(tty, tiop) (tcsetattr (tty, TCSADRAIN, tiop))
+# endif /* !M_UNIX */
+#else
+# define TIOTYPE struct termio
+# define DRAIN_OUTPUT(fd)
+# define GETATTR(tty, tiop) (ioctl (tty, TCGETA, tiop))
+# define SETATTR(tty, tiop) (ioctl (tty, TCSETAW, tiop))
+#endif /* !TERMIOS_TTY_DRIVER */
+
+static TIOTYPE otio;
+
+static void save_tty_chars PARAMS((TIOTYPE *));
+static int _get_tty_settings PARAMS((int, TIOTYPE *));
+static int get_tty_settings PARAMS((int, TIOTYPE *));
+static int _set_tty_settings PARAMS((int, TIOTYPE *));
+static int set_tty_settings PARAMS((int, TIOTYPE *));
+
+static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
+
+static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
+static void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE));
+
+#if defined (FLUSHO)
+# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO)
+#else
+# define OUTPUT_BEING_FLUSHED(tp) 0
+#endif
+
+static void
+save_tty_chars (tiop)
+ TIOTYPE *tiop;
+{
+ _rl_last_tty_chars = _rl_tty_chars;
+
+ _rl_tty_chars.t_eof = tiop->c_cc[VEOF];
+ _rl_tty_chars.t_eol = tiop->c_cc[VEOL];
+#ifdef VEOL2
+ _rl_tty_chars.t_eol2 = tiop->c_cc[VEOL2];
+#endif
+ _rl_tty_chars.t_erase = tiop->c_cc[VERASE];
+#ifdef VWERASE
+ _rl_tty_chars.t_werase = tiop->c_cc[VWERASE];
+#endif
+ _rl_tty_chars.t_kill = tiop->c_cc[VKILL];
+#ifdef VREPRINT
+ _rl_tty_chars.t_reprint = tiop->c_cc[VREPRINT];
+#endif
+ _rl_intr_char = _rl_tty_chars.t_intr = tiop->c_cc[VINTR];
+ _rl_quit_char = _rl_tty_chars.t_quit = tiop->c_cc[VQUIT];
+#ifdef VSUSP
+ _rl_susp_char = _rl_tty_chars.t_susp = tiop->c_cc[VSUSP];
+#endif
+#ifdef VDSUSP
+ _rl_tty_chars.t_dsusp = tiop->c_cc[VDSUSP];
+#endif
+#ifdef VSTART
+ _rl_tty_chars.t_start = tiop->c_cc[VSTART];
+#endif
+#ifdef VSTOP
+ _rl_tty_chars.t_stop = tiop->c_cc[VSTOP];
+#endif
+#ifdef VLNEXT
+ _rl_tty_chars.t_lnext = tiop->c_cc[VLNEXT];
+#endif
+#ifdef VDISCARD
+ _rl_tty_chars.t_flush = tiop->c_cc[VDISCARD];
+#endif
+#ifdef VSTATUS
+ _rl_tty_chars.t_status = tiop->c_cc[VSTATUS];
+#endif
+}
+
+#if defined (_AIX) || defined (_AIX41)
+/* Currently this is only used on AIX */
+static void
+rltty_warning (msg)
+ char *msg;
+{
+ _rl_errmsg ("warning: %s", msg);
+}
+#endif
+
+#if defined (_AIX)
+void
+setopost(tp)
+TIOTYPE *tp;
+{
+ if ((tp->c_oflag & OPOST) == 0)
+ {
+ _rl_errmsg ("warning: turning on OPOST for terminal\r");
+ tp->c_oflag |= OPOST|ONLCR;
+ }
+}
+#endif
+
+static int
+_get_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ int ioctl_ret;
+
+ while (1)
+ {
+ ioctl_ret = GETATTR (tty, tiop);
+ if (ioctl_ret < 0)
+ {
+ if (errno != EINTR)
+ return -1;
+ else
+ continue;
+ }
+ if (OUTPUT_BEING_FLUSHED (tiop))
+ {
+#if defined (FLUSHO)
+ _rl_errmsg ("warning: turning off output flushing");
+ tiop->c_lflag &= ~FLUSHO;
+ break;
+#else
+ continue;
+#endif
+ }
+ break;
+ }
+
+ return 0;
+}
+
+static int
+get_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ set_winsize (tty);
+
+ errno = 0;
+ if (_get_tty_settings (tty, tiop) < 0)
+ return -1;
+
+#if defined (_AIX)
+ setopost(tiop);
+#endif
+
+ return 0;
+}
+
+static int
+_set_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ while (SETATTR (tty, tiop) < 0)
+ {
+ if (errno != EINTR)
+ return -1;
+ errno = 0;
+ }
+ return 0;
+}
+
+static int
+set_tty_settings (tty, tiop)
+ int tty;
+ TIOTYPE *tiop;
+{
+ if (_set_tty_settings (tty, tiop) < 0)
+ return -1;
+
+#if 0
+
+#if defined (TERMIOS_TTY_DRIVER)
+# if defined (__ksr1__)
+ if (ksrflow)
+ {
+ ksrflow = 0;
+ tcflow (tty, TCOON);
+ }
+# else /* !ksr1 */
+ tcflow (tty, TCOON); /* Simulate a ^Q. */
+# endif /* !ksr1 */
+#else
+ ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */
+#endif /* !TERMIOS_TTY_DRIVER */
+
+#endif /* 0 */
+
+ return 0;
+}
+
+static void
+prepare_terminal_settings (meta_flag, oldtio, tiop)
+ int meta_flag;
+ TIOTYPE oldtio, *tiop;
+{
+ _rl_echoing_p = (oldtio.c_lflag & ECHO);
+#if defined (ECHOCTL)
+ _rl_echoctl = (oldtio.c_lflag & ECHOCTL);
+#endif
+
+ tiop->c_lflag &= ~(ICANON | ECHO);
+
+ if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
+ _rl_eof_char = oldtio.c_cc[VEOF];
+
+#if defined (USE_XON_XOFF)
+#if defined (IXANY)
+ tiop->c_iflag &= ~(IXON | IXANY);
+#else
+ /* `strict' Posix systems do not define IXANY. */
+ tiop->c_iflag &= ~IXON;
+#endif /* IXANY */
+#endif /* USE_XON_XOFF */
+
+ /* Only turn this off if we are using all 8 bits. */
+ if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
+ tiop->c_iflag &= ~(ISTRIP | INPCK);
+
+ /* Make sure we differentiate between CR and NL on input. */
+ tiop->c_iflag &= ~(ICRNL | INLCR);
+
+#if !defined (HANDLE_SIGNALS)
+ tiop->c_lflag &= ~ISIG;
+#else
+ tiop->c_lflag |= ISIG;
+#endif
+
+ tiop->c_cc[VMIN] = 1;
+ tiop->c_cc[VTIME] = 0;
+
+#if defined (FLUSHO)
+ if (OUTPUT_BEING_FLUSHED (tiop))
+ {
+ tiop->c_lflag &= ~FLUSHO;
+ oldtio.c_lflag &= ~FLUSHO;
+ }
+#endif
+
+ /* Turn off characters that we need on Posix systems with job control,
+ just to be sure. This includes ^Y and ^V. This should not really
+ be necessary. */
+#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
+
+#if defined (VLNEXT)
+ tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
+#endif
+
+#if defined (VDSUSP)
+ tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif
+
+#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
+}
+#endif /* !NEW_TTY_DRIVER */
+
+/* Put the terminal in CBREAK mode so that we can detect key presses. */
+#if defined (NO_TTY_DRIVER)
+void
+rl_prep_terminal (meta_flag)
+ int meta_flag;
+{
+ _rl_echoing_p = 1;
+}
+
+void
+rl_deprep_terminal ()
+{
+}
+
+#else /* ! NO_TTY_DRIVER */
+void
+rl_prep_terminal (meta_flag)
+ int meta_flag;
+{
+ int tty;
+ TIOTYPE tio;
+
+ if (terminal_prepped)
+ return;
+
+ /* Try to keep this function from being INTerrupted. */
+ _rl_block_sigint ();
+
+ tty = rl_instream ? fileno (rl_instream) : fileno (stdin);
+
+ if (get_tty_settings (tty, &tio) < 0)
+ {
+#if defined (ENOTSUP)
+ /* MacOS X and Linux, at least, lie about the value of errno if
+ tcgetattr fails. */
+ if (errno == ENOTTY || errno == EINVAL || errno == ENOTSUP)
+#else
+ if (errno == ENOTTY || errno == EINVAL)
+#endif
+ _rl_echoing_p = 1; /* XXX */
+
+ _rl_release_sigint ();
+ return;
+ }
+
+ otio = tio;
+
+ if (_rl_bind_stty_chars)
+ {
+#if defined (VI_MODE)
+ /* If editing in vi mode, make sure we restore the bindings in the
+ insertion keymap no matter what keymap we ended up in. */
+ if (rl_editing_mode == vi_mode)
+ rl_tty_unset_default_bindings (vi_insertion_keymap);
+ else
+#endif
+ rl_tty_unset_default_bindings (_rl_keymap);
+ }
+ save_tty_chars (&otio);
+ RL_SETSTATE(RL_STATE_TTYCSAVED);
+ if (_rl_bind_stty_chars)
+ {
+#if defined (VI_MODE)
+ /* If editing in vi mode, make sure we set the bindings in the
+ insertion keymap no matter what keymap we ended up in. */
+ if (rl_editing_mode == vi_mode)
+ _rl_bind_tty_special_chars (vi_insertion_keymap, tio);
+ else
+#endif
+ _rl_bind_tty_special_chars (_rl_keymap, tio);
+ }
+
+ prepare_terminal_settings (meta_flag, otio, &tio);
+
+ if (set_tty_settings (tty, &tio) < 0)
+ {
+ _rl_release_sigint ();
+ return;
+ }
+
+ if (_rl_enable_keypad)
+ _rl_control_keypad (1);
+
+ fflush (rl_outstream);
+ terminal_prepped = 1;
+ RL_SETSTATE(RL_STATE_TERMPREPPED);
+
+ _rl_release_sigint ();
+}
+
+/* Restore the terminal's normal settings and modes. */
+void
+rl_deprep_terminal ()
+{
+ int tty;
+
+ if (!terminal_prepped)
+ return;
+
+ /* Try to keep this function from being interrupted. */
+ _rl_block_sigint ();
+
+ tty = rl_instream ? fileno (rl_instream) : fileno (stdin);
+
+ if (_rl_enable_keypad)
+ _rl_control_keypad (0);
+
+ fflush (rl_outstream);
+
+ if (set_tty_settings (tty, &otio) < 0)
+ {
+ _rl_release_sigint ();
+ return;
+ }
+
+ terminal_prepped = 0;
+ RL_UNSETSTATE(RL_STATE_TERMPREPPED);
+
+ _rl_release_sigint ();
+}
+#endif /* !NO_TTY_DRIVER */
+\f
+/* **************************************************************** */
+/* */
+/* Bogus Flow Control */
+/* */
+/* **************************************************************** */
+
+int
+rl_restart_output (count, key)
+ int count, key;
+{
+#if defined (__MINGW32__)
+ return 0;
+#else /* !__MING32__ */
+
+ int fildes = fileno (rl_outstream);
+#if defined (TIOCSTART)
+#if defined (apollo)
+ ioctl (&fildes, TIOCSTART, 0);
+#else
+ ioctl (fildes, TIOCSTART, 0);
+#endif /* apollo */
+
+#else /* !TIOCSTART */
+# if defined (TERMIOS_TTY_DRIVER)
+# if defined (__ksr1__)
+ if (ksrflow)
+ {
+ ksrflow = 0;
+ tcflow (fildes, TCOON);
+ }
+# else /* !ksr1 */
+ tcflow (fildes, TCOON); /* Simulate a ^Q. */
+# endif /* !ksr1 */
+# else /* !TERMIOS_TTY_DRIVER */
+# if defined (TCXONC)
+ ioctl (fildes, TCXONC, TCOON);
+# endif /* TCXONC */
+# endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTART */
+
+ return 0;
+#endif /* !__MINGW32__ */
+}
+
+int
+rl_stop_output (count, key)
+ int count, key;
+{
+#if defined (__MINGW32__)
+ return 0;
+#else
+
+ int fildes = fileno (rl_instream);
+
+#if defined (TIOCSTOP)
+# if defined (apollo)
+ ioctl (&fildes, TIOCSTOP, 0);
+# else
+ ioctl (fildes, TIOCSTOP, 0);
+# endif /* apollo */
+#else /* !TIOCSTOP */
+# if defined (TERMIOS_TTY_DRIVER)
+# if defined (__ksr1__)
+ ksrflow = 1;
+# endif /* ksr1 */
+ tcflow (fildes, TCOOFF);
+# else
+# if defined (TCXONC)
+ ioctl (fildes, TCXONC, TCOON);
+# endif /* TCXONC */
+# endif /* !TERMIOS_TTY_DRIVER */
+#endif /* !TIOCSTOP */
+
+ return 0;
+#endif /* !__MINGW32__ */
+}
+
+/* **************************************************************** */
+/* */
+/* Default Key Bindings */
+/* */
+/* **************************************************************** */
+
+#if !defined (NO_TTY_DRIVER)
+#define SET_SPECIAL(sc, func) set_special_char(kmap, &ttybuff, sc, func)
+#endif
+
+#if defined (NO_TTY_DRIVER)
+
+#define SET_SPECIAL(sc, func)
+#define RESET_SPECIAL(c)
+
+#elif defined (NEW_TTY_DRIVER)
+static void
+set_special_char (kmap, tiop, sc, func)
+ Keymap kmap;
+ TIOTYPE *tiop;
+ int sc;
+ rl_command_func_t *func;
+{
+ if (sc != -1 && kmap[(unsigned char)sc].type == ISFUNC)
+ kmap[(unsigned char)sc].function = func;
+}
+
+#define RESET_SPECIAL(c) \
+ if (c != -1 && kmap[(unsigned char)c].type == ISFUNC) \
+ kmap[(unsigned char)c].function = rl_insert;
+
+static void
+_rl_bind_tty_special_chars (kmap, ttybuff)
+ Keymap kmap;
+ TIOTYPE ttybuff;
+{
+ if (ttybuff.flags & SGTTY_SET)
+ {
+ SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
+ SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
+ }
+
+# if defined (TIOCGLTC)
+ if (ttybuff.flags & LTCHARS_SET)
+ {
+ SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
+ SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
+ }
+# endif /* TIOCGLTC */
+}
+
+#else /* !NEW_TTY_DRIVER */
+static void
+set_special_char (kmap, tiop, sc, func)
+ Keymap kmap;
+ TIOTYPE *tiop;
+ int sc;
+ rl_command_func_t *func;
+{
+ unsigned char uc;
+
+ uc = tiop->c_cc[sc];
+ if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC)
+ kmap[uc].function = func;
+}
+
+/* used later */
+#define RESET_SPECIAL(uc) \
+ if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
+ kmap[uc].function = rl_insert;
+
+static void
+_rl_bind_tty_special_chars (kmap, ttybuff)
+ Keymap kmap;
+ TIOTYPE ttybuff;
+{
+ SET_SPECIAL (VERASE, rl_rubout);
+ SET_SPECIAL (VKILL, rl_unix_line_discard);
+
+# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
+ SET_SPECIAL (VLNEXT, rl_quoted_insert);
+# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
+
+# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
+ SET_SPECIAL (VWERASE, rl_unix_word_rubout);
+# endif /* VWERASE && TERMIOS_TTY_DRIVER */
+}
+
+#endif /* !NEW_TTY_DRIVER */
+
+/* Set the system's default editing characters to their readline equivalents
+ in KMAP. Should be static, now that we have rl_tty_set_default_bindings. */
+void
+rltty_set_default_bindings (kmap)
+ Keymap kmap;
+{
+#if !defined (NO_TTY_DRIVER)
+ TIOTYPE ttybuff;
+ int tty;
+
+ tty = fileno (rl_instream);
+
+ if (get_tty_settings (tty, &ttybuff) == 0)
+ _rl_bind_tty_special_chars (kmap, ttybuff);
+#endif
+}
+
+/* New public way to set the system default editing chars to their readline
+ equivalents. */
+void
+rl_tty_set_default_bindings (kmap)
+ Keymap kmap;
+{
+ rltty_set_default_bindings (kmap);
+}
+
+/* Rebind all of the tty special chars that readline worries about back
+ to self-insert. Call this before saving the current terminal special
+ chars with save_tty_chars(). This only works on POSIX termios or termio
+ systems. */
+void
+rl_tty_unset_default_bindings (kmap)
+ Keymap kmap;
+{
+ /* Don't bother before we've saved the tty special chars at least once. */
+ if (RL_ISSTATE(RL_STATE_TTYCSAVED) == 0)
+ return;
+
+ RESET_SPECIAL (_rl_tty_chars.t_erase);
+ RESET_SPECIAL (_rl_tty_chars.t_kill);
+
+# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
+ RESET_SPECIAL (_rl_tty_chars.t_lnext);
+# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
+
+# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
+ RESET_SPECIAL (_rl_tty_chars.t_werase);
+# endif /* VWERASE && TERMIOS_TTY_DRIVER */
+}
+
+#if defined (HANDLE_SIGNALS)
+
+#if defined (NEW_TTY_DRIVER) || defined (NO_TTY_DRIVER)
+int
+_rl_disable_tty_signals ()
+{
+ return 0;
+}
+
+int
+_rl_restore_tty_signals ()
+{
+ return 0;
+}
+#else
+
+static TIOTYPE sigstty, nosigstty;
+static int tty_sigs_disabled = 0;
+
+int
+_rl_disable_tty_signals ()
+{
+ if (tty_sigs_disabled)
+ return 0;
+
+ if (_get_tty_settings (fileno (rl_instream), &sigstty) < 0)
+ return -1;
+
+ nosigstty = sigstty;
+
+ nosigstty.c_lflag &= ~ISIG;
+ nosigstty.c_iflag &= ~IXON;
+
+ if (_set_tty_settings (fileno (rl_instream), &nosigstty) < 0)
+ return (_set_tty_settings (fileno (rl_instream), &sigstty));
+
+ tty_sigs_disabled = 1;
+ return 0;
+}
+
+int
+_rl_restore_tty_signals ()
+{
+ int r;
+
+ if (tty_sigs_disabled == 0)
+ return 0;
+
+ r = _set_tty_settings (fileno (rl_instream), &sigstty);
+
+ if (r == 0)
+ tty_sigs_disabled = 0;
+
+ return r;
+}
+#endif /* !NEW_TTY_DRIVER */
+
+#endif /* HANDLE_SIGNALS */
(rl_completion_found_quote == 0). */
iscompgen = this_shell_builtin == compgen_builtin;
iscompleting = RL_ISSTATE (RL_STATE_COMPLETING);
- if (iscompgen && iscompleting == 0 && rl_completion_found_quote == 0)
+ if (iscompgen && iscompleting == 0 && rl_completion_found_quote == 0
+ && rl_filename_dequoting_function)
{
/* Use rl_completion_quote_character because any single or
double quotes have been removed by the time TEXT makes it
--- /dev/null
+/* pcomplete.c - functions to generate lists of matches for programmable completion. */
+
+/* Copyright (C) 1999-2012 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bash is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bash. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <config.h>
+
+#if defined (PROGRAMMABLE_COMPLETION)
+
+#include "bashtypes.h"
+#include "posixstat.h"
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#include <signal.h>
+
+#if defined (PREFER_STDARG)
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
+
+#include <sys/time.h>
+
+#include <stdio.h>
+#include "bashansi.h"
+#include "bashintl.h"
+
+#include "shell.h"
+#include "pcomplete.h"
+#include "alias.h"
+#include "bashline.h"
+#include "execute_cmd.h"
+#include "pathexp.h"
+
+#if defined (JOB_CONTROL)
+# include "jobs.h"
+#endif
+
+#if !defined (NSIG)
+# include "trap.h"
+#endif
+
+#include "shmbutil.h"
+
+#include "builtins.h"
+#include "builtins/common.h"
+#include "builtins/builtext.h"
+
+#include <glob/glob.h>
+#include <glob/strmatch.h>
+
+#include <readline/rlconf.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#define PCOMP_RETRYFAIL 256
+
+#ifdef STRDUP
+# undef STRDUP
+#endif
+#define STRDUP(x) ((x) ? savestring (x) : (char *)NULL)
+
+typedef SHELL_VAR **SVFUNC ();
+
+#ifndef HAVE_STRPBRK
+extern char *strpbrk __P((char *, char *));
+#endif
+
+extern int array_needs_making;
+extern STRING_INT_ALIST word_token_alist[];
+extern char *signal_names[];
+extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
+
+#if defined (DEBUG)
+#if defined (PREFER_STDARG)
+static void debug_printf (const char *, ...) __attribute__((__format__ (printf, 1, 2)));
+#endif
+#endif /* DEBUG */
+
+static int it_init_joblist __P((ITEMLIST *, int));
+
+static int it_init_aliases __P((ITEMLIST *));
+static int it_init_arrayvars __P((ITEMLIST *));
+static int it_init_bindings __P((ITEMLIST *));
+static int it_init_builtins __P((ITEMLIST *));
+static int it_init_disabled __P((ITEMLIST *));
+static int it_init_enabled __P((ITEMLIST *));
+static int it_init_exported __P((ITEMLIST *));
+static int it_init_functions __P((ITEMLIST *));
+static int it_init_helptopics __P((ITEMLIST *));
+static int it_init_hostnames __P((ITEMLIST *));
+static int it_init_jobs __P((ITEMLIST *));
+static int it_init_running __P((ITEMLIST *));
+static int it_init_stopped __P((ITEMLIST *));
+static int it_init_keywords __P((ITEMLIST *));
+static int it_init_signals __P((ITEMLIST *));
+static int it_init_variables __P((ITEMLIST *));
+static int it_init_setopts __P((ITEMLIST *));
+static int it_init_shopts __P((ITEMLIST *));
+
+static int shouldexp_filterpat __P((char *));
+static char *preproc_filterpat __P((char *, char *));
+
+static void init_itemlist_from_varlist __P((ITEMLIST *, SVFUNC *));
+
+static STRINGLIST *gen_matches_from_itemlist __P((ITEMLIST *, const char *));
+static STRINGLIST *gen_action_completions __P((COMPSPEC *, const char *));
+static STRINGLIST *gen_globpat_matches __P((COMPSPEC *, const char *));
+static STRINGLIST *gen_wordlist_matches __P((COMPSPEC *, const char *));
+static STRINGLIST *gen_shell_function_matches __P((COMPSPEC *, const char *,
+ const char *,
+ char *, int, WORD_LIST *,
+ int, int, int *));
+static STRINGLIST *gen_command_matches __P((COMPSPEC *, const char *,
+ const char *,
+ char *, int, WORD_LIST *,
+ int, int));
+
+static STRINGLIST *gen_progcomp_completions __P((const char *, const char *,
+ const char *,
+ int, int, int *, int *,
+ COMPSPEC **));
+
+static char *pcomp_filename_completion_function __P((const char *, int));
+
+#if defined (ARRAY_VARS)
+static SHELL_VAR *bind_comp_words __P((WORD_LIST *));
+#endif
+static void bind_compfunc_variables __P((char *, int, WORD_LIST *, int, int));
+static void unbind_compfunc_variables __P((int));
+static WORD_LIST *build_arg_list __P((char *, const char *, const char *, WORD_LIST *, int));
+static WORD_LIST *command_line_to_word_list __P((char *, int, int, int *, int *));
+
+#ifdef DEBUG
+static int progcomp_debug = 0;
+#endif
+
+int prog_completion_enabled = 1;
+
+/* These are used to manage the arrays of strings for possible completions. */
+ITEMLIST it_aliases = { 0, it_init_aliases, (STRINGLIST *)0 };
+ITEMLIST it_arrayvars = { LIST_DYNAMIC, it_init_arrayvars, (STRINGLIST *)0 };
+ITEMLIST it_bindings = { 0, it_init_bindings, (STRINGLIST *)0 };
+ITEMLIST it_builtins = { 0, it_init_builtins, (STRINGLIST *)0 };
+ITEMLIST it_commands = { LIST_DYNAMIC }; /* unused */
+ITEMLIST it_directories = { LIST_DYNAMIC }; /* unused */
+ITEMLIST it_disabled = { 0, it_init_disabled, (STRINGLIST *)0 };
+ITEMLIST it_enabled = { 0, it_init_enabled, (STRINGLIST *)0 };
+ITEMLIST it_exports = { LIST_DYNAMIC, it_init_exported, (STRINGLIST *)0 };
+ITEMLIST it_files = { LIST_DYNAMIC }; /* unused */
+ITEMLIST it_functions = { 0, it_init_functions, (STRINGLIST *)0 };
+ITEMLIST it_helptopics = { 0, it_init_helptopics, (STRINGLIST *)0 };
+ITEMLIST it_hostnames = { LIST_DYNAMIC, it_init_hostnames, (STRINGLIST *)0 };
+ITEMLIST it_groups = { LIST_DYNAMIC }; /* unused */
+ITEMLIST it_jobs = { LIST_DYNAMIC, it_init_jobs, (STRINGLIST *)0 };
+ITEMLIST it_keywords = { 0, it_init_keywords, (STRINGLIST *)0 };
+ITEMLIST it_running = { LIST_DYNAMIC, it_init_running, (STRINGLIST *)0 };
+ITEMLIST it_services = { LIST_DYNAMIC }; /* unused */
+ITEMLIST it_setopts = { 0, it_init_setopts, (STRINGLIST *)0 };
+ITEMLIST it_shopts = { 0, it_init_shopts, (STRINGLIST *)0 };
+ITEMLIST it_signals = { 0, it_init_signals, (STRINGLIST *)0 };
+ITEMLIST it_stopped = { LIST_DYNAMIC, it_init_stopped, (STRINGLIST *)0 };
+ITEMLIST it_users = { LIST_DYNAMIC }; /* unused */
+ITEMLIST it_variables = { LIST_DYNAMIC, it_init_variables, (STRINGLIST *)0 };
+
+COMPSPEC *pcomp_curcs;
+const char *pcomp_curcmd;
+
+#ifdef DEBUG
+/* Debugging code */
+static void
+#if defined (PREFER_STDARG)
+debug_printf (const char *format, ...)
+#else
+debug_printf (format, va_alist)
+ const char *format;
+ va_dcl
+#endif
+{
+ va_list args;
+
+ if (progcomp_debug == 0)
+ return;
+
+ SH_VA_START (args, format);
+
+ fprintf (stdout, "DEBUG: ");
+ vfprintf (stdout, format, args);
+ fprintf (stdout, "\n");
+
+ rl_on_new_line ();
+
+ va_end (args);
+}
+#endif
+
+/* Functions to manage the item lists */
+
+void
+set_itemlist_dirty (it)
+ ITEMLIST *it;
+{
+ it->flags |= LIST_DIRTY;
+}
+
+void
+initialize_itemlist (itp)
+ ITEMLIST *itp;
+{
+ (*itp->list_getter) (itp);
+ itp->flags |= LIST_INITIALIZED;
+ itp->flags &= ~LIST_DIRTY;
+}
+
+void
+clean_itemlist (itp)
+ ITEMLIST *itp;
+{
+ STRINGLIST *sl;
+
+ sl = itp->slist;
+ if (sl)
+ {
+ if ((itp->flags & (LIST_DONTFREEMEMBERS|LIST_DONTFREE)) == 0)
+ strvec_flush (sl->list);
+ if ((itp->flags & LIST_DONTFREE) == 0)
+ free (sl->list);
+ free (sl);
+ }
+ itp->slist = (STRINGLIST *)NULL;
+ itp->flags &= ~(LIST_DONTFREE|LIST_DONTFREEMEMBERS|LIST_INITIALIZED|LIST_DIRTY);
+}
+
+
+static int
+shouldexp_filterpat (s)
+ char *s;
+{
+ register char *p;
+
+ for (p = s; p && *p; p++)
+ {
+ if (*p == '\\')
+ p++;
+ else if (*p == '&')
+ return 1;
+ }
+ return 0;
+}
+
+/* Replace any instance of `&' in PAT with TEXT. Backslash may be used to
+ quote a `&' and inhibit substitution. Returns a new string. This just
+ calls stringlib.c:strcreplace(). */
+static char *
+preproc_filterpat (pat, text)
+ char *pat;
+ char *text;
+{
+ char *ret;
+
+ ret = strcreplace (pat, '&', text, 1);
+ return ret;
+}
+
+/* Remove any match of FILTERPAT from SL. A `&' in FILTERPAT is replaced by
+ TEXT. A leading `!' in FILTERPAT negates the pattern; in this case
+ any member of SL->list that does *not* match will be removed. This returns
+ a new STRINGLIST with the matching members of SL *copied*. Any
+ non-matching members of SL->list are *freed*. */
+STRINGLIST *
+filter_stringlist (sl, filterpat, text)
+ STRINGLIST *sl;
+ char *filterpat, *text;
+{
+ int i, m, not;
+ STRINGLIST *ret;
+ char *npat, *t;
+
+ if (sl == 0 || sl->list == 0 || sl->list_len == 0)
+ return sl;
+
+ npat = shouldexp_filterpat (filterpat) ? preproc_filterpat (filterpat, text) : filterpat;
+
+ not = (npat[0] == '!');
+ t = not ? npat + 1 : npat;
+
+ ret = strlist_create (sl->list_size);
+ for (i = 0; i < sl->list_len; i++)
+ {
+ m = strmatch (t, sl->list[i], FNMATCH_EXTFLAG);
+ if ((not && m == FNM_NOMATCH) || (not == 0 && m != FNM_NOMATCH))
+ free (sl->list[i]);
+ else
+ ret->list[ret->list_len++] = sl->list[i];
+ }
+
+ ret->list[ret->list_len] = (char *)NULL;
+ if (npat != filterpat)
+ free (npat);
+
+ return ret;
+}
+
+/* Turn an array of strings returned by rl_completion_matches into a STRINGLIST.
+ This understands how rl_completion_matches sets matches[0] (the lcd of the
+ strings in the list, unless it's the only match). */
+STRINGLIST *
+completions_to_stringlist (matches)
+ char **matches;
+{
+ STRINGLIST *sl;
+ int mlen, i, n;
+
+ mlen = (matches == 0) ? 0 : strvec_len (matches);
+ sl = strlist_create (mlen + 1);
+
+ if (matches == 0 || matches[0] == 0)
+ return sl;
+
+ if (matches[1] == 0)
+ {
+ sl->list[0] = STRDUP (matches[0]);
+ sl->list[sl->list_len = 1] = (char *)NULL;
+ return sl;
+ }
+
+ for (i = 1, n = 0; i < mlen; i++, n++)
+ sl->list[n] = STRDUP (matches[i]);
+ sl->list_len = n;
+ sl->list[n] = (char *)NULL;
+
+ return sl;
+}
+
+/* Functions to manage the various ITEMLISTs that we populate internally.
+ The caller is responsible for setting ITP->flags correctly. */
+
+static int
+it_init_aliases (itp)
+ ITEMLIST *itp;
+{
+#ifdef ALIAS
+ alias_t **alias_list;
+ register int i, n;
+ STRINGLIST *sl;
+
+ alias_list = all_aliases ();
+ if (alias_list == 0)
+ {
+ itp->slist = (STRINGLIST *)NULL;
+ return 0;
+ }
+ for (n = 0; alias_list[n]; n++)
+ ;
+ sl = strlist_create (n+1);
+ for (i = 0; i < n; i++)
+ sl->list[i] = STRDUP (alias_list[i]->name);
+ sl->list[n] = (char *)NULL;
+ sl->list_size = sl->list_len = n;
+ itp->slist = sl;
+#else
+ itp->slist = (STRINGLIST *)NULL;
+#endif
+ free (alias_list);
+ return 1;
+}
+
+static void
+init_itemlist_from_varlist (itp, svfunc)
+ ITEMLIST *itp;
+ SVFUNC *svfunc;
+{
+ SHELL_VAR **vlist;
+ STRINGLIST *sl;
+ register int i, n;
+
+ vlist = (*svfunc) ();
+ if (vlist == 0)
+ {
+ itp->slist = (STRINGLIST *)NULL;
+ return;
+ }
+ for (n = 0; vlist[n]; n++)
+ ;
+ sl = strlist_create (n+1);
+ for (i = 0; i < n; i++)
+ sl->list[i] = savestring (vlist[i]->name);
+ sl->list[sl->list_len = n] = (char *)NULL;
+ itp->slist = sl;
+}
+
+static int
+it_init_arrayvars (itp)
+ ITEMLIST *itp;
+{
+#if defined (ARRAY_VARS)
+ init_itemlist_from_varlist (itp, all_array_variables);
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+static int
+it_init_bindings (itp)
+ ITEMLIST *itp;
+{
+ char **blist;
+ STRINGLIST *sl;
+
+ /* rl_funmap_names allocates blist, but not its members */
+ blist = (char **)rl_funmap_names (); /* XXX fix const later */
+ sl = strlist_create (0);
+ sl->list = blist;
+ sl->list_size = 0;
+ sl->list_len = strvec_len (sl->list);
+ itp->flags |= LIST_DONTFREEMEMBERS;
+ itp->slist = sl;
+
+ return 0;
+}
+
+static int
+it_init_builtins (itp)
+ ITEMLIST *itp;
+{
+ STRINGLIST *sl;
+ register int i, n;
+
+ sl = strlist_create (num_shell_builtins);
+ for (i = n = 0; i < num_shell_builtins; i++)
+ if (shell_builtins[i].function)
+ sl->list[n++] = shell_builtins[i].name;
+ sl->list[sl->list_len = n] = (char *)NULL;
+ itp->flags |= LIST_DONTFREEMEMBERS;
+ itp->slist = sl;
+ return 0;
+}
+
+static int
+it_init_enabled (itp)
+ ITEMLIST *itp;
+{
+ STRINGLIST *sl;
+ register int i, n;
+
+ sl = strlist_create (num_shell_builtins);
+ for (i = n = 0; i < num_shell_builtins; i++)
+ {
+ if (shell_builtins[i].function && (shell_builtins[i].flags & BUILTIN_ENABLED))
+ sl->list[n++] = shell_builtins[i].name;
+ }
+ sl->list[sl->list_len = n] = (char *)NULL;
+ itp->flags |= LIST_DONTFREEMEMBERS;
+ itp->slist = sl;
+ return 0;
+}
+
+static int
+it_init_disabled (itp)
+ ITEMLIST *itp;
+{
+ STRINGLIST *sl;
+ register int i, n;
+
+ sl = strlist_create (num_shell_builtins);
+ for (i = n = 0; i < num_shell_builtins; i++)
+ {
+ if (shell_builtins[i].function && ((shell_builtins[i].flags & BUILTIN_ENABLED) == 0))
+ sl->list[n++] = shell_builtins[i].name;
+ }
+ sl->list[sl->list_len = n] = (char *)NULL;
+ itp->flags |= LIST_DONTFREEMEMBERS;
+ itp->slist = sl;
+ return 0;
+}
+
+static int
+it_init_exported (itp)
+ ITEMLIST *itp;
+{
+ init_itemlist_from_varlist (itp, all_exported_variables);
+ return 0;
+}
+
+static int
+it_init_functions (itp)
+ ITEMLIST *itp;
+{
+ init_itemlist_from_varlist (itp, all_visible_functions);
+ return 0;
+}
+
+/* Like it_init_builtins, but includes everything the help builtin looks at,
+ not just builtins with an active implementing function. */
+static int
+it_init_helptopics (itp)
+ ITEMLIST *itp;
+{
+ STRINGLIST *sl;
+ register int i, n;
+
+ sl = strlist_create (num_shell_builtins);
+ for (i = n = 0; i < num_shell_builtins; i++)
+ sl->list[n++] = shell_builtins[i].name;
+ sl->list[sl->list_len = n] = (char *)NULL;
+ itp->flags |= LIST_DONTFREEMEMBERS;
+ itp->slist = sl;
+ return 0;
+}
+
+static int
+it_init_hostnames (itp)
+ ITEMLIST *itp;
+{
+ STRINGLIST *sl;
+
+ sl = strlist_create (0);
+ sl->list = get_hostname_list ();
+ sl->list_len = sl->list ? strvec_len (sl->list) : 0;
+ sl->list_size = sl->list_len;
+ itp->slist = sl;
+ itp->flags |= LIST_DONTFREEMEMBERS|LIST_DONTFREE;
+ return 0;
+}
+
+static int
+it_init_joblist (itp, jstate)
+ ITEMLIST *itp;
+ int jstate;
+{
+#if defined (JOB_CONTROL)
+ STRINGLIST *sl;
+ register int i;
+ register PROCESS *p;
+ char *s, *t;
+ JOB *j;
+ JOB_STATE ws; /* wanted state */
+
+ ws = JNONE;
+ if (jstate == 0)
+ ws = JRUNNING;
+ else if (jstate == 1)
+ ws = JSTOPPED;
+
+ sl = strlist_create (js.j_jobslots);
+ for (i = js.j_jobslots - 1; i >= 0; i--)
+ {
+ j = get_job_by_jid (i);
+ if (j == 0)
+ continue;
+ p = j->pipe;
+ if (jstate == -1 || JOBSTATE(i) == ws)
+ {
+ s = savestring (p->command);
+ t = strpbrk (s, " \t\n");
+ if (t)
+ *t = '\0';
+ sl->list[sl->list_len++] = s;
+ }
+ }
+ itp->slist = sl;
+#else
+ itp->slist = (STRINGLIST *)NULL;
+#endif
+ return 0;
+}
+
+static int
+it_init_jobs (itp)
+ ITEMLIST *itp;
+{
+ return (it_init_joblist (itp, -1));
+}
+
+static int
+it_init_running (itp)
+ ITEMLIST *itp;
+{
+ return (it_init_joblist (itp, 0));
+}
+
+static int
+it_init_stopped (itp)
+ ITEMLIST *itp;
+{
+ return (it_init_joblist (itp, 1));
+}
+
+static int
+it_init_keywords (itp)
+ ITEMLIST *itp;
+{
+ STRINGLIST *sl;
+ register int i, n;
+
+ for (n = 0; word_token_alist[n].word; n++)
+ ;
+ sl = strlist_create (n);
+ for (i = 0; i < n; i++)
+ sl->list[i] = word_token_alist[i].word;
+ sl->list[sl->list_len = i] = (char *)NULL;
+ itp->flags |= LIST_DONTFREEMEMBERS;
+ itp->slist = sl;
+ return 0;
+}
+
+static int
+it_init_signals (itp)
+ ITEMLIST *itp;
+{
+ STRINGLIST *sl;
+
+ sl = strlist_create (0);
+ sl->list = signal_names;
+ sl->list_len = strvec_len (sl->list);
+ itp->flags |= LIST_DONTFREE;
+ itp->slist = sl;
+ return 0;
+}
+
+static int
+it_init_variables (itp)
+ ITEMLIST *itp;
+{
+ init_itemlist_from_varlist (itp, all_visible_variables);
+ return 0;
+}
+
+static int
+it_init_setopts (itp)
+ ITEMLIST *itp;
+{
+ STRINGLIST *sl;
+
+ sl = strlist_create (0);
+ sl->list = get_minus_o_opts ();
+ sl->list_len = strvec_len (sl->list);
+ itp->slist = sl;
+ itp->flags |= LIST_DONTFREEMEMBERS;
+ return 0;
+}
+
+static int
+it_init_shopts (itp)
+ ITEMLIST *itp;
+{
+ STRINGLIST *sl;
+
+ sl = strlist_create (0);
+ sl->list = get_shopt_options ();
+ sl->list_len = strvec_len (sl->list);
+ itp->slist = sl;
+ itp->flags |= LIST_DONTFREEMEMBERS;
+ return 0;
+}
+
+/* Generate a list of all matches for TEXT using the STRINGLIST in itp->slist
+ as the list of possibilities. If the itemlist has been marked dirty or
+ it should be regenerated every time, destroy the old STRINGLIST and make a
+ new one before trying the match. TEXT is dequoted before attempting a
+ match. */
+static STRINGLIST *
+gen_matches_from_itemlist (itp, text)
+ ITEMLIST *itp;
+ const char *text;
+{
+ STRINGLIST *ret, *sl;
+ int tlen, i, n;
+ char *ntxt;
+
+ if ((itp->flags & (LIST_DIRTY|LIST_DYNAMIC)) ||
+ (itp->flags & LIST_INITIALIZED) == 0)
+ {
+ if (itp->flags & (LIST_DIRTY|LIST_DYNAMIC))
+ clean_itemlist (itp);
+ if ((itp->flags & LIST_INITIALIZED) == 0)
+ initialize_itemlist (itp);
+ }
+ if (itp->slist == 0)
+ return ((STRINGLIST *)NULL);
+ ret = strlist_create (itp->slist->list_len+1);
+ sl = itp->slist;
+
+ ntxt = bash_dequote_text (text);
+ tlen = STRLEN (ntxt);
+
+ for (i = n = 0; i < sl->list_len; i++)
+ {
+ if (tlen == 0 || STREQN (sl->list[i], ntxt, tlen))
+ ret->list[n++] = STRDUP (sl->list[i]);
+ }
+ ret->list[ret->list_len = n] = (char *)NULL;
+
+ FREE (ntxt);
+ return ret;
+}
+
+/* A wrapper for rl_filename_completion_function that dequotes the filename
+ before attempting completions. */
+static char *
+pcomp_filename_completion_function (text, state)
+ const char *text;
+ int state;
+{
+ static char *dfn; /* dequoted filename */
+ int qc;
+ int iscompgen, iscompleting;
+
+ if (state == 0)
+ {
+ FREE (dfn);
+ /* remove backslashes quoting special characters in filenames. */
+ /* There are roughly three paths we can follow to get here:
+ 1. complete -f
+ 2. compgen -f "$word" from a completion function
+ 3. compgen -f "$word" from the command line
+ They all need to be handled.
+
+ In the first two cases, readline will run the filename dequoting
+ function in rl_filename_completion_function if it found a filename
+ quoting character in the word to be completed
+ (rl_completion_found_quote). We run the dequoting function here
+ if we're running compgen, we're not completing, and the
+ rl_filename_completion_function won't dequote the filename
+ (rl_completion_found_quote == 0). */
+ iscompgen = this_shell_builtin == compgen_builtin;
+ iscompleting = RL_ISSTATE (RL_STATE_COMPLETING);
+ if (iscompgen && iscompleting == 0 && rl_completion_found_quote == 0)
+ {
+ /* Use rl_completion_quote_character because any single or
+ double quotes have been removed by the time TEXT makes it
+ here, and we don't want to remove backslashes inside
+ quoted strings. */
+ dfn = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
+ }
+ else
+ dfn = savestring (text);
+ }
+
+ return (rl_filename_completion_function (dfn, state));
+}
+
+#define GEN_COMPS(bmap, flag, it, text, glist, tlist) \
+ do { \
+ if (bmap & flag) \
+ { \
+ tlist = gen_matches_from_itemlist (it, text); \
+ if (tlist) \
+ { \
+ glist = strlist_append (glist, tlist); \
+ strlist_dispose (tlist); \
+ } \
+ } \
+ } while (0)
+
+#define GEN_XCOMPS(bmap, flag, text, func, cmatches, glist, tlist) \
+ do { \
+ if (bmap & flag) \
+ { \
+ cmatches = rl_completion_matches (text, func); \
+ tlist = completions_to_stringlist (cmatches); \
+ glist = strlist_append (glist, tlist); \
+ strvec_dispose (cmatches); \
+ strlist_dispose (tlist); \
+ } \
+ } while (0)
+
+/* Functions to generate lists of matches from the actions member of CS. */
+
+static STRINGLIST *
+gen_action_completions (cs, text)
+ COMPSPEC *cs;
+ const char *text;
+{
+ STRINGLIST *ret, *tmatches;
+ char **cmatches; /* from rl_completion_matches ... */
+ unsigned long flags;
+ int t;
+
+ ret = tmatches = (STRINGLIST *)NULL;
+ flags = cs->actions;
+
+ GEN_COMPS (flags, CA_ALIAS, &it_aliases, text, ret, tmatches);
+ GEN_COMPS (flags, CA_ARRAYVAR, &it_arrayvars, text, ret, tmatches);
+ GEN_COMPS (flags, CA_BINDING, &it_bindings, text, ret, tmatches);
+ GEN_COMPS (flags, CA_BUILTIN, &it_builtins, text, ret, tmatches);
+ GEN_COMPS (flags, CA_DISABLED, &it_disabled, text, ret, tmatches);
+ GEN_COMPS (flags, CA_ENABLED, &it_enabled, text, ret, tmatches);
+ GEN_COMPS (flags, CA_EXPORT, &it_exports, text, ret, tmatches);
+ GEN_COMPS (flags, CA_FUNCTION, &it_functions, text, ret, tmatches);
+ GEN_COMPS (flags, CA_HELPTOPIC, &it_helptopics, text, ret, tmatches);
+ GEN_COMPS (flags, CA_HOSTNAME, &it_hostnames, text, ret, tmatches);
+ GEN_COMPS (flags, CA_JOB, &it_jobs, text, ret, tmatches);
+ GEN_COMPS (flags, CA_KEYWORD, &it_keywords, text, ret, tmatches);
+ GEN_COMPS (flags, CA_RUNNING, &it_running, text, ret, tmatches);
+ GEN_COMPS (flags, CA_SETOPT, &it_setopts, text, ret, tmatches);
+ GEN_COMPS (flags, CA_SHOPT, &it_shopts, text, ret, tmatches);
+ GEN_COMPS (flags, CA_SIGNAL, &it_signals, text, ret, tmatches);
+ GEN_COMPS (flags, CA_STOPPED, &it_stopped, text, ret, tmatches);
+ GEN_COMPS (flags, CA_VARIABLE, &it_variables, text, ret, tmatches);
+
+ GEN_XCOMPS(flags, CA_COMMAND, text, command_word_completion_function, cmatches, ret, tmatches);
+ GEN_XCOMPS(flags, CA_FILE, text, pcomp_filename_completion_function, cmatches, ret, tmatches);
+ GEN_XCOMPS(flags, CA_USER, text, rl_username_completion_function, cmatches, ret, tmatches);
+ GEN_XCOMPS(flags, CA_GROUP, text, bash_groupname_completion_function, cmatches, ret, tmatches);
+ GEN_XCOMPS(flags, CA_SERVICE, text, bash_servicename_completion_function, cmatches, ret, tmatches);
+
+ /* And lastly, the special case for directories */
+ if (flags & CA_DIRECTORY)
+ {
+ t = rl_filename_completion_desired;
+ rl_completion_mark_symlink_dirs = 1; /* override user preference */
+ cmatches = bash_directory_completion_matches (text);
+ /* If we did not want filename completion before this, and there are
+ no matches, turn off rl_filename_completion_desired so whatever
+ matches we get are not treated as filenames (it gets turned on by
+ rl_filename_completion_function unconditionally). */
+ if (t == 0 && cmatches == 0 && rl_filename_completion_desired == 1)
+ rl_filename_completion_desired = 0;
+ tmatches = completions_to_stringlist (cmatches);
+ ret = strlist_append (ret, tmatches);
+ strvec_dispose (cmatches);
+ strlist_dispose (tmatches);
+ }
+
+ return ret;
+}
+
+/* Generate a list of matches for CS->globpat. Unresolved: should this use
+ TEXT as a match prefix, or just go without? Currently, the code does not
+ use TEXT, just globs CS->globpat and returns the results. If we do decide
+ to use TEXT, we should call quote_string_for_globbing before the call to
+ glob_filename. */
+static STRINGLIST *
+gen_globpat_matches (cs, text)
+ COMPSPEC *cs;
+ const char *text;
+{
+ STRINGLIST *sl;
+
+ sl = strlist_create (0);
+ sl->list = glob_filename (cs->globpat, 0);
+ if (GLOB_FAILED (sl->list))
+ sl->list = (char **)NULL;
+ if (sl->list)
+ sl->list_len = sl->list_size = strvec_len (sl->list);
+ return sl;
+}
+
+/* Perform the shell word expansions on CS->words and return the results.
+ Again, this ignores TEXT. */
+static STRINGLIST *
+gen_wordlist_matches (cs, text)
+ COMPSPEC *cs;
+ const char *text;
+{
+ WORD_LIST *l, *l2;
+ STRINGLIST *sl;
+ int nw, tlen;
+ char *ntxt; /* dequoted TEXT to use in comparisons */
+
+ if (cs->words == 0 || cs->words[0] == '\0')
+ return ((STRINGLIST *)NULL);
+
+ /* This used to be a simple expand_string(cs->words, 0), but that won't
+ do -- there's no way to split a simple list into individual words
+ that way, since the shell semantics say that word splitting is done
+ only on the results of expansion. split_at_delims also handles embedded
+ quoted strings and preserves the quotes for the expand_words_shellexp
+ function call that follows. */
+ /* XXX - this is where this function spends most of its time */
+ l = split_at_delims (cs->words, strlen (cs->words), (char *)NULL, -1, 0, (int *)NULL, (int *)NULL);
+ if (l == 0)
+ return ((STRINGLIST *)NULL);
+ /* This will jump back to the top level if the expansion fails... */
+ l2 = expand_words_shellexp (l);
+ dispose_words (l);
+
+ nw = list_length (l2);
+ sl = strlist_create (nw + 1);
+
+ ntxt = bash_dequote_text (text);
+ tlen = STRLEN (ntxt);
+
+ for (nw = 0, l = l2; l; l = l->next)
+ {
+ if (tlen == 0 || STREQN (l->word->word, ntxt, tlen))
+ sl->list[nw++] = STRDUP (l->word->word);
+ }
+ sl->list[sl->list_len = nw] = (char *)NULL;
+
+ dispose_words (l2);
+ FREE (ntxt);
+ return sl;
+}
+
+#ifdef ARRAY_VARS
+
+static SHELL_VAR *
+bind_comp_words (lwords)
+ WORD_LIST *lwords;
+{
+ SHELL_VAR *v;
+
+ v = find_variable ("COMP_WORDS");
+ if (v == 0)
+ v = make_new_array_variable ("COMP_WORDS");
+ if (readonly_p (v))
+ VUNSETATTR (v, att_readonly);
+ if (array_p (v) == 0)
+ v = convert_var_to_array (v);
+ v = assign_array_var_from_word_list (v, lwords, 0);
+
+ VUNSETATTR (v, att_invisible);
+ return v;
+}
+#endif /* ARRAY_VARS */
+
+static void
+bind_compfunc_variables (line, ind, lwords, cw, exported)
+ char *line;
+ int ind;
+ WORD_LIST *lwords;
+ int cw, exported;
+{
+ char ibuf[INT_STRLEN_BOUND(int) + 1];
+ char *value;
+ SHELL_VAR *v;
+ size_t llen;
+ int c;
+
+ /* Set the variables that the function expects while it executes. Maybe
+ these should be in the function environment (temporary_env). */
+ v = bind_variable ("COMP_LINE", line, 0);
+ if (v && exported)
+ VSETATTR(v, att_exported);
+
+ /* Post bash-4.2: COMP_POINT is characters instead of bytes. */
+ c = line[ind];
+ line[ind] = '\0';
+ llen = MB_STRLEN (line);
+ line[ind] = c;
+ value = inttostr (llen, ibuf, sizeof(ibuf));
+ v = bind_int_variable ("COMP_POINT", value);
+ if (v && exported)
+ VSETATTR(v, att_exported);
+
+ value = inttostr (rl_completion_type, ibuf, sizeof (ibuf));
+ v = bind_int_variable ("COMP_TYPE", value);
+ if (v && exported)
+ VSETATTR(v, att_exported);
+
+ value = inttostr (rl_completion_invoking_key, ibuf, sizeof (ibuf));
+ v = bind_int_variable ("COMP_KEY", value);
+ if (v && exported)
+ VSETATTR(v, att_exported);
+
+ /* Since array variables can't be exported, we don't bother making the
+ array of words. */
+ if (exported == 0)
+ {
+#ifdef ARRAY_VARS
+ v = bind_comp_words (lwords);
+ value = inttostr (cw, ibuf, sizeof(ibuf));
+ bind_int_variable ("COMP_CWORD", value);
+#endif
+ }
+ else
+ array_needs_making = 1;
+}
+
+static void
+unbind_compfunc_variables (exported)
+ int exported;
+{
+ unbind_variable ("COMP_LINE");
+ unbind_variable ("COMP_POINT");
+ unbind_variable ("COMP_TYPE");
+ unbind_variable ("COMP_KEY");
+#ifdef ARRAY_VARS
+ unbind_variable ("COMP_WORDS");
+ unbind_variable ("COMP_CWORD");
+#endif
+ if (exported)
+ array_needs_making = 1;
+}
+
+/* Build the list of words to pass to a function or external command
+ as arguments. When the function or command is invoked,
+
+ $0 == function or command being invoked
+ $1 == command name
+ $2 == word to be completed (possibly null)
+ $3 == previous word
+
+ Functions can access all of the words in the current command line
+ with the COMP_WORDS array. External commands cannot; they have to
+ make do with the COMP_LINE and COMP_POINT variables. */
+
+static WORD_LIST *
+build_arg_list (cmd, cname, text, lwords, ind)
+ char *cmd;
+ const char *cname;
+ const char *text;
+ WORD_LIST *lwords;
+ int ind;
+{
+ WORD_LIST *ret, *cl, *l;
+ WORD_DESC *w;
+ int i;
+
+ ret = (WORD_LIST *)NULL;
+ w = make_word (cmd);
+ ret = make_word_list (w, (WORD_LIST *)NULL); /* $0 */
+
+ w = make_word (cname); /* $1 */
+ cl = ret->next = make_word_list (w, (WORD_LIST *)NULL);
+
+ w = make_word (text);
+ cl->next = make_word_list (w, (WORD_LIST *)NULL); /* $2 */
+ cl = cl->next;
+
+ /* Search lwords for current word */
+ for (l = lwords, i = 1; l && i < ind-1; l = l->next, i++)
+ ;
+ w = (l && l->word) ? copy_word (l->word) : make_word ("");
+ cl->next = make_word_list (w, (WORD_LIST *)NULL);
+
+ return ret;
+}
+
+/* Build a command string with
+ $0 == cs->funcname (function to execute for completion list)
+ $1 == command name (command being completed)
+ $2 = word to be completed (possibly null)
+ $3 = previous word
+ and run in the current shell. The function should put its completion
+ list into the array variable COMPREPLY. We build a STRINGLIST
+ from the results and return it.
+
+ Since the shell function should return its list of matches in an array
+ variable, this does nothing if arrays are not compiled into the shell. */
+
+static STRINGLIST *
+gen_shell_function_matches (cs, cmd, text, line, ind, lwords, nw, cw, foundp)
+ COMPSPEC *cs;
+ const char *cmd;
+ const char *text;
+ char *line;
+ int ind;
+ WORD_LIST *lwords;
+ int nw, cw;
+ int *foundp;
+{
+ char *funcname;
+ STRINGLIST *sl;
+ SHELL_VAR *f, *v;
+ WORD_LIST *cmdlist;
+ int fval, found;
+ sh_parser_state_t ps;
+ sh_parser_state_t * restrict pps;
+#if defined (ARRAY_VARS)
+ ARRAY *a;
+#endif
+
+ found = 0;
+ if (foundp)
+ *foundp = found;
+
+ funcname = cs->funcname;
+ f = find_function (funcname);
+ if (f == 0)
+ {
+ internal_error (_("completion: function `%s' not found"), funcname);
+ rl_ding ();
+ rl_on_new_line ();
+ return ((STRINGLIST *)NULL);
+ }
+
+#if !defined (ARRAY_VARS)
+ return ((STRINGLIST *)NULL);
+#else
+
+ /* We pass cw - 1 because command_line_to_word_list returns indices that are
+ 1-based, while bash arrays are 0-based. */
+ bind_compfunc_variables (line, ind, lwords, cw - 1, 0);
+
+ cmdlist = build_arg_list (funcname, cmd, text, lwords, cw);
+
+ pps = &ps;
+ save_parser_state (pps);
+ begin_unwind_frame ("gen-shell-function-matches");
+ add_unwind_protect (restore_parser_state, (char *)pps);
+ add_unwind_protect (dispose_words, (char *)cmdlist);
+ add_unwind_protect (unbind_compfunc_variables, (char *)0);
+
+ fval = execute_shell_function (f, cmdlist);
+
+ discard_unwind_frame ("gen-shell-function-matches");
+ restore_parser_state (pps);
+
+ found = fval != EX_NOTFOUND;
+ if (fval == EX_RETRYFAIL)
+ found |= PCOMP_RETRYFAIL;
+ if (foundp)
+ *foundp = found;
+
+ /* Now clean up and destroy everything. */
+ dispose_words (cmdlist);
+ unbind_compfunc_variables (0);
+
+ /* The list of completions is returned in the array variable COMPREPLY. */
+ v = find_variable ("COMPREPLY");
+ if (v == 0)
+ return ((STRINGLIST *)NULL);
+ if (array_p (v) == 0)
+ v = convert_var_to_array (v);
+
+ VUNSETATTR (v, att_invisible);
+
+ a = array_cell (v);
+ if (found == 0 || (found & PCOMP_RETRYFAIL) || a == 0 || array_empty (a))
+ sl = (STRINGLIST *)NULL;
+ else
+ {
+ /* XXX - should we filter the list of completions so only those matching
+ TEXT are returned? Right now, we do not. */
+ sl = strlist_create (0);
+ sl->list = array_to_argv (a);
+ sl->list_len = sl->list_size = array_num_elements (a);
+ }
+
+ /* XXX - should we unbind COMPREPLY here? */
+ unbind_variable ("COMPREPLY");
+
+ return (sl);
+#endif
+}
+
+/* Build a command string with
+ $0 == cs->command (command to execute for completion list)
+ $1 == command name (command being completed)
+ $2 = word to be completed (possibly null)
+ $3 = previous word
+ and run in with command substitution. Parse the results, one word
+ per line, with backslashes allowed to escape newlines. Build a
+ STRINGLIST from the results and return it. */
+
+static STRINGLIST *
+gen_command_matches (cs, cmd, text, line, ind, lwords, nw, cw)
+ COMPSPEC *cs;
+ const char *cmd;
+ const char *text;
+ char *line;
+ int ind;
+ WORD_LIST *lwords;
+ int nw, cw;
+{
+ char *csbuf, *cscmd, *t;
+ int cmdlen, cmdsize, n, ws, we;
+ WORD_LIST *cmdlist, *cl;
+ WORD_DESC *tw;
+ STRINGLIST *sl;
+
+ bind_compfunc_variables (line, ind, lwords, cw, 1);
+ cmdlist = build_arg_list (cs->command, cmd, text, lwords, cw);
+
+ /* Estimate the size needed for the buffer. */
+ n = strlen (cs->command);
+ cmdsize = n + 1;
+ for (cl = cmdlist->next; cl; cl = cl->next)
+ cmdsize += STRLEN (cl->word->word) + 3;
+ cmdsize += 2;
+
+ /* allocate the string for the command and fill it in. */
+ cscmd = (char *)xmalloc (cmdsize + 1);
+
+ strcpy (cscmd, cs->command); /* $0 */
+ cmdlen = n;
+ cscmd[cmdlen++] = ' ';
+ for (cl = cmdlist->next; cl; cl = cl->next) /* $1, $2, $3, ... */
+ {
+ t = sh_single_quote (cl->word->word ? cl->word->word : "");
+ n = strlen (t);
+ RESIZE_MALLOCED_BUFFER (cscmd, cmdlen, n + 2, cmdsize, 64);
+ strcpy (cscmd + cmdlen, t);
+ cmdlen += n;
+ if (cl->next)
+ cscmd[cmdlen++] = ' ';
+ free (t);
+ }
+ cscmd[cmdlen] = '\0';
+
+ tw = command_substitute (cscmd, 0);
+ csbuf = tw ? tw->word : (char *)NULL;
+ if (tw)
+ dispose_word_desc (tw);
+
+ /* Now clean up and destroy everything. */
+ dispose_words (cmdlist);
+ free (cscmd);
+ unbind_compfunc_variables (1);
+
+ if (csbuf == 0 || *csbuf == '\0')
+ {
+ FREE (csbuf);
+ return ((STRINGLIST *)NULL);
+ }
+
+ /* Now break CSBUF up at newlines, with backslash allowed to escape a
+ newline, and put the individual words into a STRINGLIST. */
+ sl = strlist_create (16);
+ for (ws = 0; csbuf[ws]; )
+ {
+ we = ws;
+ while (csbuf[we] && csbuf[we] != '\n')
+ {
+ if (csbuf[we] == '\\' && csbuf[we+1] == '\n')
+ we++;
+ we++;
+ }
+ t = substring (csbuf, ws, we);
+ if (sl->list_len >= sl->list_size - 1)
+ strlist_resize (sl, sl->list_size + 16);
+ sl->list[sl->list_len++] = t;
+ while (csbuf[we] == '\n') we++;
+ ws = we;
+ }
+ sl->list[sl->list_len] = (char *)NULL;
+
+ free (csbuf);
+ return (sl);
+}
+
+static WORD_LIST *
+command_line_to_word_list (line, llen, sentinel, nwp, cwp)
+ char *line;
+ int llen, sentinel, *nwp, *cwp;
+{
+ WORD_LIST *ret;
+ char *delims;
+
+#if 0
+ delims = "()<>;&| \t\n"; /* shell metacharacters break words */
+#else
+ delims = rl_completer_word_break_characters;
+#endif
+ ret = split_at_delims (line, llen, delims, sentinel, SD_NOQUOTEDELIM, nwp, cwp);
+ return (ret);
+}
+
+/* Evaluate COMPSPEC *cs and return all matches for WORD. */
+
+STRINGLIST *
+gen_compspec_completions (cs, cmd, word, start, end, foundp)
+ COMPSPEC *cs;
+ const char *cmd;
+ const char *word;
+ int start, end;
+ int *foundp;
+{
+ STRINGLIST *ret, *tmatches;
+ char *line;
+ int llen, nw, cw, found, foundf;
+ WORD_LIST *lwords;
+ WORD_DESC *lw;
+ COMPSPEC *tcs;
+
+ found = 1;
+
+#ifdef DEBUG
+ debug_printf ("gen_compspec_completions (%s, %s, %d, %d)", cmd, word, start, end);
+ debug_printf ("gen_compspec_completions: %s -> %p", cmd, cs);
+#endif
+ ret = gen_action_completions (cs, word);
+#ifdef DEBUG
+ if (ret && progcomp_debug)
+ {
+ debug_printf ("gen_action_completions (%p, %s) -->", cs, word);
+ strlist_print (ret, "\t");
+ rl_on_new_line ();
+ }
+#endif
+
+ /* Now we start generating completions based on the other members of CS. */
+ if (cs->globpat)
+ {
+ tmatches = gen_globpat_matches (cs, word);
+ if (tmatches)
+ {
+#ifdef DEBUG
+ if (progcomp_debug)
+ {
+ debug_printf ("gen_globpat_matches (%p, %s) -->", cs, word);
+ strlist_print (tmatches, "\t");
+ rl_on_new_line ();
+ }
+#endif
+ ret = strlist_append (ret, tmatches);
+ strlist_dispose (tmatches);
+ rl_filename_completion_desired = 1;
+ }
+ }
+
+ if (cs->words)
+ {
+ tmatches = gen_wordlist_matches (cs, word);
+ if (tmatches)
+ {
+#ifdef DEBUG
+ if (progcomp_debug)
+ {
+ debug_printf ("gen_wordlist_matches (%p, %s) -->", cs, word);
+ strlist_print (tmatches, "\t");
+ rl_on_new_line ();
+ }
+#endif
+ ret = strlist_append (ret, tmatches);
+ strlist_dispose (tmatches);
+ }
+ }
+
+ lwords = (WORD_LIST *)NULL;
+ line = (char *)NULL;
+ if (cs->command || cs->funcname)
+ {
+ /* If we have a command or function to execute, we need to first break
+ the command line into individual words, find the number of words,
+ and find the word in the list containing the word to be completed. */
+ line = substring (rl_line_buffer, start, end);
+ llen = end - start;
+
+#ifdef DEBUG
+ debug_printf ("command_line_to_word_list (%s, %d, %d, %p, %p)",
+ line, llen, rl_point - start, &nw, &cw);
+#endif
+ lwords = command_line_to_word_list (line, llen, rl_point - start, &nw, &cw);
+ /* If we skipped a NULL word at the beginning of the line, add it back */
+ if (lwords && lwords->word && cmd[0] == 0 && lwords->word->word[0] != 0)
+ {
+ lw = make_bare_word (cmd);
+ lwords = make_word_list (lw, lwords);
+ nw++;
+ cw++;
+ }
+#ifdef DEBUG
+ if (lwords == 0 && llen > 0)
+ debug_printf ("ERROR: command_line_to_word_list returns NULL");
+ else if (progcomp_debug)
+ {
+ debug_printf ("command_line_to_word_list -->");
+ printf ("\t");
+ print_word_list (lwords, "!");
+ printf ("\n");
+ fflush(stdout);
+ rl_on_new_line ();
+ }
+#endif
+ }
+
+ if (cs->funcname)
+ {
+ foundf = 0;
+ tmatches = gen_shell_function_matches (cs, cmd, word, line, rl_point - start, lwords, nw, cw, &foundf);
+ if (foundf != 0)
+ found = foundf;
+ if (tmatches)
+ {
+#ifdef DEBUG
+ if (progcomp_debug)
+ {
+ debug_printf ("gen_shell_function_matches (%p, %s, %s, %p, %d, %d) -->", cs, cmd, word, lwords, nw, cw);
+ strlist_print (tmatches, "\t");
+ rl_on_new_line ();
+ }
+#endif
+ ret = strlist_append (ret, tmatches);
+ strlist_dispose (tmatches);
+ }
+ }
+
+ if (cs->command)
+ {
+ tmatches = gen_command_matches (cs, cmd, word, line, rl_point - start, lwords, nw, cw);
+ if (tmatches)
+ {
+#ifdef DEBUG
+ if (progcomp_debug)
+ {
+ debug_printf ("gen_command_matches (%p, %s, %s, %p, %d, %d) -->", cs, cmd, word, lwords, nw, cw);
+ strlist_print (tmatches, "\t");
+ rl_on_new_line ();
+ }
+#endif
+ ret = strlist_append (ret, tmatches);
+ strlist_dispose (tmatches);
+ }
+ }
+
+ if (cs->command || cs->funcname)
+ {
+ if (lwords)
+ dispose_words (lwords);
+ FREE (line);
+ }
+
+ if (foundp)
+ *foundp = found;
+
+ if (found == 0 || (found & PCOMP_RETRYFAIL))
+ {
+ strlist_dispose (ret);
+ return NULL;
+ }
+
+ if (cs->filterpat)
+ {
+ tmatches = filter_stringlist (ret, cs->filterpat, word);
+#ifdef DEBUG
+ if (progcomp_debug)
+ {
+ debug_printf ("filter_stringlist (%p, %s, %s) -->", ret, cs->filterpat, word);
+ strlist_print (tmatches, "\t");
+ rl_on_new_line ();
+ }
+#endif
+ if (ret && ret != tmatches)
+ {
+ FREE (ret->list);
+ free (ret);
+ }
+ ret = tmatches;
+ }
+
+ if (cs->prefix || cs->suffix)
+ ret = strlist_prefix_suffix (ret, cs->prefix, cs->suffix);
+
+ /* If no matches have been generated and the user has specified that
+ directory completion should be done as a default, call
+ gen_action_completions again to generate a list of matching directory
+ names. */
+ if ((ret == 0 || ret->list_len == 0) && (cs->options & COPT_DIRNAMES))
+ {
+ tcs = compspec_create ();
+ tcs->actions = CA_DIRECTORY;
+ FREE (ret);
+ ret = gen_action_completions (tcs, word);
+ compspec_dispose (tcs);
+ }
+ else if (cs->options & COPT_PLUSDIRS)
+ {
+ tcs = compspec_create ();
+ tcs->actions = CA_DIRECTORY;
+ tmatches = gen_action_completions (tcs, word);
+ ret = strlist_append (ret, tmatches);
+ strlist_dispose (tmatches);
+ compspec_dispose (tcs);
+ }
+
+ return (ret);
+}
+
+void
+pcomp_set_readline_variables (flags, nval)
+ int flags, nval;
+{
+ /* If the user specified that the compspec returns filenames, make
+ sure that readline knows it. */
+ if (flags & COPT_FILENAMES)
+ rl_filename_completion_desired = nval;
+ /* If the user doesn't want a space appended, tell readline. */
+ if (flags & COPT_NOSPACE)
+ rl_completion_suppress_append = nval;
+ /* The value here is inverted, since the default is on and the `noquote'
+ option is supposed to turn it off */
+ if (flags & COPT_NOQUOTE)
+ rl_filename_quoting_desired = 1 - nval;
+}
+
+/* Set or unset FLAGS in the options word of the current compspec.
+ SET_OR_UNSET is 1 for setting, 0 for unsetting. */
+void
+pcomp_set_compspec_options (cs, flags, set_or_unset)
+ COMPSPEC *cs;
+ int flags, set_or_unset;
+{
+ if (cs == 0 && ((cs = pcomp_curcs) == 0))
+ return;
+ if (set_or_unset)
+ cs->options |= flags;
+ else
+ cs->options &= ~flags;
+}
+
+static STRINGLIST *
+gen_progcomp_completions (ocmd, cmd, word, start, end, foundp, retryp, lastcs)
+ const char *ocmd;
+ const char *cmd;
+ const char *word;
+ int start, end;
+ int *foundp, *retryp;
+ COMPSPEC **lastcs;
+{
+ COMPSPEC *cs, *oldcs;
+ const char *oldcmd;
+ STRINGLIST *ret;
+
+ cs = progcomp_search (ocmd);
+
+ if (cs == 0 || cs == *lastcs)
+ {
+#if 0
+ if (foundp)
+ *foundp = 0;
+#endif
+ return (NULL);
+ }
+
+ if (*lastcs)
+ compspec_dispose (*lastcs);
+ cs->refcount++; /* XXX */
+ *lastcs = cs;
+
+ cs = compspec_copy (cs);
+
+ oldcs = pcomp_curcs;
+ oldcmd = pcomp_curcmd;
+
+ pcomp_curcs = cs;
+ pcomp_curcmd = cmd;
+
+ ret = gen_compspec_completions (cs, cmd, word, start, end, foundp);
+
+ pcomp_curcs = oldcs;
+ pcomp_curcmd = oldcmd;
+
+ /* We need to conditionally handle setting *retryp here */
+ if (retryp)
+ *retryp = foundp && (*foundp & PCOMP_RETRYFAIL);
+
+ if (foundp)
+ {
+ *foundp &= ~PCOMP_RETRYFAIL;
+ *foundp |= cs->options;
+ }
+
+ compspec_dispose (cs);
+ return ret;
+}
+
+/* The driver function for the programmable completion code. Returns a list
+ of matches for WORD, which is an argument to command CMD. START and END
+ bound the command currently being completed in rl_line_buffer. */
+char **
+programmable_completions (cmd, word, start, end, foundp)
+ const char *cmd;
+ const char *word;
+ int start, end, *foundp;
+{
+ COMPSPEC *cs, *lastcs;
+ STRINGLIST *ret;
+ char **rmatches, *t;
+ int found, retry, count;
+
+ lastcs = 0;
+ found = count = 0;
+
+ do
+ {
+ retry = 0;
+
+ /* We look at the basename of CMD if the full command does not have
+ an associated COMPSPEC. */
+ ret = gen_progcomp_completions (cmd, cmd, word, start, end, &found, &retry, &lastcs);
+ if (found == 0)
+ {
+ t = strrchr (cmd, '/');
+ if (t && *(++t))
+ ret = gen_progcomp_completions (t, cmd, word, start, end, &found, &retry, &lastcs);
+ }
+
+ if (found == 0)
+ ret = gen_progcomp_completions (DEFAULTCMD, cmd, word, start, end, &found, &retry, &lastcs);
+
+ count++;
+
+ if (count > 32)
+ {
+ internal_warning ("programmable_completion: %s: possible retry loop", cmd);
+ break;
+ }
+ }
+ while (retry);
+
+ if (ret)
+ {
+ rmatches = ret->list;
+ free (ret);
+ }
+ else
+ rmatches = (char **)NULL;
+
+ if (foundp)
+ *foundp = found;
+
+ if (lastcs) /* XXX - should be while? */
+ compspec_dispose (lastcs);
+
+ return (rmatches);
+}
+
+#endif /* PROGRAMMABLE_COMPLETION */
-# German language file for GNU Bash 4.2
+# German language file for GNU Bash 4.3
# Copyright (C) 2011 Free Software Foundation, Inc.
# This file is distributed under the same license as the bash package.
-# Nils Naumann <nnau@gmx.net>, 1996-2011.
+# Nils Naumann <nnau@gmx.net>, 1996-2013.
msgid ""
msgstr ""
-"Project-Id-Version: bash 4.2\n"
+"Project-Id-Version: bash 4.3-pre2\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-08-14 11:14-0400\n"
-"PO-Revision-Date: 2012-09-24 19:12+0200\n"
+"POT-Creation-Date: 2013-03-08 16:00-0500\n"
+"PO-Revision-Date: 2013-08-26 21:04+0200\n"
"Last-Translator: Nils Naumann <nau@gmx.net>\n"
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
"Language: de\n"
msgid "bad array subscript"
msgstr "Falscher Feldbezeichner."
-#: arrayfunc.c:356 builtins/declare.def:585
+#: arrayfunc.c:356 builtins/declare.def:578
#, c-format
msgid "%s: cannot convert indexed to associative array"
msgstr "%s: Kann nicht das indizierte in ein assoziatives Array umwandeln."
#: arrayfunc.c:586
#, c-format
msgid "%s: %s: must use subscript when assigning associative array"
-msgstr ""
-"%s: %s: Ein Feldbezeicher wird zum Zuweisen eines assoziativen Arrays "
-"benötigt."
+msgstr "%s: %s: Ein Feldbezeicher wird zum Zuweisen eines assoziativen Arrays benötigt."
#: bashhist.c:388
#, c-format
msgid "%s: cannot create: %s"
msgstr "%s: Kann die Datei %s nicht erzeugen."
-#: bashline.c:3928
+#: bashline.c:3923
msgid "bash_execute_unix_command: cannot find keymap for command"
-msgstr ""
-"bash_execute_unix_command: Kann nicht die Tastenzuordnung für das Kommando "
-"finden."
+msgstr "bash_execute_unix_command: Kann nicht die Tastenzuordnung für das Kommando finden."
-#: bashline.c:4015
+#: bashline.c:4010
#, c-format
msgid "%s: first non-whitespace character is not `\"'"
msgstr " %s: Das erste Zeichen ist nicht `\\'."
-#: bashline.c:4044
+#: bashline.c:4039
#, c-format
msgid "no closing `%c' in %s"
msgstr "fehlende schließende `%c' in %s."
-#: bashline.c:4078
+#: bashline.c:4073
#, c-format
msgid "%s: missing colon separator"
msgstr "%s: Fehlender Doppelpunkt."
msgid "invalid hex number"
msgstr "Ungültige hexadezimale Zahl."
-#: builtins/common.c:242 expr.c:1461
+#: builtins/common.c:242 expr.c:1451
msgid "invalid number"
msgstr "Ungültige Zahl."
msgid "can only be used in a function"
msgstr "kann nur innerhalb einer Funktion benutzt werden."
-#: builtins/declare.def:315 builtins/declare.def:533
+#: builtins/declare.def:311 builtins/declare.def:526
#, c-format
msgid "%s: reference variable cannot be an array"
msgstr ""
-#: builtins/declare.def:324
+#: builtins/declare.def:317
#, c-format
msgid "%s: nameref variable self references not allowed"
msgstr ""
-#: builtins/declare.def:422
+#: builtins/declare.def:415
msgid "cannot use `-f' to make functions"
msgstr "Mit `-f' können keine Funktionen erzeugt werden."
-#: builtins/declare.def:434 execute_cmd.c:5328
+#: builtins/declare.def:427 execute_cmd.c:5315
#, c-format
msgid "%s: readonly function"
msgstr "%s: Schreibgeschützte Funktion."
-#: builtins/declare.def:572
+#: builtins/declare.def:565
#, c-format
msgid "%s: cannot destroy array variables in this way"
msgstr "%s: Kann Feldvariablen nicht auf diese Art löschen."
-#: builtins/declare.def:579 builtins/read.def:733
+#: builtins/declare.def:572 builtins/read.def:721
#, c-format
msgid "%s: cannot convert associative to indexed array"
-msgstr ""
-"%s: Konvertieren von assoziativen in indizierte Arrays ist nicht möglich."
+msgstr "%s: Konvertieren von assoziativen in indizierte Arrays ist nicht möglich."
#: builtins/enable.def:137 builtins/enable.def:145
msgid "dynamic loading not available"
msgid "%s: cannot delete: %s"
msgstr "%s: Kann nicht löschen: %s"
-#: builtins/evalfile.c:140 builtins/hash.def:171 execute_cmd.c:5175
+#: builtins/evalfile.c:140 builtins/hash.def:171 execute_cmd.c:5162
#: shell.c:1481
#, c-format
msgid "%s: is a directory"
msgid "no command found"
msgstr "Kein Kommando gefunden."
-#: builtins/fc.def:320 builtins/fc.def:369
+#: builtins/fc.def:312 builtins/fc.def:359
msgid "history specification"
msgstr ""
-#: builtins/fc.def:390
+#: builtins/fc.def:380
#, c-format
msgid "%s: cannot open temp file: %s"
msgstr "%s: Kann die tempräre Datei nicht öffnen: %s"
msgstr[0] "Shell Kommandos auf die das Schlüsselwort zutrifft `"
msgstr[1] "Shell Kommandos auf die die Schlüsselwörter zutreffen `"
-#: builtins/help.def:182
+#: builtins/help.def:168
#, c-format
-msgid ""
-"no help topics match `%s'. Try `help help' or `man -k %s' or `info %s'."
-msgstr ""
-"Auf `%s' trifft kein Hilfethema zu. Probieren Sie `help help', `man -k %s' "
-"oder `info %s'."
+msgid "no help topics match `%s'. Try `help help' or `man -k %s' or `info %s'."
+msgstr "Auf `%s' trifft kein Hilfethema zu. Probieren Sie `help help', `man -k %s' oder `info %s'."
-#: builtins/help.def:199
+#: builtins/help.def:185
#, c-format
msgid "%s: cannot open: %s"
msgstr "%s: Kann die Datei nicht öffnen: %s"
-#: builtins/help.def:485
+#: builtins/help.def:471
#, c-format
msgid ""
"These shell commands are defined internally. Type `help' to see this list.\n"
msgid "Unknown error"
msgstr "Unbekannter Fehler."
-#: builtins/let.def:95 builtins/let.def:120 expr.c:583 expr.c:598
+#: builtins/let.def:95 builtins/let.def:120 expr.c:586 expr.c:601
msgid "expression expected"
msgstr "Ausdruck erwartet."
msgstr "kein anderes Verzeichnis"
#: builtins/pushd.def:354
-#, fuzzy, c-format
+#, c-format
msgid "%s: invalid argument"
-msgstr "%s: Ungültiges Grenzwertargument."
+msgstr "%s: Ungültiges Argument."
#: builtins/pushd.def:468
msgid "<no current directory>"
" \twith its position in the stack\n"
" \n"
" Arguments:\n"
-" +N\tDisplays the Nth entry counting from the left of the list shown "
-"by\n"
+" +N\tDisplays the Nth entry counting from the left of the list shown by\n"
" \tdirs when invoked without options, starting with zero.\n"
" \n"
-" -N\tDisplays the Nth entry counting from the right of the list shown "
-"by\n"
+" -N\tDisplays the Nth entry counting from the right of the list shown by\n"
"\tdirs when invoked without options, starting with zero."
msgstr ""
"Zeigt die Liste der gegenwärtig gespeicherten Verzeichnisse an. Durch\n"
msgid "%s: invalid timeout specification"
msgstr "%s: Ungültige Wartezeitangebe."
-#: builtins/read.def:678
+#: builtins/read.def:666
#, c-format
msgid "read error: %d: %s"
msgstr "Lesefehler: %d: %s"
#: builtins/return.def:75
msgid "can only `return' from a function or sourced script"
-msgstr ""
-"»Return« ist nur aus einer Funktion oder einem mit »source« ausgefühten "
-"Skript möglich."
+msgstr "»Return« ist nur aus einer Funktion oder einem mit »source« ausgefühten Skript möglich."
#: builtins/set.def:782
msgid "cannot simultaneously unset a function and a variable"
-msgstr ""
-"Gleichzeitiges `unset' einer Funktion und einer Variable ist nicht möglich."
+msgstr "Gleichzeitiges `unset' einer Funktion und einer Variable ist nicht möglich."
#: builtins/set.def:826
#, c-format
msgid "cannot redirect standard input from /dev/null: %s"
msgstr "Kann nicht die Standardeingabe von /dev/null umleiten: %s"
-#: execute_cmd.c:1230
+#: execute_cmd.c:1228
#, c-format
msgid "TIMEFORMAT: `%c': invalid format character"
msgstr "TIMEFORMAT: `%c': Ungültiges Formatzeichen."
-#: execute_cmd.c:2284
+#: execute_cmd.c:2282
msgid "pipe error"
msgstr "Pipe-Fehler"
-#: execute_cmd.c:4358
+#: execute_cmd.c:4347
#, c-format
msgid "%s: maximum function nesting level exceeded (%d)"
msgstr ""
-#: execute_cmd.c:4851
+#: execute_cmd.c:4840
#, c-format
msgid "%s: restricted: cannot specify `/' in command names"
msgstr "%s: Verboten: `/' ist in Kommandonamen unzulässig."
-#: execute_cmd.c:4940
+#: execute_cmd.c:4929
#, c-format
msgid "%s: command not found"
msgstr "%s: Kommando nicht gefunden."
-#: execute_cmd.c:5173
+#: execute_cmd.c:5160
#, c-format
msgid "%s: %s"
msgstr "%s: %s"
-#: execute_cmd.c:5210
+#: execute_cmd.c:5197
#, c-format
msgid "%s: %s: bad interpreter"
msgstr "%s: %s: Defekter Interpreter"
-#: execute_cmd.c:5247
-#, fuzzy, c-format
+#: execute_cmd.c:5234
+#, c-format
msgid "%s: cannot execute binary file: %s"
-msgstr "%s: Kann die Datei nicht ausführen."
+msgstr "%s: Kann die Binärdatei nicht ausführen: %s"
-#: execute_cmd.c:5319
-#, fuzzy, c-format
+#: execute_cmd.c:5306
+#, c-format
msgid "`%s': is a special builtin"
-msgstr "%s ist eine von der Shell mitgelieferte Funktion.\n"
+msgstr "`%s' ist eine spezielle eingebaute Funktion."
-#: execute_cmd.c:5371
+#: execute_cmd.c:5358
#, c-format
msgid "cannot duplicate fd %d to fd %d"
msgstr "Kann fd %d nicht auf fd %d verdoppeln."
-#: expr.c:259
+#: expr.c:262
msgid "expression recursion level exceeded"
msgstr "Zu viele Rekursionen in Ausdruck."
-#: expr.c:283
+#: expr.c:286
msgid "recursion stack underflow"
msgstr "Rekursionsstapel leer."
-#: expr.c:431
+#: expr.c:434
msgid "syntax error in expression"
msgstr "Syntaxfehler im Ausdruck."
-#: expr.c:475
+#: expr.c:478
msgid "attempted assignment to non-variable"
msgstr "Versuchte Zuweisung zu keiner Variablen."
-#: expr.c:495 expr.c:851
+#: expr.c:498 expr.c:847
msgid "division by 0"
msgstr "Division durch 0."
-#: expr.c:542
+#: expr.c:545
msgid "bug: bad expassign token"
msgstr "Fehler: Falscher Zuweisungsoperator."
-#: expr.c:595
+#: expr.c:598
msgid "`:' expected for conditional expression"
msgstr "`:' für ein bedingten Ausdruck erwaret."
-#: expr.c:910
+#: expr.c:904
msgid "exponent less than 0"
msgstr "Der Exponent ist kleiner als 0."
-#: expr.c:967
+#: expr.c:957
msgid "identifier expected after pre-increment or pre-decrement"
-msgstr ""
-"Nach einem Präinkrement oder Prädekrement wird ein Bezeichner erwartet."
+msgstr "Nach einem Präinkrement oder Prädekrement wird ein Bezeichner erwartet."
-#: expr.c:993
+#: expr.c:983
msgid "missing `)'"
msgstr "Fehlende `)'"
-#: expr.c:1044 expr.c:1381
+#: expr.c:1034 expr.c:1371
msgid "syntax error: operand expected"
msgstr "Syntax Fehler: Operator erwartet."
-#: expr.c:1383
+#: expr.c:1373
msgid "syntax error: invalid arithmetic operator"
msgstr "Syntaxfehler: Ungültiger arithmetischer Operator."
-#: expr.c:1407
+#: expr.c:1397
#, c-format
msgid "%s%s%s: %s (error token is \"%s\")"
msgstr "%s%s%s: %s (Fehlerverursachendes Zeichen ist \\\"%s\\\")."
-#: expr.c:1465
+#: expr.c:1455
msgid "invalid arithmetic base"
msgstr "Ungültige Basis."
-#: expr.c:1485
+#: expr.c:1475
msgid "value too great for base"
msgstr "Der Wert ist für die aktuelle Basis zu groß."
-#: expr.c:1534
+#: expr.c:1524
#, c-format
msgid "%s: expression error\n"
msgstr "%s: Fehler im Ausdruck.\n"
msgid "getcwd: cannot access parent directories"
msgstr "getwd: Kann auf das übergeordnete Verzeichnis nicht zugreifen."
-#: input.c:101 subst.c:5129
+#: input.c:101 subst.c:5067
#, c-format
msgid "cannot reset nodelay mode for fd %d"
msgstr "Konnte den No-Delay Modus für fd %d nicht wieder herstellen."
msgid "wait_for: No record of process %ld"
msgstr ""
-#: jobs.c:2692
+#: jobs.c:2689
#, c-format
msgid "wait_for_job: job %d is stopped"
msgstr ""
-#: jobs.c:2984
+#: jobs.c:2981
#, c-format
msgid "%s: job has terminated"
msgstr "%s: Programm ist beendet."
-#: jobs.c:2993
+#: jobs.c:2990
#, c-format
msgid "%s: job %d already in background"
msgstr ""
-#: jobs.c:3218
+#: jobs.c:3215
msgid "waitchld: turning on WNOHANG to avoid indefinite block"
msgstr ""
# Debug Ausgabe
-#: jobs.c:3709
+#: jobs.c:3699
#, c-format
msgid "%s: line %d: "
msgstr "%s: Zeile %d: "
-#: jobs.c:3723 nojobs.c:843
+#: jobs.c:3713 nojobs.c:843
#, c-format
msgid " (core dumped)"
msgstr " (Speicherabzug geschrieben)"
-#: jobs.c:3735 jobs.c:3748
+#: jobs.c:3725 jobs.c:3738
#, c-format
msgid "(wd now: %s)\n"
msgstr "(gegenwärtiges Arbeitsverzeichnis ist: %s)\n"
# interner Fehler
-#: jobs.c:3780
+#: jobs.c:3770
msgid "initialize_job_control: getpgrp failed"
msgstr "initialize_jobs: getpgrp war nicht erfolgreich."
# interner Fehler
-#: jobs.c:3841
+#: jobs.c:3831
msgid "initialize_job_control: line discipline"
msgstr "initialize_job_control: line discipline"
# interner Fehler
-#: jobs.c:3851
+#: jobs.c:3841
msgid "initialize_job_control: setpgid"
msgstr "initialize_job_control: setpgid"
-#: jobs.c:3872 jobs.c:3881
+#: jobs.c:3862 jobs.c:3871
#, c-format
msgid "cannot set terminal process group (%d)"
msgstr "Kann die Prozessgruppe des Terminals nicht setzen (%d)."
-#: jobs.c:3886
+#: jobs.c:3876
msgid "no job control in this shell"
msgstr "Keine Job Steuerung in dieser Shell."
#: lib/malloc/malloc.c:801
msgid "malloc: block on free list clobbered"
-msgstr ""
-"Malloc: Ein frei gekennzeichneter Speicherbereich wurde überschrieben."
+msgstr "Malloc: Ein frei gekennzeichneter Speicherbereich wurde überschrieben."
#: lib/malloc/malloc.c:878
msgid "free: called with already freed block argument"
#: lib/malloc/malloc.c:1020
msgid "realloc: underflow detected; mh_nbytes out of range"
-msgstr ""
-"realloc: Underflow erkannt; mh_nbytes außerhalb des Gültigkeitsbereichs."
+msgstr "realloc: Underflow erkannt; mh_nbytes außerhalb des Gültigkeitsbereichs."
#: lib/malloc/malloc.c:1026
msgid "realloc: start and end chunk sizes differ"
#: lib/malloc/table.c:194
#, c-format
msgid "register_alloc: alloc table is full with FIND_ALLOC?\n"
-msgstr ""
-"register_alloc: Speicherzuordnungstabelle ist mit FIND_ALLOC gefüllt?\n"
+msgstr "register_alloc: Speicherzuordnungstabelle ist mit FIND_ALLOC gefüllt?\n"
#: lib/malloc/table.c:203
#, c-format
msgid "register_alloc: %p already in table as allocated?\n"
-msgstr ""
-"register_alloc: %p ist bereits in der Speicherzuordnungstabelle als belegt "
-"gekennzeichnet?\n"
+msgstr "register_alloc: %p ist bereits in der Speicherzuordnungstabelle als belegt gekennzeichnet?\n"
#: lib/malloc/table.c:256
#, c-format
msgid "register_free: %p already in table as free?\n"
-msgstr ""
-"register_free: %p ist bereits in der Speicherzuordnungstabelle als frei "
-"gekennzeichnet?\n"
+msgstr "register_free: %p ist bereits in der Speicherzuordnungstabelle als frei gekennzeichnet?\n"
#: lib/sh/fmtulong.c:102
msgid "invalid base"
#: make_cmd.c:662
#, c-format
msgid "here-document at line %d delimited by end-of-file (wanted `%s')"
-msgstr ""
-"Das in der Zeile %d beginnende Here-Dokument geht bis zum Dateiende "
-"(erwartet wird `%s')."
+msgstr "Das in der Zeile %d beginnende Here-Dokument geht bis zum Dateiende (erwartet wird `%s')."
#: make_cmd.c:759
#, c-format
msgid "make_redirection: redirection instruction `%d' out of range"
msgstr ""
-#: parse.y:3210 parse.y:3493
+#: parse.y:3209 parse.y:3480
#, c-format
msgid "unexpected EOF while looking for matching `%c'"
msgstr "Dateiende beim Suchen nach `%c' erreicht."
-#: parse.y:4099
+#: parse.y:4086
msgid "unexpected EOF while looking for `]]'"
msgstr "Dateiende beim Suchen nach `]]' erreicht."
-#: parse.y:4104
+#: parse.y:4091
#, c-format
msgid "syntax error in conditional expression: unexpected token `%s'"
msgstr "Syntaxfehler im bedingten Ausdruck: Unerwartetes Zeichen `%s'."
-#: parse.y:4108
+#: parse.y:4095
msgid "syntax error in conditional expression"
msgstr "Syntaxfehler im bedingen Ausdruck."
-#: parse.y:4186
+#: parse.y:4173
#, c-format
msgid "unexpected token `%s', expected `)'"
msgstr "Unerwartetes Zeichen: `%s' anstatt von `)'"
-#: parse.y:4190
+#: parse.y:4177
msgid "expected `)'"
msgstr "`)' erwartet."
-#: parse.y:4218
+#: parse.y:4205
#, c-format
msgid "unexpected argument `%s' to conditional unary operator"
msgstr ""
-#: parse.y:4222
+#: parse.y:4209
msgid "unexpected argument to conditional unary operator"
msgstr ""
-#: parse.y:4268
+#: parse.y:4255
#, c-format
msgid "unexpected token `%s', conditional binary operator expected"
msgstr ""
-#: parse.y:4272
+#: parse.y:4259
msgid "conditional binary operator expected"
msgstr ""
-#: parse.y:4294
+#: parse.y:4281
#, c-format
msgid "unexpected argument `%s' to conditional binary operator"
msgstr ""
-#: parse.y:4298
+#: parse.y:4285
msgid "unexpected argument to conditional binary operator"
msgstr ""
-#: parse.y:4309
+#: parse.y:4296
#, c-format
msgid "unexpected token `%c' in conditional command"
msgstr ""
-#: parse.y:4312
+#: parse.y:4299
#, c-format
msgid "unexpected token `%s' in conditional command"
msgstr ""
-#: parse.y:4316
+#: parse.y:4303
#, c-format
msgid "unexpected token %d in conditional command"
msgstr ""
-#: parse.y:5666
+#: parse.y:5649
#, c-format
msgid "syntax error near unexpected token `%s'"
msgstr "Syntaxfehler beim unerwarteten Wort `%s'"
-#: parse.y:5684
+#: parse.y:5667
#, c-format
msgid "syntax error near `%s'"
msgstr "Syntaxfehler beim unerwarteten Wort `%s'"
-#: parse.y:5694
+#: parse.y:5677
msgid "syntax error: unexpected end of file"
msgstr "Syntax Fehler: Unerwartetes Dateiende."
-#: parse.y:5694
+#: parse.y:5677
msgid "syntax error"
msgstr "Syntax Fehler"
# Du oder Sie?
-#: parse.y:5756
+#: parse.y:5739
#, c-format
msgid "Use \"%s\" to leave the shell.\n"
msgstr "Benutze \"%s\" um die Shell zu verlassen.\n"
-#: parse.y:5918
+#: parse.y:5901
msgid "unexpected EOF while looking for matching `)'"
msgstr "Dateiende beim Suchen nach passender `)' erreicht."
msgid "/dev/(tcp|udp)/host/port not supported without networking"
msgstr "/dev/(tcp|udp)/host/port Wird ohne Netzwerk nicht unterstützt"
-#: redir.c:861 redir.c:973 redir.c:1034 redir.c:1199
+#: redir.c:861 redir.c:971 redir.c:1032 redir.c:1194
msgid "redirection error: cannot duplicate fd"
msgstr ""
msgstr "Shell-Optionen:\n"
#: shell.c:1835
-#, fuzzy
msgid "\t-ilrsD or -c command or -O shopt_option\t\t(invocation only)\n"
-msgstr "\t-irsD oder -c Kommando\t\t(Nur Aufruf)\n"
+msgstr "\t-ilrsD oder -c Kommando\toder -O shopt_option (Nur Aufruf)\n"
#: shell.c:1850
#, c-format
msgid "Unknown Signal #%d"
msgstr "Unbekanntes Signal Nr.: %d."
-#: subst.c:1358 subst.c:1516
+#: subst.c:1352 subst.c:1510
#, c-format
msgid "bad substitution: no closing `%s' in %s"
msgstr "Falsche Ersetzung: Keine schließende `%s' in `%s' enthalten."
-#: subst.c:2829
+#: subst.c:2823
#, c-format
msgid "%s: cannot assign list to array member"
msgstr "%s: Kann einem Feldelement keine Liste zuweisen."
-#: subst.c:5026 subst.c:5042
+#: subst.c:4964 subst.c:4980
msgid "cannot make pipe for process substitution"
msgstr "Kann keine Pipe für die Prozeßersetzung erzeugen."
-#: subst.c:5074
+#: subst.c:5012
msgid "cannot make child for process substitution"
msgstr "Kann den Kindsprozess für die Prozeßersetzung nicht erzeugen."
-#: subst.c:5119
+#: subst.c:5057
#, c-format
msgid "cannot open named pipe %s for reading"
msgstr "Kann nicht die benannte Pipe %s zum lesen öffnen."
-#: subst.c:5121
+#: subst.c:5059
#, c-format
msgid "cannot open named pipe %s for writing"
msgstr "Kann nicht die benannte Pipe %s zum schreiben öffnen."
-#: subst.c:5139
+#: subst.c:5077
#, c-format
msgid "cannot duplicate named pipe %s as fd %d"
msgstr "Kann die benannte Pipe %s nicht auf fd %d."
-#: subst.c:5337
+#: subst.c:5273
msgid "cannot make pipe for command substitution"
msgstr "Kann keine Pipes für Kommandoersetzung erzeugen."
-#: subst.c:5375
+#: subst.c:5311
msgid "cannot make child for command substitution"
msgstr "Kann keinen Unterprozess für die Kommandoersetzung erzeugen."
# interner Fehler
-#: subst.c:5394
+#: subst.c:5330
msgid "command_substitute: cannot duplicate pipe as fd 1"
msgstr "Kommandoersetzung: Kann Pipe nicht als fd 1 duplizieren."
-#: subst.c:5798 subst.c:8001
+#: subst.c:5733 subst.c:7900
#, c-format
msgid "%s: invalid variable name for name reference"
msgstr ""
-#: subst.c:6009
+#: subst.c:5926
#, c-format
msgid "%s: parameter null or not set"
msgstr "%s: Parameter ist Null oder nicht gesetzt."
# interner Fehler
-#: subst.c:6281 subst.c:6296
+#: subst.c:6198 subst.c:6213
#, c-format
msgid "%s: substring expression < 0"
msgstr "%s: Teilstring-Ausdruck < 0."
-#: subst.c:7457
+#: subst.c:7356
#, c-format
msgid "%s: bad substitution"
msgstr "%s: Falsche Variablenersetzung."
-#: subst.c:7534
+#: subst.c:7433
#, c-format
msgid "$%s: cannot assign in this way"
msgstr "$%s: Kann so nicht zuweisen."
-#: subst.c:7868
-msgid ""
-"future versions of the shell will force evaluation as an arithmetic "
-"substitution"
-msgstr ""
-"Zukünftige Versionen dieser Shell werden das Auswerten arithmetischer "
-"Ersetzungen erzwingen."
+#: subst.c:7767
+msgid "future versions of the shell will force evaluation as an arithmetic substitution"
+msgstr "Zukünftige Versionen dieser Shell werden das Auswerten arithmetischer Ersetzungen erzwingen."
-#: subst.c:8372
+#: subst.c:8271
#, c-format
msgid "bad substitution: no closing \"`\" in %s"
msgstr "Falsche Ersetzung: Keine schließende \"`\" in %s."
-#: subst.c:9273
+#: subst.c:9172
#, c-format
msgid "no match: %s"
msgstr "Keine Entsprechung: %s"
msgid "invalid signal number"
msgstr "Ungültige Signalnummer."
-#: trap.c:354
+#: trap.c:348
#, c-format
msgid "run_pending_traps: bad value in trap_list[%d]: %p"
msgstr ""
-#: trap.c:358
+#: trap.c:352
#, c-format
-msgid ""
-"run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"
+msgid "run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"
msgstr ""
# Programmierfehler
-#: trap.c:413
+#: trap.c:398
#, c-format
msgid "trap_handler: bad signal %d"
msgstr "trap_handler: Falsches Signal %d."
-#: variables.c:382
+#: variables.c:380
#, c-format
msgid "error importing function definition for `%s'"
msgstr "Fehler beim Importieren der Funktionsdefinition für `%s'."
-#: variables.c:780
+#: variables.c:778
#, c-format
msgid "shell level (%d) too high, resetting to 1"
msgstr ""
-#: variables.c:1865
-#, c-format
-msgid "%s: circular name reference"
-msgstr ""
-
-#: variables.c:2228
+#: variables.c:2198
msgid "make_local_variable: no function context at current scope"
msgstr ""
-#: variables.c:2247
-#, fuzzy, c-format
+#: variables.c:2217
+#, c-format
msgid "%s: variable may not be assigned value"
-msgstr "%s: Kann fd keiner Variable zuweisen."
+msgstr "%s: Der Variable könnte kein Wert zugewiesen sein."
-#: variables.c:3600
+#: variables.c:3554
msgid "all_local_variables: no function context at current scope"
msgstr ""
-#: variables.c:3845
+#: variables.c:3799
#, c-format
msgid "%s has null exportstr"
msgstr ""
-#: variables.c:3850 variables.c:3859
+#: variables.c:3804 variables.c:3813
#, c-format
msgid "invalid character %d in exportstr for %s"
msgstr ""
-#: variables.c:3865
+#: variables.c:3819
#, c-format
msgid "no `=' in exportstr for %s"
msgstr ""
-#: variables.c:4298
+#: variables.c:4252
msgid "pop_var_context: head of shell_variables not a function context"
msgstr ""
-#: variables.c:4311
+#: variables.c:4265
msgid "pop_var_context: no global_variables context"
msgstr ""
-#: variables.c:4385
+#: variables.c:4339
msgid "pop_scope: head of shell_variables not a temporary environment scope"
msgstr ""
-#: variables.c:5211
+#: variables.c:5165
#, c-format
msgid "%s: %s: cannot open as FILE"
msgstr "%s: %s: Kann nicht als Datei geöffnet werden."
-#: variables.c:5216
+#: variables.c:5170
#, c-format
msgid "%s: %s: invalid value for trace file descriptor"
msgstr ""
-#: variables.c:5261
-#, fuzzy, c-format
+#: variables.c:5215
+#, c-format
msgid "%s: %s: compatibility value out of range"
-msgstr "%s: %s ist außerhalb des Gültigkeitsbereiches."
+msgstr "%s: %s: Kompatibilitätswert außerhalb des Gültigkeitsbereiches."
-#: version.c:46
-#, fuzzy
-msgid "Copyright (C) 2013 Free Software Foundation, Inc."
-msgstr "Copyright (C) 2011 Free Software Foundation, Inc."
+#: version.c:46 version2.c:46
+msgid "Copyright (C) 2012 Free Software Foundation, Inc."
+msgstr "Copyright (C) 2012 Free Software Foundation, Inc."
#: version.c:47 version2.c:47
-msgid ""
-"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl."
-"html>\n"
-msgstr ""
-"Lizenz GPLv3+: GNU GPL Version 3 oder jünger <http://gnu.org/licenses/gpl."
-"html>\n"
+msgid "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n"
+msgstr "Lizenz GPLv3+: GNU GPL Version 3 oder jünger <http://gnu.org/licenses/gpl.html>\n"
#: version.c:86 version2.c:86
#, c-format
msgstr "GNU bash, Version %s (%s)\n"
#: version.c:91 version2.c:91
-#, fuzzy
msgid "This is free software; you are free to change and redistribute it."
-msgstr "Dies ist freie Software. Sie darf verändert und verteilt werden.\n"
+msgstr "Dies ist freie Software. Sie darf verändert und verteilt werden."
#: version.c:92 version2.c:92
-#, fuzzy
msgid "There is NO WARRANTY, to the extent permitted by law."
-msgstr "Für dieses Programm besteht keinerlei Garantie.\n"
-
-#: version2.c:46
-#, fuzzy
-msgid "Copyright (C) 2012 Free Software Foundation, Inc."
-msgstr "Copyright (C) 2011 Free Software Foundation, Inc."
+msgstr "Für den größtmöglichen gesetzlich zulässigen Umfang wird jede Haftung ausgeschlossen."
#: xmalloc.c:91
#, c-format
msgstr "unalias [-a] Name [Name ...]"
#: builtins.c:51
-#, fuzzy
-msgid ""
-"bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-"
-"x keyseq:shell-command] [keyseq:readline-function or readline-command]"
+msgid "bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]"
msgstr ""
-"bind [-lpvsPVS] [-m Tastaturtabelle] [-f Dateiname] [-q Name] [-u Name] [-r "
-"Tastenfolge:Shell Kommando] [Tastenfolge:readline Funktion oder Kommando]"
+"bind [-lpsvPSVX] [-m Tastaturtabelle] [-f Dateiname] [-q Name] [-u\n"
+"Name] [-r Tastenfolge] [-x Tastenfolge:Shell Kommando] [Tastenfolge:readline Funktion oder Kommando]"
#: builtins.c:54
msgid "break [n]"
msgstr "command [-pVv] Kommando [Argument ...]"
#: builtins.c:76
-#, fuzzy
msgid "declare [-aAfFgilnrtux] [-p] [name[=value] ...]"
-msgstr "declare [-aAfFgilrtux] [-p] Name[=Wert] ..."
+msgstr "declare [-aAfFgilrntux] [-p] Name[=Wert] ..."
#
#: builtins.c:78
#: builtins.c:103
msgid "fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command]"
-msgstr ""
-"fc [-e Editor] [-lnr] [Anfang] [Ende] oder fc -s [Muster=Ersetzung] "
-"[Kommando]"
+msgstr "fc [-e Editor] [-lnr] [Anfang] [Ende] oder fc -s [Muster=Ersetzung] [Kommando]"
#: builtins.c:107
msgid "fg [job_spec]"
msgstr "help [-dms] [Muster ...]"
#: builtins.c:121
-msgid ""
-"history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg "
-"[arg...]"
-msgstr ""
-"history [-c] [-d Offset] [n] oder history -anrw [Dateiname] oder history -ps "
-"Argument [Argument...]"
+msgid "history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg [arg...]"
+msgstr "history [-c] [-d Offset] [n] oder history -anrw [Dateiname] oder history -ps Argument [Argument...]"
#: builtins.c:125
msgid "jobs [-lnprs] [jobspec ...] or jobs -x command [args]"
msgstr "disown [-h] [-ar] [Jobbezeichnung ...]"
#: builtins.c:132
-msgid ""
-"kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l "
-"[sigspec]"
-msgstr ""
-"kill [-s Signalname | -n Signalnummer | -Signalname] [pid | job] ... oder "
-"kill -l [Signalname]"
+msgid "kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]"
+msgstr "kill [-s Signalname | -n Signalnummer | -Signalname] [pid | job] ... oder kill -l [Signalname]"
#: builtins.c:134
msgid "let arg [arg ...]"
msgstr "let Argument [Argument ...]"
#: builtins.c:136
-msgid ""
-"read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p "
-"prompt] [-t timeout] [-u fd] [name ...]"
-msgstr ""
-"read [-ers] [-a Feld] [-d Begrenzer] [-i Text] [-n Zeichenanzahl] [-N "
-"Zeichenanzahl] [-p Prompt] [-t Zeitlimit] [-u fd] [Name ...]"
+msgid "read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]"
+msgstr "read [-ers] [-a Feld] [-d Begrenzer] [-i Text] [-n Zeichenanzahl] [-N Zeichenanzahl] [-p Prompt] [-t Zeitlimit] [-u fd] [Name ...]"
#: builtins.c:138
msgid "return [n]"
msgstr "set [-abefhkmnptuvxBCHP] [-o Option] [--] [Argument ...]"
#: builtins.c:142
-#, fuzzy
msgid "unset [-f] [-v] [-n] [name ...]"
-msgstr "unset [-f] [-v] [NAME ...]"
+msgstr "unset [-f] [-v] [-n] [NAME ...]"
#: builtins.c:144
msgid "export [-fn] [name[=value] ...] or export -p"
msgstr "type [-afptP] Name [Name ...]"
#: builtins.c:169
-#, fuzzy
msgid "ulimit [-SHabcdefilmnpqrstuvxT] [limit]"
-msgstr "ulimit [-SHacdefilmnpqrstuvx] [Grenzwert]"
+msgstr "ulimit [-SHabcdefilmnpqrstuvxT] [Grenzwert]"
#: builtins.c:172
msgid "umask [-p] [-S] [mode]"
msgstr "umask [-p] [-S] [Modus]"
#: builtins.c:175
-#, fuzzy
msgid "wait [-n] [id ...]"
-msgstr "wait [id]"
+msgstr "wait [-n] [id ...]"
#: builtins.c:179
-#, fuzzy
msgid "wait [pid ...]"
-msgstr "wait [pid]"
+msgstr "wait [pid ...]"
#: builtins.c:182
msgid "for NAME [in WORDS ... ] ; do COMMANDS; done"
msgstr "case Wort in [Muster [| Muster]...) Kommandos ;;]... esac"
#: builtins.c:192
-msgid ""
-"if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else "
-"COMMANDS; ] fi"
-msgstr ""
-"if Kommandos; then Kommandos; [ elif Kommandos; then Kommandos; ]... [ else "
-"Kommandos; ] fi"
+msgid "if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi"
+msgstr "if Kommandos; then Kommandos; [ elif Kommandos; then Kommandos; ]... [ else Kommandos; ] fi"
#: builtins.c:194
msgid "while COMMANDS; do COMMANDS; done"
msgstr "printf [-v var] Format [Argumente]"
#: builtins.c:229
-msgid ""
-"complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-"
-"W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S "
-"suffix] [name ...]"
-msgstr ""
-"complete [-abcdefgjksuv] [-pr] [-DE] [-o Option] [-A Aktion] [-G Suchmuster] "
-"[-W Wortliste] [-F Funktion] [-C Kommando] [-X Filtermuster] [-P Prefix] [-"
-"S Suffix] [Name ...]"
+msgid "complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]"
+msgstr "complete [-abcdefgjksuv] [-pr] [-DE] [-o Option] [-A Aktion] [-G Suchmuster] [-W Wortliste] [-F Funktion] [-C Kommando] [-X Filtermuster] [-P Prefix] [-S Suffix] [Name ...]"
#: builtins.c:233
-msgid ""
-"compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] "
-"[-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]"
-msgstr ""
-"compgen [-abcdefgjksuv] [-o Option] [-A Aktion] [-G Suchmuster] [-W "
-"Wortliste] [-F Funktion] [-C Kommando] [-X Filtermuster] [-P Prefix] [-S "
-"Suffix] [Wort]"
+msgid "compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]"
+msgstr "compgen [-abcdefgjksuv] [-o Option] [-A Aktion] [-G Suchmuster] [-W Wortliste] [-F Funktion] [-C Kommando] [-X Filtermuster] [-P Prefix] [-S Suffix] [Wort]"
#: builtins.c:237
msgid "compopt [-o|+o option] [-DE] [name ...]"
msgstr "compopt [-o|+o Option] [-DE] [Name ...]"
#: builtins.c:240
-msgid ""
-"mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c "
-"quantum] [array]"
-msgstr ""
-"mapfile [-n Anzahl] [-O Quelle] [-s Anzahl] [-t] [-u fd] [-C Callback] [-c "
-"Menge] [Feldvariable]"
+msgid "mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]"
+msgstr "mapfile [-n Anzahl] [-O Quelle] [-s Anzahl] [-t] [-u fd] [-C Callback] [-c Menge] [Feldvariable]"
#: builtins.c:242
-msgid ""
-"readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c "
-"quantum] [array]"
-msgstr ""
-"readarray [-n Anzahl] [-O Quelle] [-s Anzahl] [-t] [-u fd] [-C Callback] [-c "
-"Menge] [Feldvariable]"
+msgid "readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]"
+msgstr "readarray [-n Anzahl] [-O Quelle] [-s Anzahl] [-t] [-u fd] [-C Callback] [-c Menge] [Feldvariable]"
# alias
#: builtins.c:254
-#, fuzzy
msgid ""
"Define or display aliases.\n"
" \n"
" -p\tPrint all defined aliases in a reusable format\n"
" \n"
" Exit Status:\n"
-" alias returns true unless a NAME is supplied for which no alias has "
-"been\n"
+" alias returns true unless a NAME is supplied for which no alias has been\n"
" defined."
msgstr ""
"Definiert Aliase oder zeigt sie an.\n"
" \n"
-" Ohne Argumente wird die Liste der Aliase (Synonyme) in der Form \n"
-" `alias Name=Wert' auf die Standardausgabe gedruckt.\n"
+" Ohne Argumente wird die Liste der Aliase (Synonyme) in der Form\n"
+" `alias Name=Wert' auf die Standardausgabe ausgegeben.\n"
"\n"
-" Sonst wird ein Alias für jeden angegebenen Namen definiert, für den ein\n"
-" Wert angegeben wurde. \n"
-" A trailing space in VALUE causes the next word to be checked for\n"
-" alias substitution when the alias is expanded.\n"
-" \n"
-" Options:\n"
-" -p\tPrint all defined aliases in a reusable format\n"
+" Sonst wird ein Alias für jeden angegebenen Namen definiert, für\n"
+" den ein Wert angegeben wurde. Wenn `Wert' mit einem Leerzeichen\n"
+" abschließt, dann wird auch das folgende Wort auf Aliase überprüft.\n"
+"\n"
+" Optionen:\n"
+" -p\tGibt alle definierten Aliase aus.\n"
" \n"
" Rückgabewert:\n"
-" Meldet Erfolg, außer wenn NAME nicht existiert."
+" Meldet Erfolg, außer wenn `Name' nicht existiert."
# unalias
#: builtins.c:276
# bind
#: builtins.c:289
-#, fuzzy
msgid ""
"Set Readline key bindings and variables.\n"
" \n"
" Options:\n"
" -m keymap Use KEYMAP as the keymap for the duration of this\n"
" command. Acceptable keymap names are emacs,\n"
-" emacs-standard, emacs-meta, emacs-ctlx, vi, vi-"
-"move,\n"
+" emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,\n"
" vi-command, and vi-insert.\n"
" -l List names of functions.\n"
" -P List function names and bindings.\n"
" -p List functions and bindings in a form that can be\n"
" reused as input.\n"
-" -S List key sequences that invoke macros and their "
-"values\n"
-" -s List key sequences that invoke macros and their "
-"values\n"
+" -S List key sequences that invoke macros and their values\n"
+" -s List key sequences that invoke macros and their values\n"
" in a form that can be reused as input.\n"
" -V List variable names and values\n"
" -v List variable names and values in a form that can\n"
" be reused as input.\n"
" -q function-name Query about which keys invoke the named function.\n"
-" -u function-name Unbind all keys which are bound to the named "
-"function.\n"
+" -u function-name Unbind all keys which are bound to the named function.\n"
" -r keyseq Remove the binding for KEYSEQ.\n"
" -f filename Read key bindings from FILENAME.\n"
" -x keyseq:shell-command\tCause SHELL-COMMAND to be executed when\n"
"Konfiguriert Readline Tastenzuordnungen und Variablen.\n"
" \n"
" Weist eine Tastensequenz einer Readline Funktion oder einem Makro\n"
-" zu oder setzt eine Readline Variable. Der non-option Argument\n"
-" syntax ist zu den Einträgen in ~/.inputrc äquivalent, aber sie\n"
-" müssen als einzelnes Argument übergeben werden. Z.B: bind\n"
-" '\"\\C-x\\C-r\": re-read-init-file'.\n"
+" zu oder setzt eine Readline Variable. Der Argument syntax ist zu\n"
+" den Einträgen in ~/.inputrc äquivalent, aber sie müssen als\n"
+" einzelnes Argument übergeben werden. Z.B: bind '\"\\C-x\\C-r\":\n"
+" re-read-init-file'.\n"
" \n"
" Optionen:\n"
-" -m Keymap Benutzt KEYMAP as Tastaturbelegung für die "
-"Laufzeit\n"
-" dieses Kommandos. Gültige Keymap Namen sind: "
-"emacs,\n"
-" emacs-standard, emacs-meta, emacs-ctlx, vi, vi-"
-"move,\n"
+" -m Keymap Benutzt KEYMAP as Tastaturbelegung für die Laufzeit\n"
+" dieses Kommandos. Gültige Keymap Namen sind: emacs,\n"
+" emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,\n"
" vi-command und vi-insert.\n"
" -l Listet Funktionsnamen auf.\n"
" -P Listet Funktionsnamen und Tastenzuordnungen auf.\n"
-" -p Listet Funktionsnamen und Tastenzuordnungen so "
-"auf,\n"
-" dass sie direkt als Eingabe verwendet werden "
-"können.\n"
-" -S Listet Tastenfolgen und deren Werte auf, die "
-"Makros \n"
+" -p Listet Funktionsnamen und Tastenzuordnungen so auf,\n"
+" dass sie direkt als Eingabe verwendet werden können.\n"
+" -S Listet Tastenfolgen und deren Werte auf, die Makros \n"
" aufrufen.\n"
-" -s Listet Tastenfolgen und deren Werte auf, die "
-"Makros \n"
-" aufrufen, dass sie als Eingabe wiederverwendet "
-"werden\n"
+" -s Listet Tastenfolgen und deren Werte auf, die Makros \n"
+" aufrufen, dass sie als Eingabe wiederverwendet werden\n"
" können.\n"
" -V Listet Variablennamen und Werte auf.\n"
-" -v Listet Variablennamen und Werte so auf, dass sie "
-"als\n"
+" -v Listet Variablennamen und Werte so auf, dass sie als\n"
" Eingabe verwendet werden können.\n"
-" -q Funktionsname Sucht die Tastenfolgen, welche die angegebene "
-"Funktion aufrufen.\n"
-" -u Funktionsname Entfernt alle der Funktion zugeordneten "
-"Tastenfolgen.\n"
-" -r Tastenfolge Entfernt die Zuweisungen der angegebeben "
-"Tastenfolge.\n"
-" -f Dateiname Liest die Tastenzuordnungen aus der angegebenen "
-"Datei.\n"
-" -x Tastenfolge:Shellkommando\tWeist der Tastenfolge das "
-"Shellkommando\n"
+" -q Funktionsname Sucht die Tastenfolgen, welche die angegebene\n"
+" Funktion aufrufen.\n"
+" -u Funktionsname Entfernt alle der Funktion zugeordneten Tastenfolgen.\n"
+" -r Tastenfolge Entfernt die Zuweisungen der angegebeben Tastenfolge.\n"
+" -f Dateiname Liest die Tastenzuordnungen aus der angegebenen Datei.\n"
+" -x Tastenfolge:Shellkommando\tWeist der Tastenfolge das Shellkommando\n"
" \t\t\t\t\tzu.\n"
+" -X Listet mit -x erzeugte\n"
+" Tastenfolgen und deren Werte\n"
+" auf, die Makros aufrufen, dass\n"
+" sie als Eingabe wiederverwendet werden\n"
+" können.\n"
" \n"
" Rückgabewert: \n"
" Bind gibt 0 zurück, wenn keine unerkannte Option angegeben wurde\n"
" \n"
" Execute SHELL-BUILTIN with arguments ARGs without performing command\n"
" lookup. This is useful when you wish to reimplement a shell builtin\n"
-" as a shell function, but need to execute the builtin within the "
-"function.\n"
+" as a shell function, but need to execute the builtin within the function.\n"
" \n"
" Exit Status:\n"
" Returns the exit status of SHELL-BUILTIN, or false if SHELL-BUILTIN is\n"
# cd
#: builtins.c:385
-#, fuzzy
msgid ""
"Change the shell working directory.\n"
" \n"
-" Change the current directory to DIR. The default DIR is the value of "
-"the\n"
+" Change the current directory to DIR. The default DIR is the value of the\n"
" HOME shell variable.\n"
" \n"
-" The variable CDPATH defines the search path for the directory "
-"containing\n"
-" DIR. Alternative directory names in CDPATH are separated by a colon "
-"(:).\n"
-" A null directory name is the same as the current directory. If DIR "
-"begins\n"
+" The variable CDPATH defines the search path for the directory containing\n"
+" DIR. Alternative directory names in CDPATH are separated by a colon (:).\n"
+" A null directory name is the same as the current directory. If DIR begins\n"
" with a slash (/), then CDPATH is not used.\n"
" \n"
-" If the directory is not found, and the shell option `cdable_vars' is "
-"set,\n"
-" the word is assumed to be a variable name. If that variable has a "
-"value,\n"
+" If the directory is not found, and the shell option `cdable_vars' is set,\n"
+" the word is assumed to be a variable name. If that variable has a value,\n"
" its value is used for DIR.\n"
" \n"
" Options:\n"
" \tcannot be determined successfully, exit with a non-zero status\n"
" \n"
" The default is to follow symbolic links, as if `-L' were specified.\n"
-" `..' is processed by removing the immediately previous pathname "
-"component\n"
+" `..' is processed by removing the immediately previous pathname component\n"
" back to a slash or the beginning of DIR.\n"
" \n"
" Exit Status:\n"
-" Returns 0 if the directory is changed, and if $PWD is set successfully "
-"when\n"
+" Returns 0 if the directory is changed, and if $PWD is set successfully when\n"
" -P is used; non-zero otherwise."
msgstr ""
"Wechselt das Arbeitsverzeichnis.\n"
" Wert besitzt, wird dieser als Inhalt von DIR verwendet.\n"
" \n"
" Optionen:\n"
-" -L\tErzwingt das Folgen symbolischer Verweise.\n"
-" -P\tSymbolische Verweise werden ignoriert.\n"
-" -e\tZusammen mit der »-P« Option wird der Rückgabewert ungleich 0, \n"
-"\t\twenn das aktuelle Arbeitsverzeichns nach einem\n"
-"\t\terfolgreichn Verzeichniswechsel nicht ermittelt werden\n"
-"\t\tkonnte.\n"
-" \n"
-" Standardmäßig wird symbolischen Verweisen gefolgt.\n"
+" -L\tErzwingt das symbolischen Verweisen gefolgt wird.\n"
+" Symbolische Links im aktuellen Verzeichnis werden nach\n"
+" dem übergeordneten Verzeichnis aufgelöst.\n"
+" -P\tSymbolische Verweise werden ignoriert. Symbolische\n"
+" Links im aktuellen Verzeichnis werden vor dem\n"
+" übergeordneten Verzeichnis aufgelöst.\n"
+" -e\tWenn mit der »-P« das aktuelle Arbeitsverzeichns nicht\n"
+" ermittelt werden kann, wird ein Rückgabwert ungleich 0\n"
+" geliefert.\n"
+" \n"
+" Standardmäßig wird symbolischen Verweisen gefolgt (Option -L).\n"
+" Das übergeordnete Verzeichnis wird ermittelt, indem der\n"
+" Dateiname am letzten Schrägstrich gekürzt wird oder es wird der\n"
+" Anfang von DIR verwendet.\n"
" \n"
" Rückgabewert: \n"
" Der Rückgabewert ist 0, wenn das Verzeichnis gewechselt wurde,\n"
"Execute a simple command or display information about commands.\n"
" \n"
" Runs COMMAND with ARGS suppressing shell function lookup, or display\n"
-" information about the specified COMMANDs. Can be used to invoke "
-"commands\n"
+" information about the specified COMMANDs. Can be used to invoke commands\n"
" on disk when a function with the same name exists.\n"
" \n"
" Options:\n"
" Variables with the integer attribute have arithmetic evaluation (see\n"
" the `let' command) performed when the variable is assigned a value.\n"
" \n"
-" When used in a function, `declare' makes NAMEs local, as with the "
-"`local'\n"
+" When used in a function, `declare' makes NAMEs local, as with the `local'\n"
" command. The `-g' option suppresses this behavior.\n"
" \n"
" Exit Status:\n"
" Veraltet. Siehe `help declare'."
#: builtins.c:533
-#, fuzzy
msgid ""
"Define local variables.\n"
" \n"
msgstr ""
"Definiert lokale Variablen.\n"
" \n"
-" Erzeugt eine Lokale Variable NAME und weist ihr den Wert VALUE zu. "
-"OPTION\n"
-" kann eine beliebige von `declare' akzeptierte Option sein.\n"
+" Erzeugt eine Lokale Variable NAME und weist ihr den Wert VALUE zu.\n"
+" OPTION kann eine beliebige von `declare' akzeptierte Option sein.\n"
"\n"
-" Lokale Variablen können nur innerhalb einer Funktion benutzt werden. "
-"Sie\n"
-" sind nur in der sie erzeugenden Funktion und ihren Kindern "
-"sichtbar. \n"
+" Lokale Variablen können nur innerhalb einer Funktion benutzt\n"
+" werden. Sie sind nur in der sie erzeugenden Funktion und ihren\n"
+" Kindern sichtbar.\n"
" \n"
-" Rückgabewert:\n"
-" Liefert \"Erfolg\" außer bei einer ungültigen Option, einem Fehler oder\n"
-" die Shell führt keine Funktion aus."
+" Rückgabewert: \n"
+" Liefert 0 außer bei Angabe einer ungültigen Option, einer\n"
+" fehlerhaften Variablenzuweisung oder dem Aufruf außerhalb einer\n"
+" Funktion."
#: builtins.c:550
msgid ""
"Write arguments to the standard output.\n"
" \n"
-" Display the ARGs, separated by a single space character and followed by "
-"a\n"
+" Display the ARGs, separated by a single space character and followed by a\n"
" newline, on the standard output.\n"
" \n"
" Options:\n"
msgid ""
"Execute arguments as a shell command.\n"
" \n"
-" Combine ARGs into a single string, use the result as input to the "
-"shell,\n"
+" Combine ARGs into a single string, use the result as input to the shell,\n"
" and execute the resulting commands.\n"
" \n"
" Exit Status:\n"
"Replace the shell with the given command.\n"
" \n"
" Execute COMMAND, replacing this shell with the specified program.\n"
-" ARGUMENTS become the arguments to COMMAND. If COMMAND is not "
-"specified,\n"
+" ARGUMENTS become the arguments to COMMAND. If COMMAND is not specified,\n"
" any redirections take effect in the current shell.\n"
" \n"
" Options:\n"
" -c\t\texecute COMMAND with an empty environment\n"
" -l\t\tplace a dash in the zeroth argument to COMMAND\n"
" \n"
-" If the command cannot be executed, a non-interactive shell exits, "
-"unless\n"
+" If the command cannot be executed, a non-interactive shell exits, unless\n"
" the shell option `execfail' is set.\n"
" \n"
" Exit Status:\n"
-" Returns success unless COMMAND is not found or a redirection error "
-"occurs."
+" Returns success unless COMMAND is not found or a redirection error occurs."
msgstr ""
# exit
msgstr ""
"Beendet die aktuelle Shell.\n"
"\n"
-" Beendt die die aktuelle Shell mit dem Rückgabewert N. Wenn N nicht "
-"angegeben ist,\n"
+" Beendt die die aktuelle Shell mit dem Rückgabewert N. Wenn N nicht angegeben ist,\n"
" wird der Rückgabewert des letzten ausgeführten Kommandos übernommen."
#: builtins.c:713
msgid ""
"Exit a login shell.\n"
" \n"
-" Exits a login shell with exit status N. Returns an error if not "
-"executed\n"
+" Exits a login shell with exit status N. Returns an error if not executed\n"
" in a login shell."
msgstr ""
msgid ""
"Display or execute commands from the history list.\n"
" \n"
-" fc is used to list or edit and re-execute commands from the history "
-"list.\n"
+" fc is used to list or edit and re-execute commands from the history list.\n"
" FIRST and LAST can be numbers specifying the range, or FIRST can be a\n"
" string, which means the most recent command beginning with that\n"
" string.\n"
" \n"
" Options:\n"
-" -e ENAME\tselect which editor to use. Default is FCEDIT, then "
-"EDITOR,\n"
+" -e ENAME\tselect which editor to use. Default is FCEDIT, then EDITOR,\n"
" \t\tthen vi\n"
" -l \tlist lines instead of editing\n"
" -n\tomit line numbers when listing\n"
" the last command.\n"
" \n"
" Exit Status:\n"
-" Returns success or status of executed command; non-zero if an error "
-"occurs."
+" Returns success or status of executed command; non-zero if an error occurs."
msgstr ""
#: builtins.c:753
msgid ""
"Move jobs to the background.\n"
" \n"
-" Place the jobs identified by each JOB_SPEC in the background, as if "
-"they\n"
-" had been started with `&'. If JOB_SPEC is not present, the shell's "
-"notion\n"
+" Place the jobs identified by each JOB_SPEC in the background, as if they\n"
+" had been started with `&'. If JOB_SPEC is not present, the shell's notion\n"
" of the current job is used.\n"
" \n"
" Exit Status:\n"
"Remember or display program locations.\n"
" \n"
" Determine and remember the full pathname of each command NAME. If\n"
-" no arguments are given, information about remembered commands is "
-"displayed.\n"
+" no arguments are given, information about remembered commands is displayed.\n"
" \n"
" Options:\n"
" -d\t\tforget the remembered location of each NAME\n"
" -l\t\tdisplay in a format that may be reused as input\n"
-" -p pathname\tuse PATHNAME as the full pathname of NAME\n"
+" -p pathname\tuse PATHNAME is the full pathname of NAME\n"
" -r\t\tforget all remembered locations\n"
" -t\t\tprint the remembered location of each NAME, preceding\n"
" \t\teach location with the corresponding NAME if multiple\n"
" PATTERN\tPattern specifiying a help topic\n"
" \n"
" Exit Status:\n"
-" Returns success unless PATTERN is not found or an invalid option is "
-"given."
+" Returns success unless PATTERN is not found or an invalid option is given."
msgstr ""
#: builtins.c:831
" \n"
" If the $HISTTIMEFORMAT variable is set and not null, its value is used\n"
" as a format string for strftime(3) to print the time stamp associated\n"
-" with each displayed history entry. No time stamps are printed "
-"otherwise.\n"
+" with each displayed history entry. No time stamps are printed otherwise.\n"
" \n"
" Exit Status:\n"
" Returns success unless an invalid option is given or an error occurs."
" Evaluate each ARG as an arithmetic expression. Evaluation is done in\n"
" fixed-width integers with no check for overflow, though division by 0\n"
" is trapped and flagged as an error. The following list of operators is\n"
-" grouped into levels of equal-precedence operators. The levels are "
-"listed\n"
+" grouped into levels of equal-precedence operators. The levels are listed\n"
" in order of decreasing precedence.\n"
" \n"
" \tid++, id--\tvariable post-increment, post-decrement\n"
"Read a line from the standard input and split it into fields.\n"
" \n"
" Reads a single line from the standard input, or from file descriptor FD\n"
-" if the -u option is supplied. The line is split into fields as with "
-"word\n"
+" if the -u option is supplied. The line is split into fields as with word\n"
" splitting, and the first word is assigned to the first NAME, the second\n"
" word to the second NAME, and so on, with any leftover words assigned to\n"
-" the last NAME. Only the characters found in $IFS are recognized as "
-"word\n"
+" the last NAME. Only the characters found in $IFS are recognized as word\n"
" delimiters.\n"
" \n"
-" If no NAMEs are supplied, the line read is stored in the REPLY "
-"variable.\n"
+" If no NAMEs are supplied, the line read is stored in the REPLY variable.\n"
" \n"
" Options:\n"
" -a array\tassign the words read to sequential indices of the array\n"
" -n nchars\treturn after reading NCHARS characters rather than waiting\n"
" \t\tfor a newline, but honor a delimiter if fewer than NCHARS\n"
" \t\tcharacters are read before the delimiter\n"
-" -N nchars\treturn only after reading exactly NCHARS characters, "
-"unless\n"
+" -N nchars\treturn only after reading exactly NCHARS characters, unless\n"
" \t\tEOF is encountered or read times out, ignoring any delimiter\n"
" -p prompt\toutput the string PROMPT without a trailing newline before\n"
" \t\tattempting to read\n"
" -r\t\tdo not allow backslashes to escape any characters\n"
" -s\t\tdo not echo input coming from a terminal\n"
-" -t timeout\ttime out and return failure if a complete line of input "
-"is\n"
+" -t timeout\ttime out and return failure if a complete line of input is\n"
" \t\tnot read within TIMEOUT seconds. The value of the TMOUT\n"
" \t\tvariable is the default timeout. TIMEOUT may be a\n"
" \t\tfractional number. If TIMEOUT is 0, read returns immediately,\n"
" -u fd\t\tread from file descriptor FD instead of the standard input\n"
" \n"
" Exit Status:\n"
-" The return code is zero, unless end-of-file is encountered, read times "
-"out\n"
-" (in which case it's greater than 128), a variable assignment error "
-"occurs,\n"
+" The return code is zero, unless end-of-file is encountered, read times out\n"
+" (in which case it's greater than 128), a variable assignment error occurs,\n"
" or an invalid file descriptor is supplied as the argument to -u."
msgstr ""
" physical same as -P\n"
" pipefail the return value of a pipeline is the status of\n"
" the last command to exit with a non-zero status,\n"
-" or zero if no command exited with a non-zero "
-"status\n"
+" or zero if no command exited with a non-zero status\n"
" posix change the behavior of bash where the default\n"
" operation differs from the Posix standard to\n"
" match the standard\n"
" -n\ttreat each NAME as a name reference and unset the variable itself\n"
" \trather than the variable it references\n"
" \n"
-" Without options, unset first tries to unset a variable, and if that "
-"fails,\n"
+" Without options, unset first tries to unset a variable, and if that fails,\n"
" tries to unset a function.\n"
" \n"
" Some variables cannot be unset; also see `readonly'.\n"
"Set export attribute for shell variables.\n"
" \n"
" Marks each NAME for automatic export to the environment of subsequently\n"
-" executed commands. If VALUE is supplied, assign VALUE before "
-"exporting.\n"
+" executed commands. If VALUE is supplied, assign VALUE before exporting.\n"
" \n"
" Options:\n"
" -f\trefer to shell functions\n"
" -a\trefer to indexed array variables\n"
" -A\trefer to associative array variables\n"
" -f\trefer to shell functions\n"
-" -p\tdisplay a list of all readonly variables or functions, depending "
-"on\n"
-" whether or not the -f option is given\n"
+" -p\tdisplay a list of all readonly variables and functions\n"
" \n"
" An argument of `--' disables further option processing.\n"
" \n"
" Returns success unless an invalid option is given or NAME is invalid."
msgstr ""
-#: builtins.c:1187
+#: builtins.c:1186
msgid ""
"Shift positional parameters.\n"
" \n"
" Returns success unless N is negative or greater than $#."
msgstr ""
-#: builtins.c:1199 builtins.c:1214
+#: builtins.c:1198 builtins.c:1213
msgid ""
"Execute commands from a file in the current shell.\n"
" \n"
" FILENAME cannot be read."
msgstr ""
-#: builtins.c:1230
+#: builtins.c:1229
msgid ""
"Suspend shell execution.\n"
" \n"
" Returns success unless job control is not enabled or an error occurs."
msgstr ""
-#: builtins.c:1246
+#: builtins.c:1245
msgid ""
"Evaluate conditional expression.\n"
" \n"
" -x FILE True if the file is executable by you.\n"
" -O FILE True if the file is effectively owned by you.\n"
" -G FILE True if the file is effectively owned by your group.\n"
-" -N FILE True if the file has been modified since it was last "
-"read.\n"
+" -N FILE True if the file has been modified since it was last read.\n"
" \n"
" FILE1 -nt FILE2 True if file1 is newer than file2 (according to\n"
" modification date).\n"
" STRING1 != STRING2\n"
" True if the strings are not equal.\n"
" STRING1 < STRING2\n"
-" True if STRING1 sorts before STRING2 "
-"lexicographically.\n"
+" True if STRING1 sorts before STRING2 lexicographically.\n"
" STRING1 > STRING2\n"
" True if STRING1 sorts after STRING2 lexicographically.\n"
" \n"
" \n"
" -o OPTION True if the shell option OPTION is enabled.\n"
" -v VAR\t True if the shell variable VAR is set\n"
-" -R VAR\t True if the shell variable VAR is set and is a name "
-"reference.\n"
+" -R VAR\t True if the shell variable VAR is set and is a name reference.\n"
" ! EXPR True if expr is false.\n"
" EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.\n"
" EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.\n"
msgstr ""
# [
-#: builtins.c:1327
+#: builtins.c:1326
msgid ""
"Evaluate conditional expression.\n"
" \n"
" schließt."
# times
-#: builtins.c:1336
+#: builtins.c:1335
msgid ""
"Display process times.\n"
" \n"
-" Prints the accumulated user and system times for the shell and all of "
-"its\n"
+" Prints the accumulated user and system times for the shell and all of its\n"
" child processes.\n"
" \n"
" Exit Status:\n"
" Rückgabewert:\n"
" Immer 0."
-#: builtins.c:1348
+#: builtins.c:1347
msgid ""
"Trap signals and other events.\n"
" \n"
-" Defines and activates handlers to be run when the shell receives "
-"signals\n"
+" Defines and activates handlers to be run when the shell receives signals\n"
" or other conditions.\n"
" \n"
" ARG is a command to be read and executed when the shell receives the\n"
" value. If ARG is the null string each SIGNAL_SPEC is ignored by the\n"
" shell and by the commands it invokes.\n"
" \n"
-" If a SIGNAL_SPEC is EXIT (0) ARG is executed on exit from the shell. "
-"If\n"
-" a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command. "
-"If\n"
-" a SIGNAL_SPEC is RETURN, ARG is executed each time a shell function or "
-"a\n"
-" script run by the . or source builtins finishes executing. A "
-"SIGNAL_SPEC\n"
-" of ERR means to execute ARG each time a command's failure would cause "
-"the\n"
+" If a SIGNAL_SPEC is EXIT (0) ARG is executed on exit from the shell. If\n"
+" a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command. If\n"
+" a SIGNAL_SPEC is RETURN, ARG is executed each time a shell function or a\n"
+" script run by the . or source builtins finishes executing. A SIGNAL_SPEC\n"
+" of ERR means to execute ARG each time a command's failure would cause the\n"
" shell to exit when the -e option is enabled.\n"
" \n"
-" If no arguments are supplied, trap prints the list of commands "
-"associated\n"
+" If no arguments are supplied, trap prints the list of commands associated\n"
" with each signal.\n"
" \n"
" Options:\n"
" -l\tprint a list of signal names and their corresponding numbers\n"
" -p\tdisplay the trap commands associated with each SIGNAL_SPEC\n"
" \n"
-" Each SIGNAL_SPEC is either a signal name in <signal.h> or a signal "
-"number.\n"
+" Each SIGNAL_SPEC is either a signal name in <signal.h> or a signal number.\n"
" Signal names are case insensitive and the SIG prefix is optional. A\n"
" signal may be sent to the shell with \"kill -signal $$\".\n"
" \n"
" Exit Status:\n"
-" Returns success unless a SIGSPEC is invalid or an invalid option is "
-"given."
+" Returns success unless a SIGSPEC is invalid or an invalid option is given."
msgstr ""
-#: builtins.c:1384
+#: builtins.c:1383
msgid ""
"Display information about command type.\n"
" \n"
" NAME\tCommand name to be interpreted.\n"
" \n"
" Exit Status:\n"
-" Returns success if all of the NAMEs are found; fails if any are not "
-"found."
+" Returns success if all of the NAMEs are found; fails if any are not found."
msgstr ""
-#: builtins.c:1415
+#: builtins.c:1414
msgid ""
"Modify shell resource limits.\n"
" \n"
-" Provides control over the resources available to the shell and "
-"processes\n"
+" Provides control over the resources available to the shell and processes\n"
" it creates, on systems that allow such control.\n"
" \n"
" Options:\n"
" Returns success unless an invalid option is supplied or an error occurs."
msgstr ""
-#: builtins.c:1463
+#: builtins.c:1462
msgid ""
"Display or set file mode mask.\n"
" \n"
" Returns success unless MODE is invalid or an invalid option is given."
msgstr ""
-#: builtins.c:1483
+#: builtins.c:1482
msgid ""
"Wait for job completion and return exit status.\n"
" \n"
-" Waits for each process identified by an ID, which may be a process ID or "
-"a\n"
+" Waits for each process identified by an ID, which may be a process ID or a\n"
" job specification, and reports its termination status. If ID is not\n"
" given, waits for all currently active child processes, and the return\n"
-" status is zero. If ID is a a job specification, waits for all "
-"processes\n"
+" status is zero. If ID is a a job specification, waits for all processes\n"
" in that job's pipeline.\n"
" \n"
" If the -n option is supplied, waits for the next job to terminate and\n"
" option is given."
msgstr ""
-#: builtins.c:1504
+#: builtins.c:1503
msgid ""
"Wait for process completion and return exit status.\n"
" \n"
-" Waits for each process specified by a PID and reports its termination "
-"status.\n"
+" Waits for each process specified by a PID and reports its termination status.\n"
" If PID is not given, waits for all currently active child processes,\n"
" and the return status is zero. PID must be a process ID.\n"
" \n"
" Exit Status:\n"
-" Returns the status of the last PID; fails if PID is invalid or an "
-"invalid\n"
+" Returns the status of the last PID; fails if PID is invalid or an invalid\n"
" option is given."
msgstr ""
-#: builtins.c:1519
+#: builtins.c:1518
msgid ""
"Execute commands for each member in a list.\n"
" \n"
" Returns the status of the last command executed."
msgstr ""
-#: builtins.c:1533
+#: builtins.c:1532
msgid ""
"Arithmetic for loop.\n"
" \n"
" Returns the status of the last command executed."
msgstr ""
-#: builtins.c:1551
+#: builtins.c:1550
msgid ""
"Select words from a list and execute commands.\n"
" \n"
" Returns the status of the last command executed."
msgstr ""
-#: builtins.c:1572
+#: builtins.c:1571
msgid ""
"Report time consumed by pipeline's execution.\n"
" \n"
" The return status is the return status of PIPELINE."
msgstr ""
-#: builtins.c:1589
+#: builtins.c:1588
msgid ""
"Execute commands based on pattern matching.\n"
" \n"
" Returns the status of the last command executed."
msgstr ""
-#: builtins.c:1601
+#: builtins.c:1600
msgid ""
"Execute commands based on conditional.\n"
" \n"
-" The `if COMMANDS' list is executed. If its exit status is zero, then "
-"the\n"
-" `then COMMANDS' list is executed. Otherwise, each `elif COMMANDS' list "
-"is\n"
+" The `if COMMANDS' list is executed. If its exit status is zero, then the\n"
+" `then COMMANDS' list is executed. Otherwise, each `elif COMMANDS' list is\n"
" executed in turn, and if its exit status is zero, the corresponding\n"
-" `then COMMANDS' list is executed and the if command completes. "
-"Otherwise,\n"
-" the `else COMMANDS' list is executed, if present. The exit status of "
-"the\n"
-" entire construct is the exit status of the last command executed, or "
-"zero\n"
+" `then COMMANDS' list is executed and the if command completes. Otherwise,\n"
+" the `else COMMANDS' list is executed, if present. The exit status of the\n"
+" entire construct is the exit status of the last command executed, or zero\n"
" if no condition tested true.\n"
" \n"
" Exit Status:\n"
" Returns the status of the last command executed."
msgstr ""
-#: builtins.c:1618
+#: builtins.c:1617
msgid ""
"Execute commands as long as a test succeeds.\n"
" \n"
" Returns the status of the last command executed."
msgstr ""
-#: builtins.c:1630
+#: builtins.c:1629
msgid ""
"Execute commands as long as a test does not succeed.\n"
" \n"
" Returns the status of the last command executed."
msgstr ""
-#: builtins.c:1642
+#: builtins.c:1641
msgid ""
"Create a coprocess named NAME.\n"
" \n"
" Returns the exit status of COMMAND."
msgstr ""
-#: builtins.c:1656
+#: builtins.c:1655
msgid ""
"Define shell function.\n"
" \n"
" Create a shell function named NAME. When invoked as a simple command,\n"
-" NAME runs COMMANDs in the calling shell's context. When NAME is "
-"invoked,\n"
+" NAME runs COMMANDs in the calling shell's context. When NAME is invoked,\n"
" the arguments are passed to the function as $1...$n, and the function's\n"
" name is in $FUNCNAME.\n"
" \n"
" Returns success unless NAME is readonly."
msgstr ""
-#: builtins.c:1670
+#: builtins.c:1669
msgid ""
"Group commands as a unit.\n"
" \n"
" Returns the status of the last command executed."
msgstr ""
-#: builtins.c:1682
+#: builtins.c:1681
msgid ""
"Resume job in foreground.\n"
" \n"
" Returns the status of the resumed job."
msgstr ""
-#: builtins.c:1697
+#: builtins.c:1696
msgid ""
"Evaluate arithmetic expression.\n"
" \n"
" Returns 1 if EXPRESSION evaluates to 0; returns 0 otherwise."
msgstr ""
-#: builtins.c:1709
+#: builtins.c:1708
msgid ""
"Execute conditional command.\n"
" \n"
-" Returns a status of 0 or 1 depending on the evaluation of the "
-"conditional\n"
-" expression EXPRESSION. Expressions are composed of the same primaries "
-"used\n"
-" by the `test' builtin, and may be combined using the following "
-"operators:\n"
+" Returns a status of 0 or 1 depending on the evaluation of the conditional\n"
+" expression EXPRESSION. Expressions are composed of the same primaries used\n"
+" by the `test' builtin, and may be combined using the following operators:\n"
" \n"
" ( EXPRESSION )\tReturns the value of EXPRESSION\n"
" ! EXPRESSION\t\tTrue if EXPRESSION is false; else false\n"
msgstr ""
# variable_help
-#: builtins.c:1735
-#, fuzzy
+#: builtins.c:1734
msgid ""
"Common shell variable names and usage.\n"
" \n"
" \t\tcommands should be saved on the history list.\n"
msgstr ""
" BASH_VERSION\tVersionsnummer der Bash.\n"
-" CDPATH\tEine durch Doppelpunkt getrennte Liste von\n"
-" Verzeichnissen, die\t\tdurchsucht werden, wenn das Argument\n"
-" von `cd' nicht im\t\taktuellen Verzeichnis gefunden wird.\n"
+" CDPATH\tEine durch Doppelpunkte getrennte Liste von\n"
+" Verzeichnissen, die durchsucht werden, wenn das\n"
+" Argument von `cd' nicht im aktuellen Verzeichnis\n"
+" gefunden wird.\n"
+" GLOBIGNORE Eine durch Doppelpunkte getrennte Liste von\n"
+" Dateinamenmustern, die für die Dateinamensergänzung\n"
+" ignoriert werden.\n"
" HISTFILE\tDatei, die den Kommandozeilenspeicher enthält.\n"
-" HISTFILESIZE\tMaximale Zeilenanzahl, die diese Datei\n"
-" enthalten darf.\n"
+" HISTFILESIZE\tMaximale Zeilenanzahl, dieser Datei.\n"
" HISTSIZE\tMaximale Anzahl von Zeilen, auf die der\n"
-" Historymechanismus\t\tder Shell zurückgreifen kann.\n"
+" Historymechanismus der Shell zurückgreifen kann.\n"
" HOME\tHeimatverzeichnis des aktuellen Benutzers.\n"
-" HOSTTYPE\tCPU-Typ des Rechners, auf dem die Bash gegenwärtig\n"
-" läuft.\n"
+" HOSTNAME Der aktuelle Rechnername.\n"
+" HOSTTYPE\tCPU-Typ des aktuellen Rechners.\n"
" IGNOREEOF\tLegt die Reaktion der Shell auf ein EOF-Zeichen fest.\n"
-" Wenn die Variable eine ganze Zahl enthält, wird diese Anzahl\n"
-" EOF Zeichen (Ctrl-D) abgewartet, bis die Shell verlassen wird.\n"
-" Der Vorgabewert ist 10. Ist IGNOREEOF nicht gesetzt,\n"
-" signalisiert EOF das Ende der Eingabe.\n"
-" MAILCHECK\tZeitintervall [s], in dem nach angekommener Post\n"
-" gesucht wird.\n"
-" MAILPATH\tEine durch Doppelpunkt getrennte Liste von Dateien,\n"
-" die nach\t\tneu angekommener Post durchsucht werden.\n"
-" OSTYPE\tBetriebssystemversion, auf der die Bash gegenwärtig\n"
-" läuft.\n"
+" Wenn die Variable eine ganze Zahl enthält, wird diese\n"
+" Anzahl EOF Zeichen (Ctrl-D) abgewartet, bis die Shell\n"
+" verlassen wird. Der Vorgabewert ist 10. Ist IGNOREEOF\n"
+" nicht gesetzt, signalisiert EOF das Ende der Eingabe.\n"
+" MACHTYPE Eine Zeichenkette die das aktuell laufende System beschreibt.\n"
+" MAILCHECK\tZeit in s, nach der nach E-Mail gesehen wird.\n"
+" MAILPATH\tEine durch Doppelpunkt getrennte Liste von Dateinamen,\n"
+" die nach E-Mail durchsucht werden.\n"
+" OSTYPE\tUnix Version, auf der die Bash gegenwärtig läuft.\n"
" PATH\tDurch Doppelpunkt getrennte Liste von Verzeichnissen,\n"
-" die nach Kommandos durchsucht werden.\n"
+" die nach Kommandos durchsucht werden.\n"
" PROMPT_COMMAND\tKommando, das vor der Anzeige einer primären\n"
-" Eingabeaufforderung (PS1) ausgeführt wird.\n"
-" PS1\tZeichenkette, die die primäre Eingabeaufforderung enthält.\n"
-" PS2\tZeichenkette, die die sekundäre Eingabeaufforderung enthält.\n"
+" Eingabeaufforderung (PS1) ausgeführt wird.\n"
+" PS1 Zeichenkette, die die primäre\n"
+" Eingabeaufforderung enthält.\n"
+" PS2 Zeichenkette, die die sekundäre\n"
+" Eingabeaufforderung enthält.\n"
+" PWD Der vollständige aktuelle Verzeichnisname.\n"
+" SHELLOPTS Durch Doppelpunkt getrennte Liste der aktiven\n"
+" Shell Optionen.\n"
" TERM\tName des aktuellen Terminaltyps.\n"
-" auto_resume\tEin Wert ungleich Null bewirkt, daß ein einzelnes\n"
-" Kommando auf einer Zeile zunächst in der Liste\n"
-" gegenwärtig gestoppter Jobs\tgesucht und dieser in den\n"
-" Vordergrund geholt wird. `exact' bewirkt, daß das\n"
-" Kommando genau dem Kommando in der Liste der gestoppten\n"
-" Jobs entsprechen muß. Wenn die Variable den Wert\n"
-" `substring' enthält, muß das Kommando einem Substring\n"
-" der Jobbezeichnung entsprechen. Bei einem anderen Wert müssen\n"
-" die ersten Zeichen übereinstimmen.\n"
-" command_oriented_history\tMehrzeilige Kommandos werden im\n"
-" Kommandozeilenspeicher in einer\tZeile abgelegt, wenn die\n"
-" Variable ungleich Null gesetzt ist.\n"
-" histchars Zeichen, die die Befehlswiederholung und die\n"
-" Schnellersetzung steuern. An erster Stelle steht das\n"
-" Befehlswiederholungszeichen (normalerweise `!'); an zweiter das\n"
-" `Schnell-Ersetzen-Zeichen' (normalerweise `^'). Das dritte Zeichen\n"
-" ist das\t`Kommentarzeichen' (normalerweise `#').\n"
-" HISTCONTROL Gesetzt auf `ignorespace' werden keine mit einem\n"
-" \tLeerzeichen oder Tabulator beginnenden Zeilen im\n"
-" \tKommandospeicher abgelegt. Der Wert `ignoredups' verhindert\n"
-" \tdas Speichern aufeinanderfolgender identischer\n"
-" \tZeilen. `ignoreboth' kombiniert beide Einstellungen. Wenn die\n"
-" \tVariable nicht oder auf einen anderen Wert gesetzt ist, werden\n"
-" \talle eingegebenen Zeilen im Kommandospeicher abgelegt."
+" auto_resume Ein Wert ungleich Null bewirkt, daß ein einzelnes\n"
+" Kommando auf einer Zeile zunächst in der Liste\n"
+" gegenwärtig gestoppter Jobs gesucht und dieser in den\n"
+" Vordergrund geholt wird. `exact' bewirkt, daß das\n"
+" Kommando genau dem Kommando in der Liste der\n"
+" gestoppten Jobs entsprechen muß. Wenn die Variable den\n"
+" Wert `substring' enthält, muß das Kommando einem\n"
+" Substring der Jobbezeichnung entsprechen. Bei einem\n"
+" anderen Wert müssen die ersten Zeichen übereinstimmen.\n"
+" histchars Zeichen, die die Befehlswiederholung und die\n"
+" Schnellersetzung steuern. An erster Stelle steht\n"
+" das Befehlswiederholungszeichen (normalerweise\n"
+" `!'); an zweiter das `Schnell-Ersetzen-Zeichen'\n"
+" (normalerweise `^'). Das dritte Zeichen ist das\n"
+" `Kommentarzeichen' (normalerweise `#').\n"
+" HISTIGNORE Eine durch Doppelpunkt getrennte Liste von\n"
+" Mustern, welche die in der\n"
+" Befehlswiederholungsliste zu speichernden\n"
+" Kommandos angibt.\n"
# pushd
-#: builtins.c:1792
-#, fuzzy
+#: builtins.c:1791
msgid ""
"Add directories to stack.\n"
" \n"
"\n"
" Legt ein Verzeichnisnamen auf den Verzeichnisstapel oder rotiert\n"
" diesen so,daß das Arbeitsverzeichnis auf der Spitze des Stapels\n"
-" liegt. OhneArgumente werden die obersten zwei Verzeichnisse auf\n"
-" dem Stapel vertauscht.\n"
+" liegt. Ohne angegebene Argumente werden die obersten zwei\n"
+" Verzeichnisse auf dem Stapel getauscht.\n"
"\n"
" Optionen:\n"
" -n\tunterdrückt das Wechseln in das Verzeichnis beim Hinzufügen\n"
" -befindet.\n"
" \n"
"\n"
-" DIR\tLegt DIR auf die Spitze des Verzeichnisstapels und wechselt "
-"dorthin.\n"
+" DIR\tLegt DIR auf die Spitze des Verzeichnisstapels und wechselt dorthin.\n"
+"\n"
+" Der Verzeichnisstapel kann mit dem Kommando `dirs' angezeigt\n"
+" werden.\n"
"\n"
-" Der Verzeichnisstapel kann mit dem Kommando `dirs' angezeigt werden."
+" Rückgabewert: \n"
+" Gibt Erfolg zurück, außer wenn ein ungültiges Argument angegeben\n"
+" wurde oder der Verzeichniswechsel nicht erfolgreich war."
# popd
-#: builtins.c:1826
+#: builtins.c:1825
msgid ""
"Remove directories from stack.\n"
" \n"
" wurde oder der Verzeichniswechsel nicht erfolgreich war."
# dirs
-#: builtins.c:1856
+#: builtins.c:1855
msgid ""
"Display directory stack.\n"
" \n"
" \twith its position in the stack\n"
" \n"
" Arguments:\n"
-" +N\tDisplays the Nth entry counting from the left of the list shown "
-"by\n"
+" +N\tDisplays the Nth entry counting from the left of the list shown by\n"
" \tdirs when invoked without options, starting with zero.\n"
" \n"
-" -N\tDisplays the Nth entry counting from the right of the list shown "
-"by\n"
+" -N\tDisplays the Nth entry counting from the right of the list shown by\n"
" \tdirs when invoked without options, starting with zero.\n"
" \n"
" Exit Status:\n"
" Returns success unless an invalid option is supplied or an error occurs."
msgstr ""
+"Zeigt den Verzeichnisstapel an.\n"
+"\n"
+" Zeigt die Liste der gegenwärtig gespeicherten Verzeichnisse.\n"
+" Diese werden mit dem `pushd' Kommando eingetragen und mit dem\n"
+" `popd' Kommando ausgelesen.\n"
+"\n"
+" Optionen:\n"
+" -c Löscht den Verzeichnisstapel.\n"
+" -l Keine Abkürzung für das Heimatverzeichnis durch die\n"
+" Tilde (~).\n"
+" -p Ausgabe von einem Eintrag pro Zeile.\n"
+" -v Ausgabe von einem Eintrag pro Zeile mit Angabe der\n"
+" Position im Stapel<\n"
+"\n"
+" Argumente:\n"
+" +N Gibt das N'te Element von links der Liste aus, die\n"
+" ohne Argumente ausgegeben wird. Die Zählung beginnt\n"
+" bei 0.\n"
+" -N Gibt das N'te Element von rechts der Liste aus, die\n"
+" ohne Argumente ausgegeben wird. Die Zählung beginnt\n"
+" bei 0.\n"
+"\n"
+" Rückgabewert:\n"
+" Gibt Erfolg zurück, außer bei einer ungültigen Option oder wenn\n"
+" ein Fehler auftritt."
-#: builtins.c:1885
+#: builtins.c:1884
msgid ""
"Set and unset shell options.\n"
" \n"
" Change the setting of each shell option OPTNAME. Without any option\n"
-" arguments, list all shell options with an indication of whether or not "
-"each\n"
+" arguments, list all shell options with an indication of whether or not each\n"
" is set.\n"
" \n"
" Options:\n"
" Returns success if OPTNAME is enabled; fails if an invalid option is\n"
" given or OPTNAME is disabled."
msgstr ""
+"Setzt oder löscht Shell Optionen.\n"
+"\n"
+" Ändert die in `Optionsname' genannten Shell Optionen. Ohne\n"
+" Argumente wird eine Liste der Shell Optionen un deren Stati\n"
+" ausgegeben.\n"
+"\n"
+" Optionen:\n"
+" -o Beschränkt die Optionsmanen auf die, welche mit \n"
+" `set -o' definiert werden müssen.\n"
+" -p Gibt alle Shelloptionen und deren Stati aus.\n"
+" -q Unterdrückt Ausgaben.\n"
+" -s Setzt jede Option in `Optionsname.'\n"
+" -u Deaktiviert jede Option in `Optionsname'.\n"
+"\n"
+" Rückgabewert:\n"
+" Gibt Erfolg zurück, wenn eine Option gesetzt worden ist. Wenn\n"
+" eine ungültige Option angegeben wurde oder eine Option deaktiviert\n"
+" worden ist, wird Fehler zurückgegeben."
-#: builtins.c:1906
+#: builtins.c:1905
msgid ""
"Formats and prints ARGUMENTS under control of the FORMAT.\n"
" \n"
" -v var\tassign the output to shell variable VAR rather than\n"
" \t\tdisplay it on the standard output\n"
" \n"
-" FORMAT is a character string which contains three types of objects: "
-"plain\n"
-" characters, which are simply copied to standard output; character "
-"escape\n"
+" FORMAT is a character string which contains three types of objects: plain\n"
+" characters, which are simply copied to standard output; character escape\n"
" sequences, which are converted and copied to the standard output; and\n"
-" format specifications, each of which causes printing of the next "
-"successive\n"
+" format specifications, each of which causes printing of the next successive\n"
" argument.\n"
" \n"
-" In addition to the standard format specifications described in "
-"printf(1),\n"
+" In addition to the standard format specifications described in printf(1),\n"
" printf interprets:\n"
" \n"
" %b\texpand backslash escape sequences in the corresponding argument\n"
" %q\tquote the argument in a way that can be reused as shell input\n"
-" %(fmt)T output the date-time string resulting from using FMT as a "
-"format\n"
+" %(fmt)T output the date-time string resulting from using FMT as a format\n"
" string for strftime(3)\n"
" \n"
" The format is re-used as necessary to consume all of the arguments. If\n"
" there are fewer arguments than the format requires, extra format\n"
-" specifications behave as if a zero value or null string, as "
-"appropriate,\n"
+" specifications behave as if a zero value or null string, as appropriate,\n"
" had been supplied.\n"
" \n"
" Exit Status:\n"
-" Returns success unless an invalid option is given or a write or "
-"assignment\n"
+" Returns success unless an invalid option is given or a write or assignment\n"
" error occurs."
msgstr ""
-#: builtins.c:1940
+#: builtins.c:1939
msgid ""
"Specify how arguments are to be completed by Readline.\n"
" \n"
-" For each NAME, specify how arguments are to be completed. If no "
-"options\n"
-" are supplied, existing completion specifications are printed in a way "
-"that\n"
+" For each NAME, specify how arguments are to be completed. If no options\n"
+" are supplied, existing completion specifications are printed in a way that\n"
" allows them to be reused as input.\n"
" \n"
" Options:\n"
" Returns success unless an invalid option is supplied or an error occurs."
msgstr ""
-#: builtins.c:1968
+#: builtins.c:1967
msgid ""
"Display possible completions depending on the options.\n"
" \n"
" Intended to be used from within a shell function generating possible\n"
-" completions. If the optional WORD argument is supplied, matches "
-"against\n"
+" completions. If the optional WORD argument is supplied, matches against\n"
" WORD are generated.\n"
" \n"
" Exit Status:\n"
" Returns success unless an invalid option is supplied or an error occurs."
msgstr ""
-#: builtins.c:1983
+#: builtins.c:1982
msgid ""
"Modify or display completion options.\n"
" \n"
-" Modify the completion options for each NAME, or, if no NAMEs are "
-"supplied,\n"
-" the completion currently being executed. If no OPTIONs are given, "
-"print\n"
-" the completion options for each NAME or the current completion "
-"specification.\n"
+" Modify the completion options for each NAME, or, if no NAMEs are supplied,\n"
+" the completion currently being executed. If no OPTIONs are given, print\n"
+" the completion options for each NAME or the current completion specification.\n"
" \n"
" Options:\n"
" \t-o option\tSet completion option OPTION for each NAME\n"
" have a completion specification defined."
msgstr ""
-#: builtins.c:2013
+#: builtins.c:2012
msgid ""
"Read lines from the standard input into an indexed array variable.\n"
" \n"
-" Read lines from the standard input into the indexed array variable "
-"ARRAY, or\n"
-" from file descriptor FD if the -u option is supplied. The variable "
-"MAPFILE\n"
+" Read lines from the standard input into the indexed array variable ARRAY, or\n"
+" from file descriptor FD if the -u option is supplied. The variable MAPFILE\n"
" is the default ARRAY.\n"
" \n"
" Options:\n"
-" -n count\tCopy at most COUNT lines. If COUNT is 0, all lines are "
-"copied.\n"
-" -O origin\tBegin assigning to ARRAY at index ORIGIN. The default "
-"index is 0.\n"
+" -n count\tCopy at most COUNT lines. If COUNT is 0, all lines are copied.\n"
+" -O origin\tBegin assigning to ARRAY at index ORIGIN. The default index is 0.\n"
" -s count \tDiscard the first COUNT lines read.\n"
" -t\t\tRemove a trailing newline from each line read.\n"
-" -u fd\t\tRead lines from file descriptor FD instead of the standard "
-"input.\n"
+" -u fd\t\tRead lines from file descriptor FD instead of the standard input.\n"
" -C callback\tEvaluate CALLBACK each time QUANTUM lines are read.\n"
-" -c quantum\tSpecify the number of lines read between each call to "
-"CALLBACK.\n"
+" -c quantum\tSpecify the number of lines read between each call to CALLBACK.\n"
" \n"
" Arguments:\n"
" ARRAY\t\tArray variable name to use for file data.\n"
" element to be assigned and the line to be assigned to that element\n"
" as additional arguments.\n"
" \n"
-" If not supplied with an explicit origin, mapfile will clear ARRAY "
-"before\n"
+" If not supplied with an explicit origin, mapfile will clear ARRAY before\n"
" assigning to it.\n"
" \n"
" Exit Status:\n"
-" Returns success unless an invalid option is given or ARRAY is readonly "
-"or\n"
+" Returns success unless an invalid option is given or ARRAY is readonly or\n"
" not an indexed array."
msgstr ""
-#: builtins.c:2047
+#: builtins.c:2046
msgid ""
"Read lines from a file into an array variable.\n"
" \n"
"Liest Zeilen einer Datei in eine Array Variable.\n"
"\n"
" Ist ein Synonym für `mapfile'."
-
-#~ msgid "Copyright (C) 2009 Free Software Foundation, Inc.\n"
-#~ msgstr "Copyright (C) 2009 Free Software Foundation, Inc.\n"
-
-#~ msgid ""
-#~ "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl."
-#~ "html>\n"
-#~ msgstr ""
-#~ "Lizenz GPLv2+: GNU GPL Version 2 oder jünger <http://gnu.org/licenses/gpl."
-#~ "html>\n"
# here-document tuj-dokumento (info "(bash)Redirections")
# indexed array entjerindica tabelo (info "(bash)Arrays")
# positional parameter numerparametro ($1 ...) (info "(bash)Positional Parameters")
+# resolve (symbolic links) elnodigi
# special builtin speciala komando (info "(coreutils)Special built-in utilities")
# substitution anstataŭigo (info "(bash)Shell Expansions")
# unset malvalorizi (variablon); malaktivigi, malŝalti (opcion, nomon)
"Project-Id-Version: GNU bash 4.3-pre2\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-08 16:00-0500\n"
-"PO-Revision-Date: 2013-08-18 15:10+0700\n"
+"PO-Revision-Date: 2013-08-24 14:35+0700\n"
"Last-Translator: Sergio Pokrovskij <sergio.pokrovskij@gmail.com>\n"
"Language-Team: Esperanto <translation-team-eo@lists.sourceforge.net>\n"
"Language: eo\n"
#: builtins/declare.def:311 builtins/declare.def:526
#, c-format
msgid "%s: reference variable cannot be an array"
-msgstr "%s: referenca variablo ne povas esti tabelo"
+msgstr "%s: Referenca variablo ne povas esti tabelo"
#: builtins/declare.def:317
#, c-format
msgid "%s: nameref variable self references not allowed"
-msgstr "%s: nomreferenca variablo ne referencu sin mem"
+msgstr "%s: Nomreferenca variablo ne referencu sin mem"
#: builtins/declare.def:415
msgid "cannot use `-f' to make functions"
#: builtins/declare.def:565
#, c-format
msgid "%s: cannot destroy array variables in this way"
-msgstr "$%s: ĉi tiel ne eblas neniigi variablojn"
+msgstr "%s: Ĉi tiel ne eblas neniigi tabelvariablojn"
#: builtins/declare.def:572 builtins/read.def:721
#, c-format
#: execute_cmd.c:4347
#, c-format
msgid "%s: maximum function nesting level exceeded (%d)"
-msgstr "%s: la ingado de funkcioj superis sian maksimumon (%d)"
+msgstr "%s: La ingado de funkcioj superis sian maksimumon (%d)"
#: execute_cmd.c:4840
#, c-format
" alinome."
# unalias [-a] name [name ...]
+# unalias [-a] NOMO [NOMO ...]
#: builtins.c:276
msgid ""
"Remove each NAME from the list of defined aliases.\n"
" \n"
" Return success unless a NAME is not an existing alias."
msgstr ""
-"Forigu la nomojn name ... el la listo de difinitaj alinomoj.\n"
+"Forigu la NOMOjn el la listo de difinitaj alinomoj.\n"
"\n"
" Opcioj:\n"
" -a\tSe enestas la opcio „-a‟, ĉiujn alinomojn forigu.\n"
" estas valida."
# cd:
-# "resolve symbolic links" -- interpreti? ekstrakti? (-L, -P)??
#: builtins.c:385
msgid ""
"Change the shell working directory.\n"
msgstr ""
"Ŝanĝu la kurantan laboran dosierujon de la ŝelo.\n"
"\n"
-" La kuranta dosierujo iĝu DOSIERUJO aŭ, se DOSIERUJO malestas,\n"
+" La kuranta dosierujo iĝu DOSIERUJO -- aŭ, se DOSIERUJO malestas,\n"
" la valoro de la variablo $HOME.\n"
"\n"
" La variablo $CDPATH difinas la serĉvojon por la dosierujo\n"
" variablo havas valoron, tiu valoro estas uzata kiel DOSIERUJO.\n"
"\n"
" Opcioj:\n"
-" -L\tsimbolaj ligiloj estu sekvataj: interpretu simbolajn ligilojn\n"
-" en DOSIERUJO post prilaboro de la aperoj de „..“.\n"
-" -P\tuzu la fizikan strukturon de dosierujoj sen iri laŭ simbolaj\n"
-" ligiloj: interpretu simbolajn ligilojn de DOSIERUJO antaŭ ol\n"
-" prilabori la aperojn de „..“.\n"
+" -L\tlaŭu simbolajn Ligilojn: en DOSIERUJO, traktu la aperojn de\n"
+" „..“ antaŭ ol elnodigi la simbolajn ligilojn.\n"
+" -P\tuzu la Fizikan strukturon de dosierujoj, elnodiginte simbolajn\n"
+" ligilojn de DOSIERUJO antaŭ ol trakti la aperojn de „..“.\n"
" -e eliru kun nenula elirstato se „-P‟ ĉeestas kaj la\n"
" kuranta dosierujo ne estas determinebla.\n"
"\n"
-" Defaŭlte la simbolaj ligiloj estas sekvataj, kvazaŭ „-L‟ ĉeestus.\n"
-" La prilaboro de „..“ konsistas en forigo de la ĵus-antaŭa vojnoma\n"
+" Defaŭlte la simbolaj ligiloj estas laŭataj, kvazaŭ „-L‟ ĉeestus.\n"
+" La traktado de „..“ konsistas en forigo de la ĵus-antaŭa vojnoma\n"
" ero retrodirekte ĝis la oblikvo „/“ aŭ la komenco de DOSIERUJO.\n"
"\n"
" Elirstato:\n"
" Exit Status:\n"
" Returns success unless an invalid option is given or an error occurs."
msgstr ""
-"Eligu aŭ redaktu la historiliston\n"
+"Eligu aŭ redaktu la historiliston.\n"
"\n"
" Eligu la liston de enigitaj komandoj kun lininumeroj. La ŝanĝitajn\n"
" liniojn marku per „*‟. Kun argumento n, eligu nur la ĵusajn\n"
" n liniojn.\n"
"\n"
" Opcioj:\n"
-" -c\tforviŝu la tutan historion (forigu ĉiujn eroj el la listo)\n"
+" -c forviŝu la tutan historion (forigu ĉiujn erojn el la listo)\n"
" -d forviŝu la linion kies numero estas DEŜOVO\n"
"\n"
-" -a\taldonu la historiliniojn de la kuranta seanco al la\n"
+" -a aldonu la historiliniojn de la kuranta seanco al la\n"
" historidosiero\n"
-" -n\tlegu ĉiujn ankoraŭ ne legitajn liniojn el la historidosiero\n"
+" -n legu ĉiujn ankoraŭ ne legitajn liniojn el la historidosiero\n"
" kaj aldonu ilin en la historiliston\n"
" -r legu la dosieron kaj aldonu ĝian enhavon al la kuranta\n"
" historilisto\n"
"\tfunkcioj\n"
" -H\tEbligu atingi la historion !-stile. Defaŭlte la opcio estas\n"
"\taktiva en la dialogaj ŝeloj.\n"
-" -P\tNe interpretu simbolajn ligilojn plenumante komandojn kiuj\n"
-" ŝanĝas la kurantan dosierujon („cd‟ ktp)\n"
+" -P\tLa simbolaj ligiloj estu travideblaj ĉe plenumo de komandoj\n"
+"\tkiuj ŝanĝas la kurantan dosierujon („cd‟ ktp uzu «fizikan»\n"
+"\tinterpreton de vojnomo).\n"
" -T\tSe aktiva, la DEBUG-kaptilon (DEBUG trap) heredas la ŝelaj\n"
"\tfunkcioj\n"
" --\tLa restantajn argumentojn uzu por valorizi la numerparametrojn.\n"
-" Se tiaj argumentoj mankas, malvalorizu la numerparametrojn.\n"
+"\tSe tiaj argumentoj mankas, malvalorizu la numerparametrojn.\n"
" -\tLa restantajn argumentojn uzu por valorizi la numerparametrojn.\n"
-" La opcioj -x kaj -v malaktiviĝas.\n"
+"\tLa opcioj -x kaj -v malaktiviĝas.\n"
"\n"
" Uzante la signon + anstataŭ - vi povas malŝalti la opcion. La\n"
" opciojn ankaŭ eblas uzi ĉe la voko de la ŝelo. La kuranta aro da\n"
" Exit Status:\n"
" Returns success unless an invalid option is supplied or an error occurs."
msgstr ""
-"Ŝanĝu risurcolimaĵojn de la ŝelo\n"
+"Ŝanĝu risurcolimaĵojn de la ŝelo.\n"
"\n"
" La komando „ulimit‟ ebligas mastrumi la risurcojn disponeblajn al\n"
" la procezoj lanĉataj el la ŝelo (se la operaciumo ebligas tion).\n"
"\n"
" Opcioj:\n"
-" -S\tŝanĝebla („soft‟) limo\n"
-" -H\tfirma („hard‟) limo\n"
-" -a\teligu ĉiujn kurantajn risurcolimaĵojn\n"
+" -S ŝanĝebla („soft‟) limo\n"
+" -H firma („hard‟) limo\n"
+" -a eligu ĉiujn kurantajn risurcolimaĵojn\n"
" -b la kontaktoskatola bufrolongo\n"
-" -c\tmaksimuma longo de nekropsia dosiero („core‟)\n"
-" -d\tmaksimuma longo de datumsegmento de procezo\n"
-" -e\tmaksimuma viciga prioritato („nice‟)\n"
+" -c maksimuma longo de nekropsia dosiero („core‟)\n"
+" -d maksimuma longo de datumsegmento de procezo\n"
+" -e maksimuma viciga prioritato („nice‟)\n"
" -i maksimuma longo de pendaj signaloj\n"
-" -f\tmaksimuma longo de dosieroj skribataj de la ŝelo kaj ĝiaj idoj\n"
-" -l\tmaksimuma longo de ŝlosebla procezmemoro (mlock)\n"
-" -m\tmaksimuma longo de rezida procezmemoro\n"
-" -n\tmaksimuma nombro de malfermitaj dosiernumeroj\n"
-" -p\tlongo de dukta bufro (pipe)\n"
-" -q\tmaksimuma nombro da bajtoj en atendovicoj de Poziksaj mesaĝoj\n"
-" -r\tmaksimuma prioritato realtempa\n"
-" -s\tmaksimuma longo de stako\n"
-" -t\tmaksimuma tempo ĉefprocesora (en sekundoj)\n"
-" -u\tmaksimuma nombro de procezoj de la uzanto\n"
-" -v\tlongo de la virtuala memoro\n"
-" -x\tmaksimuma nombro de dosierŝlosoj\n"
+" -f maksimuma longo de dosieroj skribataj de la ŝelo kaj ĝiaj idoj\n"
+" -l maksimuma longo de ŝlosebla procezmemoro (mlock)\n"
+" -m maksimuma longo de rezida procezmemoro\n"
+" -n maksimuma nombro de malfermitaj dosiernumeroj\n"
+" -p longo de dukta bufro (pipe)\n"
+" -q maksimuma nombro da bajtoj en atendovicoj de Poziksaj mesaĝoj\n"
+" -r maksimuma prioritato realtempa\n"
+" -s maksimuma longo de stako\n"
+" -t maksimuma tempo ĉefprocesora (en sekundoj)\n"
+" -u maksimuma nombro de procezoj de la uzanto\n"
+" -v longo de la virtuala memoro\n"
+" -x maksimuma nombro de dosierŝlosoj\n"
" -T maksimuma nombro de fadenoj\n"
"\n"
" Ne ĉiuj opcioj disponeblas sur ĉiuj komputilaj platformoj.\n"
" Returns success unless an invalid option is given or a write or assignment\n"
" error occurs."
msgstr ""
-"Aranĝu kaj eligu argumentojn argumentojn laŭ formato\n"
+"Aranĝu kaj eligu ARGUMENTOJn laŭ FORMATO.\n"
"\n"
" Opcio:\n"
" -v VAR eligu en ŝelvariablon VAR anstataŭ en la ĉefeligujon\n"
" Exit Status:\n"
" Returns success unless an invalid option is supplied or an error occurs."
msgstr ""
-"Difinu, kiel Readline kompletigu argumentojn\n"
+"Difinu, kiel Readline kompletigu argumentojn.\n"
"\n"
" Por ĉiu NOMO difinu, kiel la argumentoj estu kompletigotaj. Se\n"
" nenia opcio estas donita, eligu la aktualajn \n"
" kompletigoregulojn en formo reuzebla por enigo en la ŝelon.\n"
"\n"
" Opcioj:\n"
-" -p\tkompletigoregulojn en formo reuzebla por enigo en la ŝelon\n"
+" -p\teligu kompletigoregulojn en formo uzebla por enigo en la ŝelon\n"
" -r\tforigu la kompletigoregulon por ĉiu NOMO, aŭ, se nenia NOMO\n"
"\testas donita, ĉiujn kompletigoregulojn\n"
" -D apliku la indikitajn kompletigojn kaj agojn Defaŭlte por la\n"
# Swedish translation of bash
-# Copyright © 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+# Copyright © 2008, 2009, 2010, 2011, 2013 Free Software Foundation, Inc.
# This file is distributed under the same license as the bash package.
-# Göran Uddeborg <goeran@uddeborg.se>, 2008, 2009, 2010, 2011.
+# Göran Uddeborg <goeran@uddeborg.se>, 2008, 2009, 2010, 2011, 2013.
#
-# $Revision: 1.11 $
+# $Revision: 1.13 $
msgid ""
msgstr ""
-"Project-Id-Version: bash 4.2\n"
+"Project-Id-Version: bash 4.3-pre2\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2013-08-14 11:14-0400\n"
-"PO-Revision-Date: 2011-02-16 23:42+0100\n"
+"POT-Creation-Date: 2013-03-08 16:00-0500\n"
+"PO-Revision-Date: 2013-08-25 20:00+0200\n"
"Last-Translator: Göran Uddeborg <goeran@uddeborg.se>\n"
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
"Language: sv\n"
msgid "bad array subscript"
msgstr "felaktigt vektorindex"
-#: arrayfunc.c:356 builtins/declare.def:585
+#: arrayfunc.c:356 builtins/declare.def:578
#, c-format
msgid "%s: cannot convert indexed to associative array"
msgstr "%s: det går inte att konvertera en indexerad vektor till associativ"
msgid "%s: cannot create: %s"
msgstr "%s: det går inte att skapa: %s"
-#: bashline.c:3928
+#: bashline.c:3923
msgid "bash_execute_unix_command: cannot find keymap for command"
-msgstr ""
-"bash_execute_unix_command: det går inte att hitta en tangentbindning för "
-"kommandot"
+msgstr "bash_execute_unix_command: det går inte att hitta en tangentbindning för kommandot"
-#: bashline.c:4015
+#: bashline.c:4010
#, c-format
msgid "%s: first non-whitespace character is not `\"'"
msgstr "%s: första ickeblanka tecknet är inte '\"'"
-#: bashline.c:4044
+#: bashline.c:4039
#, c-format
msgid "no closing `%c' in %s"
msgstr "ingen avslutande \"%c\" i %s"
-#: bashline.c:4078
+#: bashline.c:4073
#, c-format
msgid "%s: missing colon separator"
msgstr "%s: kolonseparator saknas"
msgid "invalid hex number"
msgstr "ogiltigt hexadecimalt tal"
-#: builtins/common.c:242 expr.c:1461
+#: builtins/common.c:242 expr.c:1451
msgid "invalid number"
msgstr "ogiltigt tal"
msgid "can only be used in a function"
msgstr "kan endast användas i en funktion"
-#: builtins/declare.def:315 builtins/declare.def:533
+#: builtins/declare.def:311 builtins/declare.def:526
#, c-format
msgid "%s: reference variable cannot be an array"
-msgstr ""
+msgstr "%s: en referensvariabel kan inte vara en vektor"
-#: builtins/declare.def:324
+#: builtins/declare.def:317
#, c-format
msgid "%s: nameref variable self references not allowed"
-msgstr ""
+msgstr "%s: att en namnreferensvariabel självrefererar är inte tillåtet"
-#: builtins/declare.def:422
+#: builtins/declare.def:415
msgid "cannot use `-f' to make functions"
msgstr "det går inte att använda \"-f\" för att göra funktioner"
-#: builtins/declare.def:434 execute_cmd.c:5328
+#: builtins/declare.def:427 execute_cmd.c:5315
#, c-format
msgid "%s: readonly function"
msgstr "%s: endast läsbar funktion"
-#: builtins/declare.def:572
+#: builtins/declare.def:565
#, c-format
msgid "%s: cannot destroy array variables in this way"
msgstr "%s: det går inte att förstöra vektorvariabler på detta sätt"
-#: builtins/declare.def:579 builtins/read.def:733
+#: builtins/declare.def:572 builtins/read.def:721
#, c-format
msgid "%s: cannot convert associative to indexed array"
msgstr "%s: det går inte att konvertera en associativ vektor till indexerad"
msgid "%s: cannot delete: %s"
msgstr "%s: kan inte ta bort: %s"
-#: builtins/evalfile.c:140 builtins/hash.def:171 execute_cmd.c:5175
+#: builtins/evalfile.c:140 builtins/hash.def:171 execute_cmd.c:5162
#: shell.c:1481
#, c-format
msgid "%s: is a directory"
msgid "no command found"
msgstr "hittar inget kommando"
-#: builtins/fc.def:320 builtins/fc.def:369
+#: builtins/fc.def:312 builtins/fc.def:359
msgid "history specification"
msgstr "historiespecifikation"
-#: builtins/fc.def:390
+#: builtins/fc.def:380
#, c-format
msgid "%s: cannot open temp file: %s"
msgstr "%s: det går inte att öppna temporärfil: %s"
msgstr[0] "Skalkommandon som matchar nyckelordet '"
msgstr[1] "Skalkommandon som matchar nyckelorden '"
-#: builtins/help.def:182
+#: builtins/help.def:168
#, c-format
-msgid ""
-"no help topics match `%s'. Try `help help' or `man -k %s' or `info %s'."
-msgstr ""
-"inget hjälpämne matchar \"%s\". Prova \"help help\" eller \"man -k %s\" "
-"eller \"info %s\"."
+msgid "no help topics match `%s'. Try `help help' or `man -k %s' or `info %s'."
+msgstr "inget hjälpämne matchar \"%s\". Prova \"help help\" eller \"man -k %s\" eller \"info %s\"."
-#: builtins/help.def:199
+#: builtins/help.def:185
#, c-format
msgid "%s: cannot open: %s"
msgstr "%s: det går inte att öppna: %s"
-#: builtins/help.def:485
+#: builtins/help.def:471
#, c-format
msgid ""
"These shell commands are defined internally. Type `help' to see this list.\n"
msgid "Unknown error"
msgstr "Okänt fel"
-#: builtins/let.def:95 builtins/let.def:120 expr.c:583 expr.c:598
+#: builtins/let.def:95 builtins/let.def:120 expr.c:586 expr.c:601
msgid "expression expected"
msgstr "uttryck förväntades"
msgstr "ingen annan katalog"
#: builtins/pushd.def:354
-#, fuzzy, c-format
+#, c-format
msgid "%s: invalid argument"
-msgstr "%s: ogiltigt gränsargument"
+msgstr "%s: ogiltigt argument"
#: builtins/pushd.def:468
msgid "<no current directory>"
" \twith its position in the stack\n"
" \n"
" Arguments:\n"
-" +N\tDisplays the Nth entry counting from the left of the list shown "
-"by\n"
+" +N\tDisplays the Nth entry counting from the left of the list shown by\n"
" \tdirs when invoked without options, starting with zero.\n"
" \n"
-" -N\tDisplays the Nth entry counting from the right of the list shown "
-"by\n"
+" -N\tDisplays the Nth entry counting from the right of the list shown by\n"
"\tdirs when invoked without options, starting with zero."
msgstr ""
"Visa listan av kataloger i minnet just nu. Kataloger hamnar i listan\n"
msgid "%s: invalid timeout specification"
msgstr "%s: ogiltig tidsgränsspecifikation"
-#: builtins/read.def:678
+#: builtins/read.def:666
#, c-format
msgid "read error: %d: %s"
msgstr "läsfel: %d: %s"
#: builtins/return.def:75
msgid "can only `return' from a function or sourced script"
-msgstr ""
-"det går bara att göra \"return\" från en funktion eller källinläst skript"
+msgstr "det går bara att göra \"return\" från en funktion eller källinläst skript"
#: builtins/set.def:782
msgid "cannot simultaneously unset a function and a variable"
msgid "cannot redirect standard input from /dev/null: %s"
msgstr "det går inte att omdiregera standard in från /dev/null: %s"
-#: execute_cmd.c:1230
+#: execute_cmd.c:1228
#, c-format
msgid "TIMEFORMAT: `%c': invalid format character"
msgstr "TIMEFORMAT: \"%c\": ogiltigt formateringstecken"
-#: execute_cmd.c:2284
+#: execute_cmd.c:2282
msgid "pipe error"
msgstr "rörfel"
-#: execute_cmd.c:4358
+#: execute_cmd.c:4347
#, c-format
msgid "%s: maximum function nesting level exceeded (%d)"
-msgstr ""
+msgstr "%s: maximal nästning av funktioner överskriden (%d)"
-#: execute_cmd.c:4851
+#: execute_cmd.c:4840
#, c-format
msgid "%s: restricted: cannot specify `/' in command names"
msgstr "%s: begränsat: det går inte att ange \"/\" i kommandonamn"
-#: execute_cmd.c:4940
+#: execute_cmd.c:4929
#, c-format
msgid "%s: command not found"
msgstr "%s: kommandot finns inte"
-#: execute_cmd.c:5173
+#: execute_cmd.c:5160
#, c-format
msgid "%s: %s"
msgstr "%s: %s"
-#: execute_cmd.c:5210
+#: execute_cmd.c:5197
#, c-format
msgid "%s: %s: bad interpreter"
msgstr "%s: %s: felaktig tolk"
-#: execute_cmd.c:5247
-#, fuzzy, c-format
+#: execute_cmd.c:5234
+#, c-format
msgid "%s: cannot execute binary file: %s"
-msgstr "%s: det går inte att köra binär fil"
+msgstr "%s: det går inte att köra binär fil: %s"
-#: execute_cmd.c:5319
-#, fuzzy, c-format
+#: execute_cmd.c:5306
+#, c-format
msgid "`%s': is a special builtin"
-msgstr "%s är inbyggt i skalet\n"
+msgstr "”%s”: är en speciell inbyggd"
-#: execute_cmd.c:5371
+#: execute_cmd.c:5358
#, c-format
msgid "cannot duplicate fd %d to fd %d"
msgstr "det går inte att duplicera fb %d till fb %d"
-#: expr.c:259
+#: expr.c:262
msgid "expression recursion level exceeded"
msgstr "rekursionsnivå i uttryck överskriden"
-#: expr.c:283
+#: expr.c:286
msgid "recursion stack underflow"
msgstr "underspill i rekursionsstacken"
-#: expr.c:431
+#: expr.c:434
msgid "syntax error in expression"
msgstr "syntaxfel i uttrycket"
-#: expr.c:475
+#: expr.c:478
msgid "attempted assignment to non-variable"
msgstr "försök att tilldela till en icke-variabel"
-#: expr.c:495 expr.c:851
+#: expr.c:498 expr.c:847
msgid "division by 0"
msgstr "division med 0"
-#: expr.c:542
+#: expr.c:545
msgid "bug: bad expassign token"
msgstr "bug: felaktig expassign-token"
-#: expr.c:595
+#: expr.c:598
msgid "`:' expected for conditional expression"
msgstr "\":\" förväntades i villkorligt uttryck"
-#: expr.c:910
+#: expr.c:904
msgid "exponent less than 0"
msgstr "exponenten är mindre än 0"
-#: expr.c:967
+#: expr.c:957
msgid "identifier expected after pre-increment or pre-decrement"
msgstr "en identifierare förväntades efter pre-ökning eller pre-minskning"
-#: expr.c:993
+#: expr.c:983
msgid "missing `)'"
msgstr "\")\" saknas"
-#: expr.c:1044 expr.c:1381
+#: expr.c:1034 expr.c:1371
msgid "syntax error: operand expected"
msgstr "syntaxfel: en operand förväntades"
-#: expr.c:1383
+#: expr.c:1373
msgid "syntax error: invalid arithmetic operator"
msgstr "syntaxfel: ogiltig aritmetisk operator"
-#: expr.c:1407
+#: expr.c:1397
#, c-format
msgid "%s%s%s: %s (error token is \"%s\")"
msgstr "%s%s%s: %s (felsymbol är \"%s\")"
-#: expr.c:1465
+#: expr.c:1455
msgid "invalid arithmetic base"
msgstr "ogiltig aritmetisk bas"
-#: expr.c:1485
+#: expr.c:1475
msgid "value too great for base"
msgstr "värdet är för stort för basen"
-#: expr.c:1534
+#: expr.c:1524
#, c-format
msgid "%s: expression error\n"
msgstr "%s: uttrycksfel\n"
msgid "getcwd: cannot access parent directories"
msgstr "getcwd: det går inte att komma åt föräldrakatalogen"
-#: input.c:101 subst.c:5129
+#: input.c:101 subst.c:5067
#, c-format
msgid "cannot reset nodelay mode for fd %d"
msgstr "det går inte att återställa fördröjningsfritt läge för fb %d"
#: input.c:267
#, c-format
msgid "cannot allocate new file descriptor for bash input from fd %d"
-msgstr ""
-"det går inte att allokera en ny filbeskrivare för bashindata från fb %d"
+msgstr "det går inte att allokera en ny filbeskrivare för bashindata från fb %d"
#: input.c:275
#, c-format
msgid "wait_for: No record of process %ld"
msgstr "wait_for: Ingen uppgift om process %ld"
-#: jobs.c:2692
+#: jobs.c:2689
#, c-format
msgid "wait_for_job: job %d is stopped"
msgstr "wait_for_job: jobb %d är stoppat"
-#: jobs.c:2984
+#: jobs.c:2981
#, c-format
msgid "%s: job has terminated"
msgstr "%s: jobbet har avslutat"
-#: jobs.c:2993
+#: jobs.c:2990
#, c-format
msgid "%s: job %d already in background"
msgstr "%s: jobb %d är redan i bakgrunden"
-#: jobs.c:3218
+#: jobs.c:3215
msgid "waitchld: turning on WNOHANG to avoid indefinite block"
msgstr "waitchld: slår på WNOHANG för att undvika oändlig blockering"
-#: jobs.c:3709
+#: jobs.c:3699
#, c-format
msgid "%s: line %d: "
msgstr "%s: rad %d: "
-#: jobs.c:3723 nojobs.c:843
+#: jobs.c:3713 nojobs.c:843
#, c-format
msgid " (core dumped)"
msgstr " (minnesutskrift skapad)"
-#: jobs.c:3735 jobs.c:3748
+#: jobs.c:3725 jobs.c:3738
#, c-format
msgid "(wd now: %s)\n"
msgstr "(ak nu: %s)\n"
-#: jobs.c:3780
+#: jobs.c:3770
msgid "initialize_job_control: getpgrp failed"
msgstr "initialize_job_control: getpgrp misslyckades"
-#: jobs.c:3841
+#: jobs.c:3831
msgid "initialize_job_control: line discipline"
msgstr "initialize_job_control: linjedisciplin"
-#: jobs.c:3851
+#: jobs.c:3841
msgid "initialize_job_control: setpgid"
msgstr "initialize_job_control: setpgid"
-#: jobs.c:3872 jobs.c:3881
+#: jobs.c:3862 jobs.c:3871
#, c-format
msgid "cannot set terminal process group (%d)"
msgstr "det går inte att sätta terminalprocessgrupp (%d)"
-#: jobs.c:3886
+#: jobs.c:3876
msgid "no job control in this shell"
msgstr "ingen jobbstyrning i detta skal"
#: make_cmd.c:759
#, c-format
msgid "make_redirection: redirection instruction `%d' out of range"
-msgstr ""
-"make_redirection: omdirigeringsinstruktion \"%d\" utanför giltigt intervall"
+msgstr "make_redirection: omdirigeringsinstruktion \"%d\" utanför giltigt intervall"
-#: parse.y:3210 parse.y:3493
+#: parse.y:3209 parse.y:3480
#, c-format
msgid "unexpected EOF while looking for matching `%c'"
msgstr "oväntat filslut vid sökning efter matchande \"%c\""
-#: parse.y:4099
+#: parse.y:4086
msgid "unexpected EOF while looking for `]]'"
msgstr "oväntat filslut vid sökning efter \"]]\""
-#: parse.y:4104
+#: parse.y:4091
#, c-format
msgid "syntax error in conditional expression: unexpected token `%s'"
msgstr "syntaxfel i villkorligt uttryck: oväntad symbol \"%s\""
-#: parse.y:4108
+#: parse.y:4095
msgid "syntax error in conditional expression"
msgstr "syntaxfel i villkorligt uttryck"
-#: parse.y:4186
+#: parse.y:4173
#, c-format
msgid "unexpected token `%s', expected `)'"
msgstr "oväntad symbol \"%s\", \")\" förväntades"
-#: parse.y:4190
+#: parse.y:4177
msgid "expected `)'"
msgstr "\")\" förväntades"
-#: parse.y:4218
+#: parse.y:4205
#, c-format
msgid "unexpected argument `%s' to conditional unary operator"
msgstr "oväntat argument \"%s\" till villkorlig unär operator"
-#: parse.y:4222
+#: parse.y:4209
msgid "unexpected argument to conditional unary operator"
msgstr "oväntat argument till villkorlig unär operator"
-#: parse.y:4268
+#: parse.y:4255
#, c-format
msgid "unexpected token `%s', conditional binary operator expected"
msgstr "oväntad symbol \"%s\", villkorlig binär operator förväntades"
-#: parse.y:4272
+#: parse.y:4259
msgid "conditional binary operator expected"
msgstr "villkorlig binär operato förväntades"
-#: parse.y:4294
+#: parse.y:4281
#, c-format
msgid "unexpected argument `%s' to conditional binary operator"
msgstr "oväntat argument \"%s\" till villkorlig binär operator"
-#: parse.y:4298
+#: parse.y:4285
msgid "unexpected argument to conditional binary operator"
msgstr "oväntat argument till villkorlig binär operator"
-#: parse.y:4309
+#: parse.y:4296
#, c-format
msgid "unexpected token `%c' in conditional command"
msgstr "oväntad symbol \"%c\" i villkorligt kommando"
-#: parse.y:4312
+#: parse.y:4299
#, c-format
msgid "unexpected token `%s' in conditional command"
msgstr "oväntad symbol \"%s\" i villkorligt kommando"
-#: parse.y:4316
+#: parse.y:4303
#, c-format
msgid "unexpected token %d in conditional command"
msgstr "oväntad symbol %d i villkorligt kommando"
-#: parse.y:5666
+#: parse.y:5649
#, c-format
msgid "syntax error near unexpected token `%s'"
msgstr "syntaxfel nära den oväntade symbolen \"%s\""
-#: parse.y:5684
+#: parse.y:5667
#, c-format
msgid "syntax error near `%s'"
msgstr "syntaxfel nära \"%s\""
-#: parse.y:5694
+#: parse.y:5677
msgid "syntax error: unexpected end of file"
msgstr "syntaxfel: oväntat filslut"
-#: parse.y:5694
+#: parse.y:5677
msgid "syntax error"
msgstr "syntaxfel"
-#: parse.y:5756
+#: parse.y:5739
#, c-format
msgid "Use \"%s\" to leave the shell.\n"
msgstr "Använd \"%s\" fär att lämna skalet.\n"
-#: parse.y:5918
+#: parse.y:5901
msgid "unexpected EOF while looking for matching `)'"
msgstr "oväntat filslut när matchande \")\" söktes"
msgid "/dev/(tcp|udp)/host/port not supported without networking"
msgstr "/dev/(tcp|udp)/host/port stöds inte utan nätverksfunktion"
-#: redir.c:861 redir.c:973 redir.c:1034 redir.c:1199
+#: redir.c:861 redir.c:971 redir.c:1032 redir.c:1194
msgid "redirection error: cannot duplicate fd"
msgstr "omdirigeringsfel: det går inte att duplicera fb"
msgstr "Skalflaggor:\n"
#: shell.c:1835
-#, fuzzy
msgid "\t-ilrsD or -c command or -O shopt_option\t\t(invocation only)\n"
-msgstr "\t-irsD eller -c kommando eller -O shopt_flagga\t\t(bara uppstart)\n"
+msgstr "\t-ilrsD eller -c kommando eller -O shopt_flagga\t\t(bara uppstart)\n"
#: shell.c:1850
#, c-format
msgid "Unknown Signal #%d"
msgstr "Okänd signal nr %d"
-#: subst.c:1358 subst.c:1516
+#: subst.c:1352 subst.c:1510
#, c-format
msgid "bad substitution: no closing `%s' in %s"
msgstr "felaktig substitution: ingen avslutande \"%s\" i %s"
-#: subst.c:2829
+#: subst.c:2823
#, c-format
msgid "%s: cannot assign list to array member"
msgstr "%s: det går inte att tilldela listor till vektormedlemmar"
-#: subst.c:5026 subst.c:5042
+#: subst.c:4964 subst.c:4980
msgid "cannot make pipe for process substitution"
msgstr "det går inte att skapa rör för processubstitution"
-#: subst.c:5074
+#: subst.c:5012
msgid "cannot make child for process substitution"
msgstr "det går inte att skapa barn för processubstitution"
-#: subst.c:5119
+#: subst.c:5057
#, c-format
msgid "cannot open named pipe %s for reading"
msgstr "det går inte att öppna namngivet rör %s för läsning"
-#: subst.c:5121
+#: subst.c:5059
#, c-format
msgid "cannot open named pipe %s for writing"
msgstr "det går inte att öppna namngivet rör %s för skrivning"
-#: subst.c:5139
+#: subst.c:5077
#, c-format
msgid "cannot duplicate named pipe %s as fd %d"
msgstr "det går inte att duplicera namngivet rör %s som fb %d"
-#: subst.c:5337
+#: subst.c:5273
msgid "cannot make pipe for command substitution"
msgstr "det går inte att skapa rör för kommandosubstitution"
-#: subst.c:5375
+#: subst.c:5311
msgid "cannot make child for command substitution"
msgstr "det går inte att skapa barn för kommandosubstitution"
-#: subst.c:5394
+#: subst.c:5330
msgid "command_substitute: cannot duplicate pipe as fd 1"
msgstr "command_substitute: det går inte att duplicera rör som fb 1"
-#: subst.c:5798 subst.c:8001
-#, fuzzy, c-format
+#: subst.c:5733 subst.c:7900
+#, c-format
msgid "%s: invalid variable name for name reference"
-msgstr "%s: %s: ogiltigt värde för spårningsfilbeskrivare"
+msgstr "%s: ogiltigt variabelnamn för referens"
-#: subst.c:6009
+#: subst.c:5926
#, c-format
msgid "%s: parameter null or not set"
msgstr "%s: parametern tom eller inte satt"
-#: subst.c:6281 subst.c:6296
+#: subst.c:6198 subst.c:6213
#, c-format
msgid "%s: substring expression < 0"
msgstr "%s: delstränguttryck < 0"
-#: subst.c:7457
+#: subst.c:7356
#, c-format
msgid "%s: bad substitution"
msgstr "%s: felaktig substitution"
-#: subst.c:7534
+#: subst.c:7433
#, c-format
msgid "$%s: cannot assign in this way"
msgstr "$%s: det går inte att tilldela på detta sätt"
-#: subst.c:7868
-msgid ""
-"future versions of the shell will force evaluation as an arithmetic "
-"substitution"
-msgstr ""
-"framtida versioner av skalet kommer att framtvinga evaluering som en "
-"aritmetisk substition"
+#: subst.c:7767
+msgid "future versions of the shell will force evaluation as an arithmetic substitution"
+msgstr "framtida versioner av skalet kommer att framtvinga evaluering som en aritmetisk substition"
-#: subst.c:8372
+#: subst.c:8271
#, c-format
msgid "bad substitution: no closing \"`\" in %s"
msgstr "felaktig ersättning: ingen avslutande \"`\" i %s"
-#: subst.c:9273
+#: subst.c:9172
#, c-format
msgid "no match: %s"
msgstr "ingen match: %s"
msgid "invalid signal number"
msgstr "ogiltigt signalnummer"
-#: trap.c:354
+#: trap.c:348
#, c-format
msgid "run_pending_traps: bad value in trap_list[%d]: %p"
msgstr "run_pending_traps: felaktigt värde i trap_list[%d]: %p"
-#: trap.c:358
+#: trap.c:352
#, c-format
-msgid ""
-"run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"
-msgstr ""
-"run_pending_traps: signalhanterare är SIG_DFL, skickar om %d (%s) till mig "
-"själv"
+msgid "run_pending_traps: signal handler is SIG_DFL, resending %d (%s) to myself"
+msgstr "run_pending_traps: signalhanterare är SIG_DFL, skickar om %d (%s) till mig själv"
-#: trap.c:413
+#: trap.c:398
#, c-format
msgid "trap_handler: bad signal %d"
msgstr "trap_handler: felaktig signal %d"
-#: variables.c:382
+#: variables.c:380
#, c-format
msgid "error importing function definition for `%s'"
msgstr "fel vid import av funktionsdefinition för \"%s\""
-#: variables.c:780
+#: variables.c:778
#, c-format
msgid "shell level (%d) too high, resetting to 1"
msgstr "skalnivå (%d) för hög, återställer till 1"
-#: variables.c:1865
-#, fuzzy, c-format
-msgid "%s: circular name reference"
-msgstr "%s: %s: ogiltigt värde för spårningsfilbeskrivare"
-
-#: variables.c:2228
+#: variables.c:2198
msgid "make_local_variable: no function context at current scope"
msgstr "make_local_variable: ingen funktionskontext i aktuellt sammanhang"
-#: variables.c:2247
-#, fuzzy, c-format
+#: variables.c:2217
+#, c-format
msgid "%s: variable may not be assigned value"
-msgstr "%s: det går inte att tilldela fb till variabel"
+msgstr "%s: variabeln får inte tilldelas ett värde"
-#: variables.c:3600
+#: variables.c:3554
msgid "all_local_variables: no function context at current scope"
msgstr "all_local_variables: ingen funktionskontext i aktuellt sammanhang"
-#: variables.c:3845
+#: variables.c:3799
#, c-format
msgid "%s has null exportstr"
msgstr "%s har tom exportstr"
-#: variables.c:3850 variables.c:3859
+#: variables.c:3804 variables.c:3813
#, c-format
msgid "invalid character %d in exportstr for %s"
msgstr "ogiltigt tecken %d i exportstr för %s"
-#: variables.c:3865
+#: variables.c:3819
#, c-format
msgid "no `=' in exportstr for %s"
msgstr "inget \"=\" i exportstr för %s"
-#: variables.c:4298
+#: variables.c:4252
msgid "pop_var_context: head of shell_variables not a function context"
-msgstr ""
-"pop_var_context: huvudet på shell_variables är inte en funktionskontext"
+msgstr "pop_var_context: huvudet på shell_variables är inte en funktionskontext"
-#: variables.c:4311
+#: variables.c:4265
msgid "pop_var_context: no global_variables context"
msgstr "pop_var_context: ingen kontext global_variables"
-#: variables.c:4385
+#: variables.c:4339
msgid "pop_scope: head of shell_variables not a temporary environment scope"
-msgstr ""
-"pop_scope: huvudet på shell_variables är inte en temporär omgivningsräckvidd"
+msgstr "pop_scope: huvudet på shell_variables är inte en temporär omgivningsräckvidd"
-#: variables.c:5211
+#: variables.c:5165
#, c-format
msgid "%s: %s: cannot open as FILE"
msgstr "%s: %s: går inte att öppna som FILE"
-#: variables.c:5216
+#: variables.c:5170
#, c-format
msgid "%s: %s: invalid value for trace file descriptor"
msgstr "%s: %s: ogiltigt värde för spårningsfilbeskrivare"
-#: variables.c:5261
-#, fuzzy, c-format
+#: variables.c:5215
+#, c-format
msgid "%s: %s: compatibility value out of range"
-msgstr "%s: %s utanför giltigt intervall"
+msgstr "%s: %s: kompatibilitetsvärde utanför giltigt intervall"
-#: version.c:46
-#, fuzzy
-msgid "Copyright (C) 2013 Free Software Foundation, Inc."
-msgstr "Copyright © 2011 Free Software Foundation, Inc."
+#: version.c:46 version2.c:46
+msgid "Copyright (C) 2012 Free Software Foundation, Inc."
+msgstr "Copyright © 2012 Free Software Foundation, Inc."
#: version.c:47 version2.c:47
-msgid ""
-"License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl."
-"html>\n"
-msgstr ""
-"Licens GPLv3+: GNU GPL version 3 eller senare <http://gnu.org/licenses/gpl."
-"html>\n"
+msgid "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\n"
+msgstr "Licens GPLv3+: GNU GPL version 3 eller senare <http://gnu.org/licenses/gpl.html>\n"
#: version.c:86 version2.c:86
#, c-format
msgstr "GNU bash, version %s (%s)\n"
#: version.c:91 version2.c:91
-#, fuzzy
msgid "This is free software; you are free to change and redistribute it."
-msgstr ""
-"Detta är fri programvara, det får fritt ändra och vidaredistribuera den.\n"
+msgstr "Detta är fri programvara, det får fritt ändra och vidaredistribuera den."
#: version.c:92 version2.c:92
-#, fuzzy
msgid "There is NO WARRANTY, to the extent permitted by law."
-msgstr "Det finns INGEN GARANTI, så långt lagen tillåter.\n"
-
-#: version2.c:46
-#, fuzzy
-msgid "Copyright (C) 2012 Free Software Foundation, Inc."
-msgstr "Copyright © 2011 Free Software Foundation, Inc."
+msgstr "Det finns INGEN GARANTI, så långt lagen tillåter."
#: xmalloc.c:91
#, c-format
msgstr "unalias [-a] namn [namn ...]"
#: builtins.c:51
-#, fuzzy
-msgid ""
-"bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-"
-"x keyseq:shell-command] [keyseq:readline-function or readline-command]"
-msgstr ""
-"bind [-lpvsPVS] [-m tangentkarta] [-f filenamn] [-q namn] [-u namn] [-r "
-"tangentsekv] [-x tangentsekv:skalkommando] [tangentsekv:readline-funktion "
-"eller readline-kommando]"
+msgid "bind [-lpsvPSVX] [-m keymap] [-f filename] [-q name] [-u name] [-r keyseq] [-x keyseq:shell-command] [keyseq:readline-function or readline-command]"
+msgstr "bind [-lpvsPVSX] [-m tangentkarta] [-f filenamn] [-q namn] [-u namn] [-r tangentsekv] [-x tangentsekv:skalkommando] [tangentsekv:readline-funktion eller readline-kommando]"
#: builtins.c:54
msgid "break [n]"
msgstr "command [-pVv] kommando [arg ...]"
#: builtins.c:76
-#, fuzzy
msgid "declare [-aAfFgilnrtux] [-p] [name[=value] ...]"
-msgstr "declare [-aAfFgilrtux] [-p] [namn[=värde] ...]"
+msgstr "declare [-aAfFgilnrtux] [-p] [namn[=värde] …]"
#: builtins.c:78
msgid "typeset [-aAfFgilrtux] [-p] name[=value] ..."
#: builtins.c:103
msgid "fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command]"
-msgstr ""
-"fc [-e rnamn] [-lnr] [första] [sista] eller fc -s [mnst=ers] [kommando]"
+msgstr "fc [-e rnamn] [-lnr] [första] [sista] eller fc -s [mnst=ers] [kommando]"
#: builtins.c:107
msgid "fg [job_spec]"
msgstr "help [-dms] [mönster ...]"
#: builtins.c:121
-msgid ""
-"history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg "
-"[arg...]"
-msgstr ""
-"history [-c] [-d avstånd] [n] eller history -anrw [filnamn] eller history -"
-"ps arg [arg...]"
+msgid "history [-c] [-d offset] [n] or history -anrw [filename] or history -ps arg [arg...]"
+msgstr "history [-c] [-d avstånd] [n] eller history -anrw [filnamn] eller history -ps arg [arg...]"
#: builtins.c:125
msgid "jobs [-lnprs] [jobspec ...] or jobs -x command [args]"
msgstr "disown [-h] [-ar] [jobbspec ...]"
#: builtins.c:132
-msgid ""
-"kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l "
-"[sigspec]"
-msgstr ""
-"kill [-s sigspec | -n signum | -sigspec] pid | jobbspec ... eller kill -l "
-"[sigspec]"
+msgid "kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]"
+msgstr "kill [-s sigspec | -n signum | -sigspec] pid | jobbspec ... eller kill -l [sigspec]"
#: builtins.c:134
msgid "let arg [arg ...]"
msgstr "let arg [arg ...]"
#: builtins.c:136
-msgid ""
-"read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p "
-"prompt] [-t timeout] [-u fd] [name ...]"
-msgstr ""
-"read [-ers] [-a vektor] [-d avgr] [-i text] [-n ntkn] [-N ntkn] [-p prompt] "
-"[-t tidgräns] [-u fb] [namn ...]"
+msgid "read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]"
+msgstr "read [-ers] [-a vektor] [-d avgr] [-i text] [-n ntkn] [-N ntkn] [-p prompt] [-t tidgräns] [-u fb] [namn ...]"
#: builtins.c:138
msgid "return [n]"
msgstr "set [-abefhkmnptuvxBCHP] [-o flaggnamn] [--] [arg ...]"
#: builtins.c:142
-#, fuzzy
msgid "unset [-f] [-v] [-n] [name ...]"
-msgstr "unset [-f] [-v] [namn ...]"
+msgstr "unset [-f] [-v] [-n] [namn …]"
#: builtins.c:144
msgid "export [-fn] [name[=value] ...] or export -p"
msgstr "type [-afptP] namn [namn ...]"
#: builtins.c:169
-#, fuzzy
msgid "ulimit [-SHabcdefilmnpqrstuvxT] [limit]"
-msgstr "ulimit [-SHacdefilmnpqrstuvx] [gräns]"
+msgstr "ulimit [-SHabcdefilmnpqrstuvxT] [gräns]"
#: builtins.c:172
msgid "umask [-p] [-S] [mode]"
msgstr "umask [-p] [-S] [rättigheter]"
#: builtins.c:175
-#, fuzzy
msgid "wait [-n] [id ...]"
-msgstr "wait [id]"
+msgstr "wait [-n] [id …]"
#: builtins.c:179
-#, fuzzy
msgid "wait [pid ...]"
-msgstr "wait [id]"
+msgstr "wait [pid …]"
#: builtins.c:182
msgid "for NAME [in WORDS ... ] ; do COMMANDS; done"
msgstr "case ORD in [MÖNSTER [| MÖNSTER]...) KOMMANDON ;;]... esac"
#: builtins.c:192
-msgid ""
-"if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else "
-"COMMANDS; ] fi"
-msgstr ""
-"if KOMMANDON; then KOMMANDON; [ elif KOMMANDON; then KOMMANDON; ]... [ else "
-"KOMMANDON; ] fi"
+msgid "if COMMANDS; then COMMANDS; [ elif COMMANDS; then COMMANDS; ]... [ else COMMANDS; ] fi"
+msgstr "if KOMMANDON; then KOMMANDON; [ elif KOMMANDON; then KOMMANDON; ]... [ else KOMMANDON; ] fi"
#: builtins.c:194
msgid "while COMMANDS; do COMMANDS; done"
msgstr "printf [-v var] format [argument]"
#: builtins.c:229
-msgid ""
-"complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-"
-"W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S "
-"suffix] [name ...]"
-msgstr ""
-"complete [-abcdefgjksuv] [-pr] [-DE] [-o flagga] [-A åtgärd] [-G globmnst] [-"
-"W ordlista] [-F funktion] [-C kommando] [-X filtermnst] [-P prefix] [-S "
-"suffix] [namn ...]"
+msgid "complete [-abcdefgjksuv] [-pr] [-DE] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [name ...]"
+msgstr "complete [-abcdefgjksuv] [-pr] [-DE] [-o flagga] [-A åtgärd] [-G globmnst] [-W ordlista] [-F funktion] [-C kommando] [-X filtermnst] [-P prefix] [-S suffix] [namn ...]"
#: builtins.c:233
-msgid ""
-"compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] "
-"[-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]"
-msgstr ""
-"compgen [-abcdefgjksuv] [-o flagga] [-A åtgärd] [-G globmnst] [-W "
-"ordlista] [-F funktion] [-C kommando] [-X filtermnst] [-P prefix] [-S "
-"suffix] [ord]"
+msgid "compgen [-abcdefgjksuv] [-o option] [-A action] [-G globpat] [-W wordlist] [-F function] [-C command] [-X filterpat] [-P prefix] [-S suffix] [word]"
+msgstr "compgen [-abcdefgjksuv] [-o flagga] [-A åtgärd] [-G globmnst] [-W ordlista] [-F funktion] [-C kommando] [-X filtermnst] [-P prefix] [-S suffix] [ord]"
#: builtins.c:237
msgid "compopt [-o|+o option] [-DE] [name ...]"
msgstr "compopt [-o|+o flagga] [-DE] [namn ...]"
#: builtins.c:240
-msgid ""
-"mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c "
-"quantum] [array]"
-msgstr ""
-"mapfile [-n antal] [-O start] [-s antal] [-t] [-u fb] [-C återanrop] [-c "
-"kvanta] [vektor]"
+msgid "mapfile [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]"
+msgstr "mapfile [-n antal] [-O start] [-s antal] [-t] [-u fb] [-C återanrop] [-c kvanta] [vektor]"
#: builtins.c:242
-msgid ""
-"readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c "
-"quantum] [array]"
-msgstr ""
-"readarray [-n antal] [-O start] [-s antal] [-t] [-u fb] [-C återanrop] [-c "
-"kvanta] [vektor]"
+msgid "readarray [-n count] [-O origin] [-s count] [-t] [-u fd] [-C callback] [-c quantum] [array]"
+msgstr "readarray [-n antal] [-O start] [-s antal] [-t] [-u fb] [-C återanrop] [-c kvanta] [vektor]"
#: builtins.c:254
msgid ""
" -p\tPrint all defined aliases in a reusable format\n"
" \n"
" Exit Status:\n"
-" alias returns true unless a NAME is supplied for which no alias has "
-"been\n"
+" alias returns true unless a NAME is supplied for which no alias has been\n"
" defined."
msgstr ""
"Definiera eller visa alias.\n"
" \n"
-" Utan argumen skriver \"alias\" listan på alias på den återanvändbara "
-"formen\n"
+" Utan argumen skriver \"alias\" listan på alias på den återanvändbara formen\n"
" \"alias NAMN=VÄRDE\" på standard ut.\n"
" \n"
" Annars är ett alias definierat för varje NAMN vars VÄRDE är angivet.\n"
" Returnerar framgång om inte ett NAMN inte är ett existerande alias."
#: builtins.c:289
-#, fuzzy
msgid ""
"Set Readline key bindings and variables.\n"
" \n"
" Options:\n"
" -m keymap Use KEYMAP as the keymap for the duration of this\n"
" command. Acceptable keymap names are emacs,\n"
-" emacs-standard, emacs-meta, emacs-ctlx, vi, vi-"
-"move,\n"
+" emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,\n"
" vi-command, and vi-insert.\n"
" -l List names of functions.\n"
" -P List function names and bindings.\n"
" -p List functions and bindings in a form that can be\n"
" reused as input.\n"
-" -S List key sequences that invoke macros and their "
-"values\n"
-" -s List key sequences that invoke macros and their "
-"values\n"
+" -S List key sequences that invoke macros and their values\n"
+" -s List key sequences that invoke macros and their values\n"
" in a form that can be reused as input.\n"
" -V List variable names and values\n"
" -v List variable names and values in a form that can\n"
" be reused as input.\n"
" -q function-name Query about which keys invoke the named function.\n"
-" -u function-name Unbind all keys which are bound to the named "
-"function.\n"
+" -u function-name Unbind all keys which are bound to the named function.\n"
" -r keyseq Remove the binding for KEYSEQ.\n"
" -f filename Read key bindings from FILENAME.\n"
" -x keyseq:shell-command\tCause SHELL-COMMAND to be executed when\n"
msgstr ""
"Sätt Readline-tangentbindningar och -variabler.\n"
" \n"
-" Bind en tangentsekvens till en Readline-funktion eller -makro, eller "
-"sätt\n"
+" Bind en tangentsekvens till en Readline-funktion eller -makro, eller sätt\n"
" en Readline-variabel. Syntaxen för argument vid sidan om flaggor är\n"
-" densamma som den i ~/.inputrc, men måste skickas som ett ensamt "
-"argument:\n"
+" densamma som den i ~/.inputrc, men måste skickas som ett ensamt argument:\n"
" t.ex., bind '\"\\C-x\\C-r\": re-read-init-file'.\n"
" \n"
" Flaggor:\n"
" -m tangentkarta Använt TANGENTKARTA som tangentkarta under detta\n"
" kommando. Acceptabla tangentkartenamn är emacs,\n"
-" emacs-standard, emacs-meta, emacs-ctlx, vi, vi-"
-"move,\n"
+" emacs-standard, emacs-meta, emacs-ctlx, vi, vi-move,\n"
" vi-command och vi-insert.\n"
" -l Lista namnen på funktioner.\n"
" -P List funktionsnamn och bindningar.\n"
" -p List funktioner och bindningar på ett sätt som kan\n"
" återanvändas som indata.\n"
-" -S Lista tangentsekvenser som anropar makron och "
-"deras\n"
+" -S Lista tangentsekvenser som anropar makron och deras\n"
" värden.\n"
-" -s Lista tangentskevenser som anropar makron och "
-"deras\n"
-" värden på ett sätt som kan återanvändas som "
-"indata.\n"
+" -s Lista tangentskevenser som anropar makron och deras\n"
+" värden på ett sätt som kan återanvändas som indata.\n"
" -V Lista variabelnamn och värden\n"
" -v Lista variabelnamn och värden på ett sätt som kan\n"
" återanvändas som indata.\n"
-" -q funktionsnamn Fråga efter vilka tangenter som anroper den "
-"namngivna\n"
+" -q funktionsnamn Fråga efter vilka tangenter som anroper den namngivna\n"
" funktionen\n"
" -u funktionsnamn Tag bort alla tangenter som är bundna till den\n"
" namngivna funktionen.\n"
" -r tangentsekv Ta bort bindningen för TANGENTSEKV.\n"
" -f filnamn Läs tangentbindningar från FILNAMN.\n"
-" -x tangentsekv:skalkommando Görs så att SKALKOMMANDO körs när\n"
+" -x tangentsekv:skalkommando Gör så att SKALKOMMANDO körs när\n"
" \t\t\t\t TANGENTSEKV skrivs.\n"
+" -X\t\t Lista tangentsekvenser bundna med -x och tillhörande\n"
+" kommandon på ett format som kan återanvändas som\n"
+" indata.\n"
" \n"
" Slutstatus:\n"
" bind returnerar 0 om inte en okänd flagga ges eller ett fel inträffar."
msgstr ""
"Återuppta for-, while eller until-slinga.\n"
" \n"
-" Återuppta nästa iteration i den omslutande FOR-, WHILE- eller UNTIL-"
-"slingan.\n"
+" Återuppta nästa iteration i den omslutande FOR-, WHILE- eller UNTIL-slingan.\n"
" Om N anges, återuppta den N:e omslutande slingan.\n"
" \n"
" Slutstatus:\n"
" \n"
" Execute SHELL-BUILTIN with arguments ARGs without performing command\n"
" lookup. This is useful when you wish to reimplement a shell builtin\n"
-" as a shell function, but need to execute the builtin within the "
-"function.\n"
+" as a shell function, but need to execute the builtin within the function.\n"
" \n"
" Exit Status:\n"
" Returns the exit status of SHELL-BUILTIN, or false if SHELL-BUILTIN is\n"
msgstr ""
"Exekvera en i skalet inbyggd funktion.\n"
" \n"
-" Exekvera SKALINBYGGD med argument ARG utan att utföra "
-"kommandouppslagning.\n"
+" Exekvera SKALINBYGGD med argument ARG utan att utföra kommandouppslagning.\n"
" Detta är användbart när du vill implementera om en inbyggd funktion i\n"
" skalet som en skalfunktion, men behöver köra den inbyggda funktionen i\n"
" skalfunktionen.\n"
" \n"
" Slutstatus:\n"
-" Returnerar slutstatus från SKALINBYGGD, eller falkst om SKALINBYGGD "
-"inte\n"
+" Returnerar slutstatus från SKALINBYGGD, eller falkst om SKALINBYGGD inte\n"
" är inbyggd i skalet."
#: builtins.c:367
" ogiltigt."
#: builtins.c:385
-#, fuzzy
msgid ""
"Change the shell working directory.\n"
" \n"
-" Change the current directory to DIR. The default DIR is the value of "
-"the\n"
+" Change the current directory to DIR. The default DIR is the value of the\n"
" HOME shell variable.\n"
" \n"
-" The variable CDPATH defines the search path for the directory "
-"containing\n"
-" DIR. Alternative directory names in CDPATH are separated by a colon "
-"(:).\n"
-" A null directory name is the same as the current directory. If DIR "
-"begins\n"
+" The variable CDPATH defines the search path for the directory containing\n"
+" DIR. Alternative directory names in CDPATH are separated by a colon (:).\n"
+" A null directory name is the same as the current directory. If DIR begins\n"
" with a slash (/), then CDPATH is not used.\n"
" \n"
-" If the directory is not found, and the shell option `cdable_vars' is "
-"set,\n"
-" the word is assumed to be a variable name. If that variable has a "
-"value,\n"
+" If the directory is not found, and the shell option `cdable_vars' is set,\n"
+" the word is assumed to be a variable name. If that variable has a value,\n"
" its value is used for DIR.\n"
" \n"
" Options:\n"
" \tcannot be determined successfully, exit with a non-zero status\n"
" \n"
" The default is to follow symbolic links, as if `-L' were specified.\n"
-" `..' is processed by removing the immediately previous pathname "
-"component\n"
+" `..' is processed by removing the immediately previous pathname component\n"
" back to a slash or the beginning of DIR.\n"
" \n"
" Exit Status:\n"
-" Returns 0 if the directory is changed, and if $PWD is set successfully "
-"when\n"
+" Returns 0 if the directory is changed, and if $PWD is set successfully when\n"
" -P is used; non-zero otherwise."
msgstr ""
"Ändra skalets arbetskatalog.\n"
" katalognamn är detsamma som aktuell katalog. Om KAT börjar med ett\n"
" snedstreck (/) används inte CDPATH.\n"
" \n"
-" Om katalogen inte kan hittas, och skalvariabeln \"cdable_vars\" är "
-"satt,\n"
+" Om katalogen inte kan hittas, och skalvariabeln ”cdable_vars” är satt,\n"
" antas ordet vara ett variabelnamn. Om den variabeln har ett värde\n"
" används dess värde för KAT.\n"
" \n"
" Flaggor:\n"
-" -L\tframtvinga att symboliska länkar följs\n"
+" -L\tframtvinga att symboliska länkar följs: lös upp symboliska\n"
+" \tKAT efter behandling av instanser av ”..”\n"
" -P\tanvänd den fysiska katalogstrukturen utan att följa\n"
-" \tsymboliska länkar\n"
+" \tsymboliska länkar: lös upp symboliska länkar i KAT före behandling av\n"
+" \t”..”\n"
" -e\tom flaggan -P ges, och det inte går att avgöra den aktuella\n"
" \tkatalogen, returnera då med status skild från noll\n"
" \n"
-" Standardvärde är att följa symboliska längar, som om \"-L\" vore "
-"angivet.\n"
+" Standardvärde är att följa symboliska längar, som om ”-L” vore angivet.\n"
+" ”..” behandlas genom att ta bort den omedelbart föregående\n"
+" sökvägskomponenten tillbaka till ett snedstreck eller början av KAT\n"
" \n"
" Slutstatus:\n"
" Returnerar 0 om katalogen är ändrad, och om $PWD satts korrekt om -P\n"
" Som standard beter sig \"pwd\" som om \"-L\" vore angivet.\n"
" \n"
" Slutstatus:\n"
-" Returnerar 0 om inte en ogiltig flagga anges eller den aktuella "
-"katalogen\n"
+" Returnerar 0 om inte en ogiltig flagga anges eller den aktuella katalogen\n"
" inte kan läsas."
#: builtins.c:437
"Execute a simple command or display information about commands.\n"
" \n"
" Runs COMMAND with ARGS suppressing shell function lookup, or display\n"
-" information about the specified COMMANDs. Can be used to invoke "
-"commands\n"
+" information about the specified COMMANDs. Can be used to invoke commands\n"
" on disk when a function with the same name exists.\n"
" \n"
" Options:\n"
" -V\tskriv en mer utförlig beskrivning om varje KOMMANDO\n"
" \n"
" Slutstatus:\n"
-" Returnerar slutstatus från KOMMANDO, eller misslyckande om KOMMANDO "
-"inte\n"
+" Returnerar slutstatus från KOMMANDO, eller misslyckande om KOMMANDO inte\n"
" finns."
#: builtins.c:485
-#, fuzzy
msgid ""
"Set variable values and attributes.\n"
" \n"
" Variables with the integer attribute have arithmetic evaluation (see\n"
" the `let' command) performed when the variable is assigned a value.\n"
" \n"
-" When used in a function, `declare' makes NAMEs local, as with the "
-"`local'\n"
+" When used in a function, `declare' makes NAMEs local, as with the `local'\n"
" command. The `-g' option suppresses this behavior.\n"
" \n"
" Exit Status:\n"
" -A\tför att göra NAMN till associativa vektorer (om det stöds)\n"
" -i\tför att ge NAMN attributet \"heltal\"\n"
" -l\tför att konvertera NAMN till gemena vid tilldelning\n"
+" -n\tgör NAMN till en referens till variablen som namnges som värde\n"
" -r\tför att göra NAMN endast läsbart\n"
" -t\tför att ge NAMN attributet \"spåra\"\n"
" -u\tför att konvertera NAMN till versaler vid tilldelning\n"
" För variabler med attributet heltal utförs atitmetisk beräkning (se\n"
" kommandot \"let\") när variabeln tilldelas ett värde.\n"
" \n"
-" Vid användning i en funktion gör \"declare\" NAMN lokala, som med "
-"kommandot\n"
+" Vid användning i en funktion gör \"declare\" NAMN lokala, som med kommandot\n"
" \"local\". Flaggan \"-g\" åsidosätter detta beteende.\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte en ogiltig flagga ges eller ett fel "
-"inträffar."
+" Returnerar framgång om inte en ogiltig flagga ges eller ett fel vid\n"
+" variabeltilldelning inträffar."
#: builtins.c:525
msgid ""
" Föråldrat. Se \"help declare\"."
#: builtins.c:533
-#, fuzzy
msgid ""
"Define local variables.\n"
" \n"
"Definiera lokala variabler.\n"
" \n"
" Skapa en lokal variabel kallad NAMN, och ge den VÄRDE. FLAGGA kan\n"
-" vara alla flaggor som accepteras av \"declare\".\n"
+" vara alla flaggor som accepteras av ”declare”.\n"
" \n"
-" Lokala variabler kan endast användas i en funktion; de är synliga "
-"endast\n"
+" Lokala variabler kan endast användas i en funktion; de är synliga endast\n"
" för funktionen de definieras i och dess barn.\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte en ogiltig flagga ges, ett fel inträffar\n"
-" eller skalet inte exekverar en funktion."
+" Returnerar framgång om inte en ogiltig flagga ges, ett fel vid\n"
+" variabeltilldelning inträffar eller skalet inte exekverar en funktion."
#: builtins.c:550
-#, fuzzy
msgid ""
"Write arguments to the standard output.\n"
" \n"
-" Display the ARGs, separated by a single space character and followed by "
-"a\n"
+" Display the ARGs, separated by a single space character and followed by a\n"
" newline, on the standard output.\n"
" \n"
" Options:\n"
msgstr ""
"Skriv argument på standard ut.\n"
" \n"
-" Visa ARGumenten på standard ut följt av en nyrad.\n"
+" Visa ARGumenten, separerade av ensamma blanktecken och följda av en\n"
+" nyrad, på standard ut.\n"
" \n"
" Flaggor:\n"
" -n\tlägg inte till en nyrad\n"
" -e\taktivera tolkning av nedanstående specialsekvenser\n"
" -E\tundertryck uttryckligen tolkning av specialsekvenser\n"
" \n"
-" \"echo\" tolkar följande bakstrecksekvenser:\n"
+" ”echo” tolkar följande bakstrecksekvenser:\n"
" \\a\talarm (klocka)\n"
" \\b\tbacksteg\n"
" \\c\tundertryck följande utdata\n"
" \\e\tescape-tecknet\n"
+" \\E\tescape-tecknet\n"
" \\f\tsidmatning\n"
" \\n\tnyrad\n"
" \\r\tvagnretur\n"
msgid ""
"Execute arguments as a shell command.\n"
" \n"
-" Combine ARGs into a single string, use the result as input to the "
-"shell,\n"
+" Combine ARGs into a single string, use the result as input to the shell,\n"
" and execute the resulting commands.\n"
" \n"
" Exit Status:\n"
msgstr ""
"Exekvera argument som ett skalkommando.\n"
" \n"
-" Kombinera ARGument till en enda sträng, och använd resultatet som "
-"indata\n"
+" Kombinera ARGument till en enda sträng, och använd resultatet som indata\n"
" till skalet och exekvera de resulterande kommandona.\n"
" \n"
" Slutstatus:\n"
"Replace the shell with the given command.\n"
" \n"
" Execute COMMAND, replacing this shell with the specified program.\n"
-" ARGUMENTS become the arguments to COMMAND. If COMMAND is not "
-"specified,\n"
+" ARGUMENTS become the arguments to COMMAND. If COMMAND is not specified,\n"
" any redirections take effect in the current shell.\n"
" \n"
" Options:\n"
" -c\t\texecute COMMAND with an empty environment\n"
" -l\t\tplace a dash in the zeroth argument to COMMAND\n"
" \n"
-" If the command cannot be executed, a non-interactive shell exits, "
-"unless\n"
+" If the command cannot be executed, a non-interactive shell exits, unless\n"
" the shell option `execfail' is set.\n"
" \n"
" Exit Status:\n"
-" Returns success unless COMMAND is not found or a redirection error "
-"occurs."
+" Returns success unless COMMAND is not found or a redirection error occurs."
msgstr ""
"Ersätt skalet med det givna kommandot.\n"
" \n"
-" Exekvera KOMMANDO genom att ersätta detta skal med det angivna "
-"programmet.\n"
+" Exekvera KOMMANDO genom att ersätta detta skal med det angivna programmet.\n"
" ARGUMENT blir argument till KOMMANDO. Om KOMMANDO inte anges kommer\n"
" eventuella omdirigeringar att gälla för det aktuella skalet.\n"
" \n"
msgid ""
"Exit a login shell.\n"
" \n"
-" Exits a login shell with exit status N. Returns an error if not "
-"executed\n"
+" Exits a login shell with exit status N. Returns an error if not executed\n"
" in a login shell."
msgstr ""
"Avsluta ett inloggningsskal.\n"
msgid ""
"Display or execute commands from the history list.\n"
" \n"
-" fc is used to list or edit and re-execute commands from the history "
-"list.\n"
+" fc is used to list or edit and re-execute commands from the history list.\n"
" FIRST and LAST can be numbers specifying the range, or FIRST can be a\n"
" string, which means the most recent command beginning with that\n"
" string.\n"
" \n"
" Options:\n"
-" -e ENAME\tselect which editor to use. Default is FCEDIT, then "
-"EDITOR,\n"
+" -e ENAME\tselect which editor to use. Default is FCEDIT, then EDITOR,\n"
" \t\tthen vi\n"
" -l \tlist lines instead of editing\n"
" -n\tomit line numbers when listing\n"
" the last command.\n"
" \n"
" Exit Status:\n"
-" Returns success or status of executed command; non-zero if an error "
-"occurs."
+" Returns success or status of executed command; non-zero if an error occurs."
msgstr ""
"Visa eller kör kommandon från historielistan.\n"
" \n"
" Med formatet \"fc -s [mnst=ers ...] [kommando]\" körs KOMMANDO om efter\n"
" att substitutionen GAMMALT=NYTT har utförts.\n"
" \n"
-" Ett användbart alias att använda med detta är r=\"fc -s\", så att "
-"skriva\n"
-" \"r cc\" kör senaste kommandot som börjar med \"cc\" och att skriva \"r"
-"\" kör\n"
+" Ett användbart alias att använda med detta är r=\"fc -s\", så att skriva\n"
+" \"r cc\" kör senaste kommandot som börjar med \"cc\" och att skriva \"r\" kör\n"
" om senaste kommandot.\n"
" \n"
" Slutstatus:\n"
msgid ""
"Move jobs to the background.\n"
" \n"
-" Place the jobs identified by each JOB_SPEC in the background, as if "
-"they\n"
-" had been started with `&'. If JOB_SPEC is not present, the shell's "
-"notion\n"
+" Place the jobs identified by each JOB_SPEC in the background, as if they\n"
+" had been started with `&'. If JOB_SPEC is not present, the shell's notion\n"
" of the current job is used.\n"
" \n"
" Exit Status:\n"
msgstr ""
"Flytta jobb till bakgrunden.\n"
" \n"
-" Placera jobben som idintifieras av varje JOBBSPEC i bakgrunden som om "
-"de\n"
-" hade startats med \"&\". Om ingen JOBBSPEC finns används skalets "
-"begrepp\n"
+" Placera jobben som idintifieras av varje JOBBSPEC i bakgrunden som om de\n"
+" hade startats med \"&\". Om ingen JOBBSPEC finns används skalets begrepp\n"
" om det aktuella jobbet.\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte jobbstyrning inte är aktiverat eller ett "
-"fel\n"
+" Returnerar framgång om inte jobbstyrning inte är aktiverat eller ett fel\n"
" inträffar."
#: builtins.c:782
-#, fuzzy
msgid ""
"Remember or display program locations.\n"
" \n"
" Determine and remember the full pathname of each command NAME. If\n"
-" no arguments are given, information about remembered commands is "
-"displayed.\n"
+" no arguments are given, information about remembered commands is displayed.\n"
" \n"
" Options:\n"
" -d\t\tforget the remembered location of each NAME\n"
" -l\t\tdisplay in a format that may be reused as input\n"
-" -p pathname\tuse PATHNAME as the full pathname of NAME\n"
+" -p pathname\tuse PATHNAME is the full pathname of NAME\n"
" -r\t\tforget all remembered locations\n"
" -t\t\tprint the remembered location of each NAME, preceding\n"
" \t\teach location with the corresponding NAME if multiple\n"
"Kom ihåg eller visa programlägen.\n"
" \n"
" Bestäm och kom ihåg den fullständiga sökvägen till varje kommando NAMN.\n"
-" Om inget argument ges visas information om kommandon som finns i "
-"minnet.\n"
+" Om inget argument ges visas information om kommandon som finns i minnet.\n"
" \n"
" Flaggor:\n"
" -d\t\tglöm platsen i minnet för varje NAMN\n"
" PATTERN\tPattern specifiying a help topic\n"
" \n"
" Exit Status:\n"
-" Returns success unless PATTERN is not found or an invalid option is "
-"given."
+" Returns success unless PATTERN is not found or an invalid option is given."
msgstr ""
"Visa information om inbyggda kommandon.\n"
" \n"
" Visar korta sammanfattningar om inbyggda kommandon. Om MÖNSTER anges\n"
-" ges detaljerad hjälp om alla kommandon som matchar MÖNSTER, annars "
-"skrivs\n"
+" ges detaljerad hjälp om alla kommandon som matchar MÖNSTER, annars skrivs\n"
" listan med hjälpämnen.\n"
" \n"
" Flaggor:\n"
" MÖNSTER\tMönster som anger hjälpämnen\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte MÖNSTER inte finns eller en ogiltig flagga "
-"ges."
+" Returnerar framgång om inte MÖNSTER inte finns eller en ogiltig flagga ges."
#: builtins.c:831
msgid ""
" \n"
" If the $HISTTIMEFORMAT variable is set and not null, its value is used\n"
" as a format string for strftime(3) to print the time stamp associated\n"
-" with each displayed history entry. No time stamps are printed "
-"otherwise.\n"
+" with each displayed history entry. No time stamps are printed otherwise.\n"
" \n"
" Exit Status:\n"
" Returns success unless an invalid option is given or an error occurs."
" \tatt lagra det i historielistan\n"
" -s\tlägg till ARG till historielistan som en ensam post\n"
" \n"
-" Om FILENAMN anges används det som historiefil. Annars, om $HISTFILE "
-"har\n"
+" Om FILENAMN anges används det som historiefil. Annars, om $HISTFILE har\n"
" ett värde används det, annars ~/.bash_history.\n"
" \n"
-" Om variabeln $HISTTIMEFORMAT är satt och inte tom används dess värde "
-"som\n"
-" en formatsträng till strftime(3) för att skriva tidsstämplar "
-"tillhörande\n"
+" Om variabeln $HISTTIMEFORMAT är satt och inte tom används dess värde som\n"
+" en formatsträng till strftime(3) för att skriva tidsstämplar tillhörande\n"
" varje visad historiepost. Inga tidsstämplar skrivs annars.\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte en ogiltig flagga ges eller ett fel "
-"inträffar."
+" Returnerar framgång om inte en ogiltig flagga ges eller ett fel inträffar."
#: builtins.c:867
msgid ""
" i ARG har ersatts med process-id:t för det jobbets processgruppledare.\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte en ogiltig flagga ges eller ett fel "
-"inträffar.\n"
+" Returnerar framgång om inte en ogiltig flagga ges eller ett fel inträffar.\n"
" Om -x används returneras slutstatus från KOMMANDO."
#: builtins.c:894
msgstr ""
"Skicka en signal till ett jobb.\n"
" \n"
-" Skicka processerna som identifieras av PID eller JOBBSPEC signalerna "
-"som\n"
+" Skicka processerna som identifieras av PID eller JOBBSPEC signalerna som\n"
" namnges av SIGSPEC eller SIGNUM. Om varken SIGSPEC eller SIGNUM är\n"
" angivna antas SIGTERM.\n"
" \n"
" -l\tlista signalnamnen. Om argument följer \"-l\" antas de vara\n"
" \tsignalnummer som namn skall listas för\n"
" \n"
-" Kill är inbyggt i skalet av två skäl: det tillåter att jobb-id:n "
-"används\n"
-" istället för process-id:n, och det tillåter processer att dödas om "
-"gränsen\n"
+" Kill är inbyggt i skalet av två skäl: det tillåter att jobb-id:n används\n"
+" istället för process-id:n, och det tillåter processer att dödas om gränsen\n"
" för hur många processer du får skapa har nåtts.\n"
" \n"
" Slutstatus:\n"
" Evaluate each ARG as an arithmetic expression. Evaluation is done in\n"
" fixed-width integers with no check for overflow, though division by 0\n"
" is trapped and flagged as an error. The following list of operators is\n"
-" grouped into levels of equal-precedence operators. The levels are "
-"listed\n"
+" grouped into levels of equal-precedence operators. The levels are listed\n"
" in order of decreasing precedence.\n"
" \n"
" \tid++, id--\tvariable post-increment, post-decrement\n"
msgstr ""
"Evaluera aritmetiska uttryck.\n"
" \n"
-" Evaluera varje ARG som ett aritmetiskt uttryck. Evaluering görs i "
-"heltal\n"
+" Evaluera varje ARG som ett aritmetiskt uttryck. Evaluering görs i heltal\n"
" med fix bredd utan kontroll av spill, fast division med 0 fångas och\n"
" flaggas som ett fel. Följande lista över operatorer är grupperad i\n"
-" nivåer av operatorer med samma precedens. Nivåerna är listade i "
-"ordning\n"
+" nivåer av operatorer med samma precedens. Nivåerna är listade i ordning\n"
" med sjunkande precedens.\n"
" \n"
" \tid++, id--\tpostinkrementering av variabel, postdekrementering\n"
" uttryck. Variablerna behöver inte ha sina heltalsattribut påslagna för\n"
" att användas i ett uttryck.\n"
" \n"
-" Operatorer beräknas i precedensordning. Delutryck i parenteser "
-"beräknas\n"
+" Operatorer beräknas i precedensordning. Delutryck i parenteser beräknas\n"
" först och kan åsidosätta precedensreglerna ovan.\n"
" \n"
" Slutstatus:\n"
-" Om det sista ARG beräknas till 0, returnerar let 1; let returnerar 0 "
-"annars."
+" Om det sista ARG beräknas till 0, returnerar let 1; let returnerar 0 annars."
#: builtins.c:981
-#, fuzzy
msgid ""
"Read a line from the standard input and split it into fields.\n"
" \n"
" Reads a single line from the standard input, or from file descriptor FD\n"
-" if the -u option is supplied. The line is split into fields as with "
-"word\n"
+" if the -u option is supplied. The line is split into fields as with word\n"
" splitting, and the first word is assigned to the first NAME, the second\n"
" word to the second NAME, and so on, with any leftover words assigned to\n"
-" the last NAME. Only the characters found in $IFS are recognized as "
-"word\n"
+" the last NAME. Only the characters found in $IFS are recognized as word\n"
" delimiters.\n"
" \n"
-" If no NAMEs are supplied, the line read is stored in the REPLY "
-"variable.\n"
+" If no NAMEs are supplied, the line read is stored in the REPLY variable.\n"
" \n"
" Options:\n"
" -a array\tassign the words read to sequential indices of the array\n"
" -n nchars\treturn after reading NCHARS characters rather than waiting\n"
" \t\tfor a newline, but honor a delimiter if fewer than NCHARS\n"
" \t\tcharacters are read before the delimiter\n"
-" -N nchars\treturn only after reading exactly NCHARS characters, "
-"unless\n"
+" -N nchars\treturn only after reading exactly NCHARS characters, unless\n"
" \t\tEOF is encountered or read times out, ignoring any delimiter\n"
" -p prompt\toutput the string PROMPT without a trailing newline before\n"
" \t\tattempting to read\n"
" -r\t\tdo not allow backslashes to escape any characters\n"
" -s\t\tdo not echo input coming from a terminal\n"
-" -t timeout\ttime out and return failure if a complete line of input "
-"is\n"
+" -t timeout\ttime out and return failure if a complete line of input is\n"
" \t\tnot read within TIMEOUT seconds. The value of the TMOUT\n"
" \t\tvariable is the default timeout. TIMEOUT may be a\n"
" \t\tfractional number. If TIMEOUT is 0, read returns immediately,\n"
" -u fd\t\tread from file descriptor FD instead of the standard input\n"
" \n"
" Exit Status:\n"
-" The return code is zero, unless end-of-file is encountered, read times "
-"out\n"
-" (in which case it's greater than 128), a variable assignment error "
-"occurs,\n"
+" The return code is zero, unless end-of-file is encountered, read times out\n"
+" (in which case it's greater than 128), a variable assignment error occurs,\n"
" or an invalid file descriptor is supplied as the argument to -u."
msgstr ""
"Läs en rad från standard in och dela upp den i fält.\n"
" \n"
" Läser en ensam rad från standard in, eller från filbeskrivare FB om\n"
-" flaggan -u ges. Raden delas upp i fält som vid orduppdelning, och "
-"första\n"
-" ordet tilldelas det första NAMNet, andra ordet till det andra NAMNet, "
-"och\n"
+" flaggan -u ges. Raden delas upp i fält som vid orduppdelning, och första\n"
+" ordet tilldelas det första NAMNet, andra ordet till det andra NAMNet, och\n"
" så vidare, med eventuella återstående ord tilldelade till det sista\n"
" NAMNet. Endast tecknen som finns i $IFS används som ordavgränsare.\n"
" \n"
" Om inga NAMN anges, lagras den inlästa raden i variabeln REPLY.\n"
" \n"
" Flaggor:\n"
-" -a vektor\ttilldela de inlästa orden till sekvensiella index i "
-"vektor-\n"
+" -a vektor\ttilldela de inlästa orden till sekvensiella index i vektor-\n"
" \t\tvariabeln VEKTOR, med start från noll\n"
" -d avgr\tfortsätt tills det första tecknet i AVGR lästs, istället för\n"
" \t\tnyrad\n"
" -n ntkn\treturnera efter att ha läst NTKN tecken istället för att\n"
" \t\tvänta på en nyrad, men ta hänsyn till en avgränsare om färre\n"
" \t\tän NTKN tecken lästs före avgränsaren\n"
-" -N ntkn\treturnera endast efter att ha läst exakt NTKN tecken, om "
-"inte\n"
+" -N ntkn\treturnera endast efter att ha läst exakt NTKN tecken, om inte\n"
" \t\tfilslut påträffades eller tidsgränsen överskreds, ignorera\n"
" \t\talla avgränsare\n"
" -p prompt\tskriv ut strängen PROMPT utan en avslutande nyrad före\n"
" -t tidgräns\tsluta vänta och returnera misslyckande om inte en\n"
" \t\tkomplett rad lästs inom TIDSGRÄNS sekunder. Värdet på variabeln\n"
" \t\tTMOUT är standardvärdet på tidsgränsen. TIDSGRÄNS kan vara ett\n"
-" \t\tbråktal. Om TIDSGRÄNS är 0 returnerar read lyckad status bara\n"
+" \t\tdecimaltal. Om TIDSGRÄNS är 0 returnerar read direkt, utan\n"
+" att försöka läsa några data, och returnerar lyckad status bara\n"
"\t\tom det finns indata tillgängligt på den angivna filbeskrivaren.\n"
" Slutstatus är större än 128 om tidsgränsen överskrids\n"
" -u fb\t\tläs från filbeskrivare FB istället för standard in\n"
" \n"
" Slutstatus:\n"
" Returkoden är noll om inte filslut nås, läsningens tidsgräns överskrids\n"
-" eller en ogiltig filbeskrivare ges som argument till -u."
+" (då den är större än 128), ett fel vid variabeltilldelning inträffar eller\n"
+" en ogiltig filbeskrivare ges som argument till -u."
#: builtins.c:1026
msgid ""
" skript."
#: builtins.c:1039
-#, fuzzy
msgid ""
"Set or unset values of shell options and positional parameters.\n"
" \n"
" physical same as -P\n"
" pipefail the return value of a pipeline is the status of\n"
" the last command to exit with a non-zero status,\n"
-" or zero if no command exited with a non-zero "
-"status\n"
+" or zero if no command exited with a non-zero status\n"
" posix change the behavior of bash where the default\n"
" operation differs from the Posix standard to\n"
" match the standard\n"
" -e Avsluta omedelbart om ett kommando avslutar med nollskild status.\n"
" -f Avaktivera filnamnsgenerering (globbing).\n"
" -h Kom ihåg platsen för kommandon när de slås upp.\n"
-" -k Alla tilldelningsargument placeras i miljön för ett kommando, "
-"inte\n"
+" -k Alla tilldelningsargument placeras i miljön för ett kommando, inte\n"
" bara de som föregår kommandonamnet.\n"
" -m Jobbstyrning är aktiverat.\n"
" -n Läs kommandon men exekvera dem inte.\n"
" hashall samma som -h\n"
" histexpand samma som -H\n"
" history aktivera kommandohistoria\n"
-" ignoreeof skalet kommer inte avsluta vid läsning av "
-"filslut\n"
+" ignoreeof skalet kommer inte avsluta vid läsning av filslut\n"
" interactive-comments\n"
" tillåt kommentarer att förekomma i interaktiva\n"
" kommandon\n"
" xtrace samma som -x\n"
" -p Slås på när den verkliga och effektiva användar-id:n inte stämmer\n"
" överens. Avaktiverar bearbetning av $ENV-filen och import av\n"
-" skalfunktioner. Att slå av denna flagga får den effektiva uid "
-"och\n"
+" skalfunktioner. Att slå av denna flagga får den effektiva uid och\n"
" gid att sättas till den verkliga uid och gid.\n"
" -t Avsluta efter att ha läst och exekverat ett kommando.\n"
" -u Behandla osatta variabler som fel vid substitution.\n"
" -E Om satt ärvs ERR-fällan av skalfunktioner.\n"
" -H Aktivera historiesubstituion i !-stil. Denna flagga är på som\n"
" standard när skalet är interaktivt.\n"
-" -P Om satt följs inte symboliska länkar när kommandon såsom cd körs\n"
-" som ändrar aktuell katalog.\n"
+" -P Om satt löses inte symboliska länkar upp när kommandon såsom cd\n"
+" körs som ändrar aktuell katalog.\n"
" -T Om satt ärvs DEBUG-fällan av skalfunktioner.\n"
-" -- Tilldela eventuella återstående argument till "
-"positionsparametrar.\n"
+" -- Tilldela eventuella återstående argument till positionsparametrar.\n"
" Om det inte finns några återstående argument nollställs\n"
" positionsparametrarna.\n"
-" - Tilldela eventuella återstående argument till "
-"positionsparametrar.\n"
+" - Tilldela eventuella återstående argument till positionsparametrar.\n"
" Flaggorna -x och -v slås av.\n"
" \n"
-" Användning av + istället för - får dessa flaggor att slås av. "
-"Flaggorna\n"
+" Användning av + istället för - får dessa flaggor att slås av. Flaggorna\n"
" kan även användas vid uppstart av skalet. Den aktuella uppsättningen\n"
" flaggor finns i $-. De återstående n ARGumenten är positionsparametrar\n"
" och tilldelas, i ordning, till $1, $2, .. $n. Om inga ARGument ges\n"
" Returnerar framgång om inte en ogiltig flagga ges."
#: builtins.c:1124
-#, fuzzy
msgid ""
"Unset values and attributes of shell variables and functions.\n"
" \n"
" -n\ttreat each NAME as a name reference and unset the variable itself\n"
" \trather than the variable it references\n"
" \n"
-" Without options, unset first tries to unset a variable, and if that "
-"fails,\n"
+" Without options, unset first tries to unset a variable, and if that fails,\n"
" tries to unset a function.\n"
" \n"
" Some variables cannot be unset; also see `readonly'.\n"
" Flaggor:\n"
" -f\tbehandla varje NAMN som en skalfunktion\n"
" -v\tbehandla varje NAMN som en skalvariabel\n"
+" -n\tbehandla varje NAMN som en namnreferens tar bort värdet på\n"
+" \tvariabeln själv istället för variabeln den refererar\n"
" \n"
" Utan flaggor försöker unset först att ta bort en variabel, och, om det\n"
" misslyckas, försöker den ta bort en funktion.\n"
" \n"
-" Några variabler kan inte tas bort, se även \"readonly\".\n"
+" Några variabler kan inte tas bort, se även ”readonly”.\n"
" \n"
" Slutstatus:\n"
" Returnerar framgång om inte en ogiltig flagga ges eller NAMN endast är\n"
"Set export attribute for shell variables.\n"
" \n"
" Marks each NAME for automatic export to the environment of subsequently\n"
-" executed commands. If VALUE is supplied, assign VALUE before "
-"exporting.\n"
+" executed commands. If VALUE is supplied, assign VALUE before exporting.\n"
" \n"
" Options:\n"
" -f\trefer to shell functions\n"
" Returnerar framgång om inte en ogiltig flagga ges eller NAMN är ogiltigt."
#: builtins.c:1165
-#, fuzzy
msgid ""
"Mark shell variables as unchangeable.\n"
" \n"
" -a\trefer to indexed array variables\n"
" -A\trefer to associative array variables\n"
" -f\trefer to shell functions\n"
-" -p\tdisplay a list of all readonly variables or functions, depending "
-"on\n"
-" whether or not the -f option is given\n"
+" -p\tdisplay a list of all readonly variables and functions\n"
" \n"
" An argument of `--' disables further option processing.\n"
" \n"
" Slutstatus:\n"
" Returnerar framgång om inte en ogiltig flagga ges eller NAMN är ogiltigt."
-#: builtins.c:1187
+#: builtins.c:1186
msgid ""
"Shift positional parameters.\n"
" \n"
msgstr ""
"Skifta positionsparametrar.\n"
" \n"
-" Byt namn på positionsparametrarna $N+1,$N+2 ... till $1,$2 ... Om N "
-"inte\n"
+" Byt namn på positionsparametrarna $N+1,$N+2 ... till $1,$2 ... Om N inte\n"
" anges antas det vara 1.\n"
" \n"
" Slutstatus:\n"
" Returnerar framgång om inte N är negativt eller större än $#."
-#: builtins.c:1199 builtins.c:1214
+#: builtins.c:1198 builtins.c:1213
msgid ""
"Execute commands from a file in the current shell.\n"
" \n"
msgstr ""
"Exekvera kommandon från en fil i det aktuella skalet.\n"
" \n"
-" Läs och exekvera kommandon från FILNAMN i det aktuella skalet. "
-"Posterna\n"
+" Läs och exekvera kommandon från FILNAMN i det aktuella skalet. Posterna\n"
" i $PATH används för att hitta katalogen som innehåller FILNAMN. Om\n"
" något ARGUMENT ges blir de positionsparametrar när FILNAMN körs.\n"
" \n"
" Returnerar status på det sista kommandot som körs i FILNAMN, misslyckas\n"
" om FILNAMN inte kan läsas."
-#: builtins.c:1230
+#: builtins.c:1229
msgid ""
"Suspend shell execution.\n"
" \n"
" -f\tframtvinga suspendering, även om skalet är ett inloggningsskal\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte jobbstyrning inte är aktiverat eller ett "
-"fel\n"
+" Returnerar framgång om inte jobbstyrning inte är aktiverat eller ett fel\n"
" inträffar."
-#: builtins.c:1246
-#, fuzzy
+#: builtins.c:1245
msgid ""
"Evaluate conditional expression.\n"
" \n"
" -x FILE True if the file is executable by you.\n"
" -O FILE True if the file is effectively owned by you.\n"
" -G FILE True if the file is effectively owned by your group.\n"
-" -N FILE True if the file has been modified since it was last "
-"read.\n"
+" -N FILE True if the file has been modified since it was last read.\n"
" \n"
" FILE1 -nt FILE2 True if file1 is newer than file2 (according to\n"
" modification date).\n"
" STRING1 != STRING2\n"
" True if the strings are not equal.\n"
" STRING1 < STRING2\n"
-" True if STRING1 sorts before STRING2 "
-"lexicographically.\n"
+" True if STRING1 sorts before STRING2 lexicographically.\n"
" STRING1 > STRING2\n"
" True if STRING1 sorts after STRING2 lexicographically.\n"
" \n"
" \n"
" -o OPTION True if the shell option OPTION is enabled.\n"
" -v VAR\t True if the shell variable VAR is set\n"
-" -R VAR\t True if the shell variable VAR is set and is a name "
-"reference.\n"
+" -R VAR\t True if the shell variable VAR is set and is a name reference.\n"
" ! EXPR True if expr is false.\n"
" EXPR1 -a EXPR2 True if both expr1 AND expr2 are true.\n"
" EXPR1 -o EXPR2 True if either expr1 OR expr2 is true.\n"
" -g FIL Sant om filen är sätt-gruppid.\n"
" -h FIL Sant om filen är en symbolisk länk.\n"
" -L FIL Sant om filen är en symbolisk länk.\n"
-" -k FIL Sant om filen har \"fastbiten\" satt.\n"
+" -k FIL Sant om filen har ”fastbiten” satt.\n"
" -p FIL Sant om filen är ett namngivet rör.\n"
" -r FIL Sant om filen kan läsas av dig.\n"
" -s FIL Sant om filen finns och inte är tom.\n"
" \n"
" -o FLAGGA Sant om skalflaggan FLAGGA är aktiv.\n"
" -v VAR Sant om skalvariabeln VAR är satt.\n"
+" -R VAR Sant om skalvariabeln VAR är satt och är en namnreferens.\n"
" ! UTTR Sant om uttr är falskt.\n"
" UTTR1 -a UTTR2 Sant om både uttr1 OCH uttr2 är sanna.\n"
" UTTR1 -o UTTR2 Sant om antingen uttr1 ELLER uttr2 är sanna.\n"
" Returnerar framgång om UTTR beräknas till sant. Misslyckas ifall UTTR\n"
" beräknas till falskt eller ett ogiltigt argument ges."
-#: builtins.c:1327
+#: builtins.c:1326
msgid ""
"Evaluate conditional expression.\n"
" \n"
msgstr ""
"Beräkna villkorligt uttryck.\n"
" \n"
-" Detta är en synonym till det inbyggda \"test\", men det sista "
-"argumentet\n"
+" Detta är en synonym till det inbyggda \"test\", men det sista argumentet\n"
" måste vara en bokstavlig \"]\", för att matcha den inledande \"[\"."
-#: builtins.c:1336
+#: builtins.c:1335
msgid ""
"Display process times.\n"
" \n"
-" Prints the accumulated user and system times for the shell and all of "
-"its\n"
+" Prints the accumulated user and system times for the shell and all of its\n"
" child processes.\n"
" \n"
" Exit Status:\n"
msgstr ""
"Visa processtider.\n"
" \n"
-" Skriver ut den sammanlagda användar- och systemtiden för skalet och "
-"alla\n"
+" Skriver ut den sammanlagda användar- och systemtiden för skalet och alla\n"
" dess barnprocesser.\n"
" \n"
" Slutstatus:\n"
" Lyckas alltid."
-#: builtins.c:1348
+#: builtins.c:1347
msgid ""
"Trap signals and other events.\n"
" \n"
-" Defines and activates handlers to be run when the shell receives "
-"signals\n"
+" Defines and activates handlers to be run when the shell receives signals\n"
" or other conditions.\n"
" \n"
" ARG is a command to be read and executed when the shell receives the\n"
" value. If ARG is the null string each SIGNAL_SPEC is ignored by the\n"
" shell and by the commands it invokes.\n"
" \n"
-" If a SIGNAL_SPEC is EXIT (0) ARG is executed on exit from the shell. "
-"If\n"
-" a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command. "
-"If\n"
-" a SIGNAL_SPEC is RETURN, ARG is executed each time a shell function or "
-"a\n"
-" script run by the . or source builtins finishes executing. A "
-"SIGNAL_SPEC\n"
-" of ERR means to execute ARG each time a command's failure would cause "
-"the\n"
+" If a SIGNAL_SPEC is EXIT (0) ARG is executed on exit from the shell. If\n"
+" a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command. If\n"
+" a SIGNAL_SPEC is RETURN, ARG is executed each time a shell function or a\n"
+" script run by the . or source builtins finishes executing. A SIGNAL_SPEC\n"
+" of ERR means to execute ARG each time a command's failure would cause the\n"
" shell to exit when the -e option is enabled.\n"
" \n"
-" If no arguments are supplied, trap prints the list of commands "
-"associated\n"
+" If no arguments are supplied, trap prints the list of commands associated\n"
" with each signal.\n"
" \n"
" Options:\n"
" -l\tprint a list of signal names and their corresponding numbers\n"
" -p\tdisplay the trap commands associated with each SIGNAL_SPEC\n"
" \n"
-" Each SIGNAL_SPEC is either a signal name in <signal.h> or a signal "
-"number.\n"
+" Each SIGNAL_SPEC is either a signal name in <signal.h> or a signal number.\n"
" Signal names are case insensitive and the SIG prefix is optional. A\n"
" signal may be sent to the shell with \"kill -signal $$\".\n"
" \n"
" Exit Status:\n"
-" Returns success unless a SIGSPEC is invalid or an invalid option is "
-"given."
+" Returns success unless a SIGSPEC is invalid or an invalid option is given."
msgstr ""
"Fånga signaler och andra händelser.\n"
" \n"
" SIGNALSPEC ERR betyder att köra ARG varje gång ett kommandos felstatus\n"
" skulle fått skalet att avsluta om flaggan -e ovre satt.\n"
" \n"
-" Om inga argument ges skriver trap listan av kommandon som hör till "
-"varje\n"
+" Om inga argument ges skriver trap listan av kommandon som hör till varje\n"
" signal.\n"
" \n"
" Flaggor:\n"
" frivilligt. En signal kan skickas till skalet med \"kill -signal $$\".\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte en SIGSPEC är ogiltig eller en ogiltig "
-"flagga\n"
+" Returnerar framgång om inte en SIGSPEC är ogiltig eller en ogiltig flagga\n"
" ges."
-#: builtins.c:1384
+#: builtins.c:1383
msgid ""
"Display information about command type.\n"
" \n"
" NAME\tCommand name to be interpreted.\n"
" \n"
" Exit Status:\n"
-" Returns success if all of the NAMEs are found; fails if any are not "
-"found."
+" Returns success if all of the NAMEs are found; fails if any are not found."
msgstr ""
"Visa information om kommandotyper.\n"
" \n"
" -p\treturnerar antingen namnet på diskfilen som skulle exekverats,\n"
" \teller ingenting om \"type -t NAMN\" inte skulle returnerat \"file\".\n"
" -t\tskriv ut ett ensamt ord som är ett av \"alias\", \"keyword\",\n"
-" \t\"function\", \"builtin\", \"file\" eller \"\", om NAMN är ett alias, "
-"ett\n"
-" \treserverat ord i skalet, en skalfunktion, inbyggt i skalet, en "
-"diskfil\n"
+" \t\"function\", \"builtin\", \"file\" eller \"\", om NAMN är ett alias, ett\n"
+" \treserverat ord i skalet, en skalfunktion, inbyggt i skalet, en diskfil\n"
" \trespektive inte finns\n"
" \n"
" Argument:\n"
" Slutstatus:\n"
" Returnerar framgång om alla NAMNen finns, misslyckas om något inte finns."
-#: builtins.c:1415
-#, fuzzy
+#: builtins.c:1414
msgid ""
"Modify shell resource limits.\n"
" \n"
-" Provides control over the resources available to the shell and "
-"processes\n"
+" Provides control over the resources available to the shell and processes\n"
" it creates, on systems that allow such control.\n"
" \n"
" Options:\n"
msgstr ""
"Modifiera skalresursgränser.\n"
" \n"
-" Ger kontroll över resurserna som är tillgängliga till skalet och "
-"processer\n"
+" Ger kontroll över resurserna som är tillgängliga till skalet och processer\n"
" det skapar, på system som möjliggör sådan styrning.\n"
" \n"
" Flaggor:\n"
-" -S\tanvänd den \"mjuka\" resursgränsen\n"
-" -H\tanvänd den \"hårda\" resursgränsen\n"
+" -S\tanvänd den ”mjuka” resursgränsen\n"
+" -H\tanvänd den ”hårda” resursgränsen\n"
" -a\talla aktuella gränser rapporteras\n"
" -b\tstorleken på uttagsbuffertar\n"
" -c\tden maximala storleken på minnesutskrifter som skapas\n"
" -d\tden maximala storleken på en process datasegmen\n"
-" -e\tden maximala schemaläggningsprioriteten (\"nice\")\n"
+" -e\tden maximala schemaläggningsprioriteten (”nice”)\n"
" -f\tden maximala storleken på filer som skrivs av skalet och dess\n"
" \tbarn\n"
" -i\tdet maximala antalet väntande signaler\n"
" -u\tdet maximala antalet användarprocesser\n"
" -v\tstorleken på det virtuella minnet\n"
" -x\tdet maximala antalet fillås\n"
+" -T det maximala antalet trådar\n"
+" \n"
+" Alla flaggor är inte tillgängliga på alla plattformar.\n"
" \n"
" Om GRÄNS anges är det ett nytt värde för den specificerade resursen; de\n"
-" speciella GRÄNS-värdena \"soft\", \"hard\" och \"unlimited\" står för "
-"den\n"
-" aktuella mjuka gränsen, den aktuella hårda grånsen respektive inge "
-"gräns.\n"
+" speciella GRÄNS-värdena ”soft”, ”hard” och ”unlimited” står för den\n"
+" aktuella mjuka gränsen, den aktuella hårda grånsen respektive inge gräns.\n"
" Annars skrivs det aktuella värdet på den specificerade resursen. Om\n"
" ingen flagga ges antas -f.\n"
" \n"
-" Värden är i 1024-bytesteg, utom för -t som är i sekunder, -p som är i "
-"steg\n"
+" Värden är i 1024-bytesteg, utom för -t som är i sekunder, -p som är i steg\n"
" på 512 byte och -u som är ett antal processer utan någon skalning.\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte en ogiltig flagga anges eller ett fel "
-"inträffar."
+" Returnerar framgång om inte en ogiltig flagga anges eller ett fel inträffar."
-#: builtins.c:1463
+#: builtins.c:1462
msgid ""
"Display or set file mode mask.\n"
" \n"
" Sätter användarens filskapningsmask till RÄTTIGHETER. Om RÄTTIGHETER\n"
" utelämnas skrivs det aktuella värdet på masken.\n"
" \n"
-" Om RÄTTIGHETER börjar med en siffra tolkas det som ett oktalt tal, "
-"annars\n"
+" Om RÄTTIGHETER börjar med en siffra tolkas det som ett oktalt tal, annars\n"
" är det en symbolisk rättighetssträng som den som tas av chmod(1).\n"
" \n"
" Flaggor:\n"
" -S\tgör utmatningen symbolisk, annars används oktala tal\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte RÄTTIGHETER är ogiltig eller en ogiltig "
-"flagga\n"
+" Returnerar framgång om inte RÄTTIGHETER är ogiltig eller en ogiltig flagga\n"
" ges."
-#: builtins.c:1483
-#, fuzzy
+#: builtins.c:1482
msgid ""
"Wait for job completion and return exit status.\n"
" \n"
-" Waits for each process identified by an ID, which may be a process ID or "
-"a\n"
+" Waits for each process identified by an ID, which may be a process ID or a\n"
" job specification, and reports its termination status. If ID is not\n"
" given, waits for all currently active child processes, and the return\n"
-" status is zero. If ID is a a job specification, waits for all "
-"processes\n"
+" status is zero. If ID is a a job specification, waits for all processes\n"
" in that job's pipeline.\n"
" \n"
" If the -n option is supplied, waits for the next job to terminate and\n"
" Returns the status of the last ID; fails if ID is invalid or an invalid\n"
" option is given."
msgstr ""
-"Vänta på att jobb blir färdiga och returnerar slutstatus.\n"
+"Vänta på att jobb blir färdiga och returnera slutstatus.\n"
" \n"
-" Väntar på processen som identifieras av ID, som kan vara en process-id\n"
-" eller en jobbspecifikation, och rapportera dess avslutningsstatus. Om\n"
-" ID inte ges, vänta på alla nu körande barnprocesser, och returstatus är\n"
-" noll. Om ID är en jobbspecifikation, vänta på alla processer i det\n"
-" jobbets rör.\n"
+" Väntar på varje process som identifieras av ett ID, som kan vara en\n"
+" process-id eller en jobbspecifikation, och rapportera dess\n"
+" avslutningsstatus. Om ID inte ges, vänta på alla nu körande\n"
+" barnprocesser, och returstatus är noll. Om ID är en jobbspecifikation, \n"
+" vänta på alla processer i det jobbets rör.\n"
+" \n"
+" Om flaggan -n ges väntar på nästa jobb att avsluta och retunera dess\n"
+" slutstatus.\n"
" \n"
" Slutstatus:\n"
-" Returnerar status på ID, misslyckas ifall ID är ogiltig eller en "
-"ogiltig\n"
-" flagga ges."
+" Returnerar status på den sista ID, misslyckas ifall ID är ogiltig\n"
+" eller en ogiltig flagga ges."
-#: builtins.c:1504
-#, fuzzy
+#: builtins.c:1503
msgid ""
"Wait for process completion and return exit status.\n"
" \n"
-" Waits for each process specified by a PID and reports its termination "
-"status.\n"
+" Waits for each process specified by a PID and reports its termination status.\n"
" If PID is not given, waits for all currently active child processes,\n"
" and the return status is zero. PID must be a process ID.\n"
" \n"
" Exit Status:\n"
-" Returns the status of the last PID; fails if PID is invalid or an "
-"invalid\n"
+" Returns the status of the last PID; fails if PID is invalid or an invalid\n"
" option is given."
msgstr ""
"Vänta på att en process blir färdig och returnerar slutstatus.\n"
" \n"
-" Väntar på den angivna processen och rapportera dess avslutningsstatus. "
-"Om\n"
-" PID inte ges, vänta på alla nu körande barnprocesser, och returstatus "
-"är\n"
-" noll. PID måste vara en process-id.\n"
+" Väntar på varje process som identifieras av en PID rapporterar dess\n"
+" slutstatus. Om PID inte ges, väntar på alla nu körande barnprocesser,\n"
+" och returstatus är noll. PID måste vara en process-id.\n"
" \n"
" Slutstatus:\n"
-" Returnerar status på ID, misslyckas ifall ID är ogiltig eller en "
-"ogiltig\n"
-" flagga ges."
+" Returnerar status på den sista PID, misslyckas ifall PID är ogiltig\n"
+" eller en ogiltig flagga ges."
-#: builtins.c:1519
+#: builtins.c:1518
msgid ""
"Execute commands for each member in a list.\n"
" \n"
"Exekvera kommandon för varje medlem i en lista.\n"
" \n"
" \"for\"-slingan exekverar en sekvens av kommandon för varje medlem i en\n"
-" lista av element. Om \"in ORD ...;\" inte är med antas 'in \"$@\"'. "
-"För\n"
+" lista av element. Om \"in ORD ...;\" inte är med antas 'in \"$@\"'. För\n"
" varje element i ORD sätts NAMN till det elementet, och KOMMANDON\n"
" exekveras.\n"
" \n"
" Slutstatus:\n"
" Returnerar status för det sist exekverade kommandot."
-#: builtins.c:1533
+#: builtins.c:1532
msgid ""
"Arithmetic for loop.\n"
" \n"
" Slutstatus:\n"
" Returnerar statusen från det sist exekverade kommandot."
-#: builtins.c:1551
+#: builtins.c:1550
msgid ""
"Select words from a list and execute commands.\n"
" \n"
" Sluttatus:\n"
" Returnerar statusen från det sist exekverade kommandot."
-#: builtins.c:1572
+#: builtins.c:1571
msgid ""
"Report time consumed by pipeline's execution.\n"
" \n"
" Slutstatus:\n"
" Returstatusen är returstatusen från RÖR."
-#: builtins.c:1589
+#: builtins.c:1588
msgid ""
"Execute commands based on pattern matching.\n"
" \n"
" Slutstatus:\n"
" Returnerar statusen från det sist exekverade kommandot."
-#: builtins.c:1601
+#: builtins.c:1600
msgid ""
"Execute commands based on conditional.\n"
" \n"
-" The `if COMMANDS' list is executed. If its exit status is zero, then "
-"the\n"
-" `then COMMANDS' list is executed. Otherwise, each `elif COMMANDS' list "
-"is\n"
+" The `if COMMANDS' list is executed. If its exit status is zero, then the\n"
+" `then COMMANDS' list is executed. Otherwise, each `elif COMMANDS' list is\n"
" executed in turn, and if its exit status is zero, the corresponding\n"
-" `then COMMANDS' list is executed and the if command completes. "
-"Otherwise,\n"
-" the `else COMMANDS' list is executed, if present. The exit status of "
-"the\n"
-" entire construct is the exit status of the last command executed, or "
-"zero\n"
+" `then COMMANDS' list is executed and the if command completes. Otherwise,\n"
+" the `else COMMANDS' list is executed, if present. The exit status of the\n"
+" entire construct is the exit status of the last command executed, or zero\n"
" if no condition tested true.\n"
" \n"
" Exit Status:\n"
msgstr ""
"Exekvera kommndon baserat på ett villkor.\n"
" \n"
-" Listan \"if KOMMANDON\" exekveras. Om des slutstatus är noll så "
-"exekveras\n"
-" listan \"then COMMANDS\". Annars exekveras varje lista \"elif KOMMANDON"
-"\"\n"
+" Listan \"if KOMMANDON\" exekveras. Om des slutstatus är noll så exekveras\n"
+" listan \"then COMMANDS\". Annars exekveras varje lista \"elif KOMMANDON\"\n"
" i tur och ordning, och om dess slutstatus är noll exekveras motsvarande\n"
-" lista \"then COMMANDS\" och if-kommandot avslutar. Annars exekveras "
-"listan\n"
+" lista \"then COMMANDS\" och if-kommandot avslutar. Annars exekveras listan\n"
" \"else COMMANDS\" om den finns. Slutstatus av hela konstruktionen är\n"
" slutstatusen på det sist exekverade kommandot, eller noll om inget\n"
" villkor returnerade sant.\n"
" Slutstatus:\n"
" Returnerar status från det sist exekverade kommandot."
-#: builtins.c:1618
+#: builtins.c:1617
msgid ""
"Execute commands as long as a test succeeds.\n"
" \n"
" Slutstatus:\n"
" Returnerar statusen från det sist exekverade kommandot."
-#: builtins.c:1630
+#: builtins.c:1629
msgid ""
"Execute commands as long as a test does not succeed.\n"
" \n"
" Slutstatus:\n"
" Returnerar statusen från det sist exekverade kommandot."
-#: builtins.c:1642
+#: builtins.c:1641
msgid ""
"Create a coprocess named NAME.\n"
" \n"
" Slutstatus:\n"
" Returnerar statusen från KOMMANDO."
-#: builtins.c:1656
+#: builtins.c:1655
msgid ""
"Define shell function.\n"
" \n"
" Create a shell function named NAME. When invoked as a simple command,\n"
-" NAME runs COMMANDs in the calling shell's context. When NAME is "
-"invoked,\n"
+" NAME runs COMMANDs in the calling shell's context. When NAME is invoked,\n"
" the arguments are passed to the function as $1...$n, and the function's\n"
" name is in $FUNCNAME.\n"
" \n"
" Slutstatus:\n"
" Returnerar framgång om inte NAMN endast är läsbart."
-#: builtins.c:1670
+#: builtins.c:1669
msgid ""
"Group commands as a unit.\n"
" \n"
" Slutstatus:\n"
" Returnerar stutusen från det sist exekverade kommandot."
-#: builtins.c:1682
+#: builtins.c:1681
msgid ""
"Resume job in foreground.\n"
" \n"
" Slutstatus:\n"
" Returnerar statusen på det återupptagna jobbet."
-#: builtins.c:1697
+#: builtins.c:1696
msgid ""
"Evaluate arithmetic expression.\n"
" \n"
" Slutstatus:\n"
" Returnerar 1 om UTTRYCK beräknas till 0, returnerar 0 annars."
-#: builtins.c:1709
+#: builtins.c:1708
msgid ""
"Execute conditional command.\n"
" \n"
-" Returns a status of 0 or 1 depending on the evaluation of the "
-"conditional\n"
-" expression EXPRESSION. Expressions are composed of the same primaries "
-"used\n"
-" by the `test' builtin, and may be combined using the following "
-"operators:\n"
+" Returns a status of 0 or 1 depending on the evaluation of the conditional\n"
+" expression EXPRESSION. Expressions are composed of the same primaries used\n"
+" by the `test' builtin, and may be combined using the following operators:\n"
" \n"
" ( EXPRESSION )\tReturns the value of EXPRESSION\n"
" ! EXPRESSION\t\tTrue if EXPRESSION is false; else false\n"
"Kör ett villkorligt kommando.\n"
" \n"
" Returnerar en status av 0 eller 1 beroende på evalueringen av det\n"
-" villkorliga uttrycket UTTRYCK. Uttryck är sammansatta av samma "
-"primitiver\n"
+" villkorliga uttrycket UTTRYCK. Uttryck är sammansatta av samma primitiver\n"
" som används av det inbyggda \"test\", och kan kombineras med följande\n"
" operatorer:\n"
" \n"
" UTTR1 || UTTR2\tSant om antingen UTTR1 eller UTTR2 är sant, annars\n"
" falskt\n"
" \n"
-" När operatorerna \"==\" och \"!=\" används används strängen till höger "
-"om\n"
-" som ett mönster och mönstermatchning utförs. När operatorn \"=~\" "
-"används\n"
+" När operatorerna \"==\" och \"!=\" används används strängen till höger om\n"
+" som ett mönster och mönstermatchning utförs. När operatorn \"=~\" används\n"
" matchas strängen till höger om operatorn som ett reguljärt uttryck.\n"
" \n"
" Operatorerna && och || beräknar inte UTTR2 om UTTR1 är tillräckligt för\n"
" Slutstatus:\n"
" 0 eller 1 beroende på värdet av UTTRYCK."
-#: builtins.c:1735
+#: builtins.c:1734
msgid ""
"Common shell variable names and usage.\n"
" \n"
" HISTIGNORE\tEn kolonseparerad lista av mönster som används för att\n"
" \t\tbestämma vilka kommandon som skall sparas i historielistan.\n"
-#: builtins.c:1792
+#: builtins.c:1791
msgid ""
"Add directories to stack.\n"
" \n"
" Returnerar framgång om inte ett ogiltigt argument ges eller bytet av\n"
" katalog misslyckas."
-#: builtins.c:1826
+#: builtins.c:1825
msgid ""
"Remove directories from stack.\n"
" \n"
" Returnerar framgång om inte ett ogiltigt argument ges eller bytet av\n"
" katalog misslyckas."
-#: builtins.c:1856
+#: builtins.c:1855
msgid ""
"Display directory stack.\n"
" \n"
" \twith its position in the stack\n"
" \n"
" Arguments:\n"
-" +N\tDisplays the Nth entry counting from the left of the list shown "
-"by\n"
+" +N\tDisplays the Nth entry counting from the left of the list shown by\n"
" \tdirs when invoked without options, starting with zero.\n"
" \n"
-" -N\tDisplays the Nth entry counting from the right of the list shown "
-"by\n"
+" -N\tDisplays the Nth entry counting from the right of the list shown by\n"
" \tdirs when invoked without options, starting with zero.\n"
" \n"
" Exit Status:\n"
" \tav dirs när det anropas utan fläggor, med början från noll.\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte en ogiltig flagga ges eller ett fel "
-"inträffar."
+" Returnerar framgång om inte en ogiltig flagga ges eller ett fel inträffar."
-#: builtins.c:1885
+#: builtins.c:1884
msgid ""
"Set and unset shell options.\n"
" \n"
" Change the setting of each shell option OPTNAME. Without any option\n"
-" arguments, list all shell options with an indication of whether or not "
-"each\n"
+" arguments, list all shell options with an indication of whether or not each\n"
" is set.\n"
" \n"
" Options:\n"
" Returnerar framgång om FLGNAMN är aktiverat, misslyckas om en ogiltig\n"
" flagga ges eller FLGNAMN är avaktiverat."
-#: builtins.c:1906
-#, fuzzy
+#: builtins.c:1905
msgid ""
"Formats and prints ARGUMENTS under control of the FORMAT.\n"
" \n"
" -v var\tassign the output to shell variable VAR rather than\n"
" \t\tdisplay it on the standard output\n"
" \n"
-" FORMAT is a character string which contains three types of objects: "
-"plain\n"
-" characters, which are simply copied to standard output; character "
-"escape\n"
+" FORMAT is a character string which contains three types of objects: plain\n"
+" characters, which are simply copied to standard output; character escape\n"
" sequences, which are converted and copied to the standard output; and\n"
-" format specifications, each of which causes printing of the next "
-"successive\n"
+" format specifications, each of which causes printing of the next successive\n"
" argument.\n"
" \n"
-" In addition to the standard format specifications described in "
-"printf(1),\n"
+" In addition to the standard format specifications described in printf(1),\n"
" printf interprets:\n"
" \n"
" %b\texpand backslash escape sequences in the corresponding argument\n"
" %q\tquote the argument in a way that can be reused as shell input\n"
-" %(fmt)T output the date-time string resulting from using FMT as a "
-"format\n"
+" %(fmt)T output the date-time string resulting from using FMT as a format\n"
" string for strftime(3)\n"
" \n"
" The format is re-used as necessary to consume all of the arguments. If\n"
" there are fewer arguments than the format requires, extra format\n"
-" specifications behave as if a zero value or null string, as "
-"appropriate,\n"
+" specifications behave as if a zero value or null string, as appropriate,\n"
" had been supplied.\n"
" \n"
" Exit Status:\n"
-" Returns success unless an invalid option is given or a write or "
-"assignment\n"
+" Returns success unless an invalid option is given or a write or assignment\n"
" error occurs."
msgstr ""
"Formatera och skriv ARGUMENT styrda av FORMAT.\n"
" \n"
" FORMAT är en teckensträng som innehåller tre sortes objekt: vanliga\n"
" tecken, som helt enkelt kopieras till standard ut, teckenstyrsekvenser\n"
-" som konverteras och kopieras till standard ut och "
-"formatspecifikationer,\n"
+" som konverteras och kopieras till standard ut och formatspecifikationer,\n"
" där var och en medför utskrift av det nästföljande argumentet.\n"
" argument.\n"
" \n"
-" Förutom de standardformatspecifikationer som beskrivs a printf(1) och\n"
-" printf(3) tolkar printf:\n"
+" Förutom de standardformatspecifikationer som beskrivs a printf(1),\n"
+" tolkar printf:\n"
" \n"
" %b\texpandera bakstrecksstyrsekvenser i motsvarande argument\n"
" %q\tcitera argumentet på ett sätt som kan återanvändas som\n"
" %(fmt)T skriv ut datum-/tidsträngen som blir resultatet av att\n"
" använda FMT som en formatsträng till strftime(3)\n"
" \n"
+" Formatet återanvänds vid behov för att konsumera alla argument. Om\n"
+" det finns färre argument än formatet behöver beter sig överskjutande\n"
+" formatspecifikationer som om värdet noll eller den tomma strängen,\n"
+" det som passar, hade angivits.\n"
+" \n"
" Slutstatus:\n"
" Returnerar framgång om inte en ogiltig flagga ges eller ett skriv-\n"
" eller tilldelningsfel inträffar."
-#: builtins.c:1940
+#: builtins.c:1939
msgid ""
"Specify how arguments are to be completed by Readline.\n"
" \n"
-" For each NAME, specify how arguments are to be completed. If no "
-"options\n"
-" are supplied, existing completion specifications are printed in a way "
-"that\n"
+" For each NAME, specify how arguments are to be completed. If no options\n"
+" are supplied, existing completion specifications are printed in a way that\n"
" allows them to be reused as input.\n"
" \n"
" Options:\n"
" -E.\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte en ogiltig flagga ges eller ett fel "
-"inträffar."
+" Returnerar framgång om inte en ogiltig flagga ges eller ett fel inträffar."
-#: builtins.c:1968
+#: builtins.c:1967
msgid ""
"Display possible completions depending on the options.\n"
" \n"
" Intended to be used from within a shell function generating possible\n"
-" completions. If the optional WORD argument is supplied, matches "
-"against\n"
+" completions. If the optional WORD argument is supplied, matches against\n"
" WORD are generated.\n"
" \n"
" Exit Status:\n"
" matchningar av ORD.\n"
" \n"
" Slutstatus:\n"
-" Returnerar framgång om inte en ogiltig flagga ges eller ett fel "
-"inträffar."
+" Returnerar framgång om inte en ogiltig flagga ges eller ett fel inträffar."
-#: builtins.c:1983
+#: builtins.c:1982
msgid ""
"Modify or display completion options.\n"
" \n"
-" Modify the completion options for each NAME, or, if no NAMEs are "
-"supplied,\n"
-" the completion currently being executed. If no OPTIONs are given, "
-"print\n"
-" the completion options for each NAME or the current completion "
-"specification.\n"
+" Modify the completion options for each NAME, or, if no NAMEs are supplied,\n"
+" the completion currently being executed. If no OPTIONs are given, print\n"
+" the completion options for each NAME or the current completion specification.\n"
" \n"
" Options:\n"
" \t-o option\tSet completion option OPTION for each NAME\n"
msgstr ""
"Modifiera eller visa kompletteringsflaggor.\n"
" \n"
-" Modifiera kompletteringsflaggorna för varje NAMN, eller, om inga NAMN "
-"är\n"
+" Modifiera kompletteringsflaggorna för varje NAMN, eller, om inga NAMN är\n"
" givna, den komplettering som för närvarande körs. Om ingen FLAGGA är\n"
" given skrivs kompletteringsflaggorna för varje NAMN eller den aktuella\n"
" kompletteringsspecifikationen.\n"
" \t-D\t Ändra flaggorna för standardkommandokompletteringen\n"
" \t-E\t\tÄndra flaggorna för komplettering av ett tomt kommando\n"
" \n"
-" Genom att använda \"+o\" istället för \"-o\" slås den angivna flaggan "
-"av.\n"
+" Genom att använda \"+o\" istället för \"-o\" slås den angivna flaggan av.\n"
" \n"
" Argument:\n"
" \n"
" Varje NAMN refererar till ett kommando för vilket en kompletterings-\n"
-" specifikation måste ha definierats tidigare med det inbyggda \"complete"
-"\".\n"
+" specifikation måste ha definierats tidigare med det inbyggda \"complete\".\n"
" Om inget NAMN ges måste compopt anropas av en funktion som just nu\n"
" genererar kompletteringar, och flaggorna för den just nu exekverande\n"
" kompletteringsgeneratorn modifieras.\n"
" Returnerar framgång om inte en ogiltig flagga ges eller NAMN inte har\n"
" någon kompletteringsspecifikaation definierad."
-#: builtins.c:2013
+#: builtins.c:2012
msgid ""
"Read lines from the standard input into an indexed array variable.\n"
" \n"
-" Read lines from the standard input into the indexed array variable "
-"ARRAY, or\n"
-" from file descriptor FD if the -u option is supplied. The variable "
-"MAPFILE\n"
+" Read lines from the standard input into the indexed array variable ARRAY, or\n"
+" from file descriptor FD if the -u option is supplied. The variable MAPFILE\n"
" is the default ARRAY.\n"
" \n"
" Options:\n"
-" -n count\tCopy at most COUNT lines. If COUNT is 0, all lines are "
-"copied.\n"
-" -O origin\tBegin assigning to ARRAY at index ORIGIN. The default "
-"index is 0.\n"
+" -n count\tCopy at most COUNT lines. If COUNT is 0, all lines are copied.\n"
+" -O origin\tBegin assigning to ARRAY at index ORIGIN. The default index is 0.\n"
" -s count \tDiscard the first COUNT lines read.\n"
" -t\t\tRemove a trailing newline from each line read.\n"
-" -u fd\t\tRead lines from file descriptor FD instead of the standard "
-"input.\n"
+" -u fd\t\tRead lines from file descriptor FD instead of the standard input.\n"
" -C callback\tEvaluate CALLBACK each time QUANTUM lines are read.\n"
-" -c quantum\tSpecify the number of lines read between each call to "
-"CALLBACK.\n"
+" -c quantum\tSpecify the number of lines read between each call to CALLBACK.\n"
" \n"
" Arguments:\n"
" ARRAY\t\tArray variable name to use for file data.\n"
" element to be assigned and the line to be assigned to that element\n"
" as additional arguments.\n"
" \n"
-" If not supplied with an explicit origin, mapfile will clear ARRAY "
-"before\n"
+" If not supplied with an explicit origin, mapfile will clear ARRAY before\n"
" assigning to it.\n"
" \n"
" Exit Status:\n"
-" Returns success unless an invalid option is given or ARRAY is readonly "
-"or\n"
+" Returns success unless an invalid option is given or ARRAY is readonly or\n"
" not an indexed array."
msgstr ""
"Läs rader från standard in till en indexerad vektorvariabel.\n"
" standard för VEKTOR.\n"
" \n"
" Flaggor:\n"
-" -n antal\tKopiera högs ANTAL rader. Om ANTAL är 0 kopieras alla "
-"rader.\n"
-" -O start\tBörja tilldela till VEKTOR vid index START. Standardindex "
-"är 0.\n"
+" -n antal\tKopiera högs ANTAL rader. Om ANTAL är 0 kopieras alla rader.\n"
+" -O start\tBörja tilldela till VEKTOR vid index START. Standardindex är 0.\n"
" -s antal \tSläng de första ANTAL inlästa raderna.\n"
" -t\t\tTa bort en avslutande nyrad från varje inläst rad.\n"
" -u fb\t\tLäs rader från filbeskrivare FB istället för standard in.\n"
" VEKTOR\t\tNamn på vektorvariabel att använda för fildata.\n"
" \n"
" Om -C ges utan -c är standardkvanta 5000. När ÅTERANROP evalueras får\n"
-" den indexet på nästa vektorelement att tilldelas och raden att "
-"tilldelas\n"
+" den indexet på nästa vektorelement att tilldelas och raden att tilldelas\n"
" till det elementet som extra argument.\n"
" \n"
-" Om det inte ges någon specificerad start kommer mapfile nollställa "
-"VEKTOR\n"
+" Om det inte ges någon specificerad start kommer mapfile nollställa VEKTOR\n"
" före tilldelning till den.\n"
" \n"
" Slutstatus:\n"
" Returnerar framgång om inte en ogiltig flagga ges eller VEKTOR är\n"
" oföränderlig eller inte en indexerad vektor."
-#: builtins.c:2047
+#: builtins.c:2046
msgid ""
"Read lines from a file into an array variable.\n"
" \n"
"Läs rader från en fil till en vektorvariabel.\n"
" \n"
" En synonym till \"mapfile\"."
-
-#~ msgid "Copyright (C) 2009 Free Software Foundation, Inc.\n"
-#~ msgstr "Copyright © 2009 Free Software Foundation, Inc.\n"
-
-#~ msgid ""
-#~ "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl."
-#~ "html>\n"
-#~ msgstr ""
-#~ "Licens GPLv2+: GNU GPL version 2 eller senare <http://gnu.org/licenses/"
-#~ "gpl.html>\n"
-
-#~ msgid "wait [pid]"
-#~ msgstr "wait [pid]"
sigemptyset (&act.sa_mask);
sigemptyset (&oact.sa_mask);
- sigaction (sig, &act, &oact);
- return (oact.sa_handler);
+ if (sigaction (sig, &act, &oact) == 0)
+ return (oact.sa_handler);
+ else
+ return (SIG_DFL);
}
#endif /* HAVE_POSIX_SIGNALS */
--- /dev/null
+/* sig.c - interface for shell signal handlers and signal initialization. */
+
+/* Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+ This file is part of GNU Bash, the Bourne Again SHell.
+
+ Bash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bash is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bash. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "config.h"
+
+#include "bashtypes.h"
+
+#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
+# include <unistd.h>
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+
+#include "bashintl.h"
+
+#include "shell.h"
+#if defined (JOB_CONTROL)
+#include "jobs.h"
+#endif /* JOB_CONTROL */
+#include "siglist.h"
+#include "sig.h"
+#include "trap.h"
+
+#include "builtins/common.h"
+
+#if defined (READLINE)
+# include "bashline.h"
+# include <readline/readline.h>
+#endif
+
+#if defined (HISTORY)
+# include "bashhist.h"
+#endif
+
+extern int last_command_exit_value;
+extern int last_command_exit_signal;
+extern int return_catch_flag;
+extern int loop_level, continuing, breaking, funcnest;
+extern int executing_list;
+extern int comsub_ignore_return;
+extern int parse_and_execute_level, shell_initialized;
+#if defined (HISTORY)
+extern int history_lines_this_session;
+#endif
+extern int no_line_editing;
+
+extern void initialize_siglist ();
+
+/* Non-zero after SIGINT. */
+volatile sig_atomic_t interrupt_state = 0;
+
+/* Non-zero after SIGWINCH */
+volatile sig_atomic_t sigwinch_received = 0;
+
+/* Non-zero after SIGTERM */
+volatile sig_atomic_t sigterm_received = 0;
+
+/* Set to the value of any terminating signal received. */
+volatile sig_atomic_t terminating_signal = 0;
+
+/* The environment at the top-level R-E loop. We use this in
+ the case of error return. */
+procenv_t top_level;
+
+#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
+/* The signal masks that this shell runs with. */
+sigset_t top_level_mask;
+#endif /* JOB_CONTROL */
+
+/* When non-zero, we throw_to_top_level (). */
+int interrupt_immediately = 0;
+
+/* When non-zero, we call the terminating signal handler immediately. */
+int terminate_immediately = 0;
+
+#if defined (SIGWINCH)
+static SigHandler *old_winch = (SigHandler *)SIG_DFL;
+#endif
+
+static void initialize_shell_signals __P((void));
+
+void
+initialize_signals (reinit)
+ int reinit;
+{
+ initialize_shell_signals ();
+ initialize_job_signals ();
+#if !defined (HAVE_SYS_SIGLIST) && !defined (HAVE_UNDER_SYS_SIGLIST) && !defined (HAVE_STRSIGNAL)
+ if (reinit == 0)
+ initialize_siglist ();
+#endif /* !HAVE_SYS_SIGLIST && !HAVE_UNDER_SYS_SIGLIST && !HAVE_STRSIGNAL */
+}
+
+/* A structure describing a signal that terminates the shell if not
+ caught. The orig_handler member is present so children can reset
+ these signals back to their original handlers. */
+struct termsig {
+ int signum;
+ SigHandler *orig_handler;
+ int orig_flags;
+};
+
+#define NULL_HANDLER (SigHandler *)SIG_DFL
+
+/* The list of signals that would terminate the shell if not caught.
+ We catch them, but just so that we can write the history file,
+ and so forth. */
+static struct termsig terminating_signals[] = {
+#ifdef SIGHUP
+{ SIGHUP, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGINT
+{ SIGINT, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGILL
+{ SIGILL, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGTRAP
+{ SIGTRAP, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGIOT
+{ SIGIOT, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGDANGER
+{ SIGDANGER, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGEMT
+{ SIGEMT, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGFPE
+{ SIGFPE, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGBUS
+{ SIGBUS, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGSEGV
+{ SIGSEGV, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGSYS
+{ SIGSYS, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGPIPE
+{ SIGPIPE, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGALRM
+{ SIGALRM, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGTERM
+{ SIGTERM, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGXCPU
+{ SIGXCPU, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGXFSZ
+{ SIGXFSZ, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGVTALRM
+{ SIGVTALRM, NULL_HANDLER, 0 },
+#endif
+
+#if 0
+#ifdef SIGPROF
+{ SIGPROF, NULL_HANDLER, 0 },
+#endif
+#endif
+
+#ifdef SIGLOST
+{ SIGLOST, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGUSR1
+{ SIGUSR1, NULL_HANDLER, 0 },
+#endif
+
+#ifdef SIGUSR2
+{ SIGUSR2, NULL_HANDLER, 0 },
+#endif
+};
+
+#define TERMSIGS_LENGTH (sizeof (terminating_signals) / sizeof (struct termsig))
+
+#define XSIG(x) (terminating_signals[x].signum)
+#define XHANDLER(x) (terminating_signals[x].orig_handler)
+#define XSAFLAGS(x) (terminating_signals[x].orig_flags)
+
+static int termsigs_initialized = 0;
+
+/* Initialize signals that will terminate the shell to do some
+ unwind protection. For non-interactive shells, we only call
+ this when a trap is defined for EXIT (0) or when trap is run
+ to display signal dispositions. */
+void
+initialize_terminating_signals ()
+{
+ register int i;
+#if defined (HAVE_POSIX_SIGNALS)
+ struct sigaction act, oact;
+#endif
+
+ if (termsigs_initialized)
+ return;
+
+ /* The following code is to avoid an expensive call to
+ set_signal_handler () for each terminating_signals. Fortunately,
+ this is possible in Posix. Unfortunately, we have to call signal ()
+ on non-Posix systems for each signal in terminating_signals. */
+#if defined (HAVE_POSIX_SIGNALS)
+ act.sa_handler = termsig_sighandler;
+ act.sa_flags = 0;
+ sigemptyset (&act.sa_mask);
+ sigemptyset (&oact.sa_mask);
+ for (i = 0; i < TERMSIGS_LENGTH; i++)
+ sigaddset (&act.sa_mask, XSIG (i));
+ for (i = 0; i < TERMSIGS_LENGTH; i++)
+ {
+ /* If we've already trapped it, don't do anything. */
+ if (signal_is_trapped (XSIG (i)))
+ continue;
+
+ sigaction (XSIG (i), &act, &oact);
+ XHANDLER(i) = oact.sa_handler;
+ XSAFLAGS(i) = oact.sa_flags;
+ /* Don't do anything with signals that are ignored at shell entry
+ if the shell is not interactive. */
+ /* XXX - should we do this for interactive shells, too? */
+ if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
+ {
+ sigaction (XSIG (i), &oact, &act);
+ set_signal_ignored (XSIG (i));
+ }
+#if defined (SIGPROF) && !defined (_MINIX)
+ if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
+ sigaction (XSIG (i), &oact, (struct sigaction *)NULL);
+#endif /* SIGPROF && !_MINIX */
+ }
+
+#else /* !HAVE_POSIX_SIGNALS */
+
+ for (i = 0; i < TERMSIGS_LENGTH; i++)
+ {
+ /* If we've already trapped it, don't do anything. */
+ if (signal_is_trapped (XSIG (i)))
+ continue;
+
+ XHANDLER(i) = signal (XSIG (i), termsig_sighandler);
+ XSAFLAGS(i) = 0;
+ /* Don't do anything with signals that are ignored at shell entry
+ if the shell is not interactive. */
+ /* XXX - should we do this for interactive shells, too? */
+ if (interactive_shell == 0 && XHANDLER (i) == SIG_IGN)
+ {
+ signal (XSIG (i), SIG_IGN);
+ set_signal_ignored (XSIG (i));
+ }
+#ifdef SIGPROF
+ if (XSIG (i) == SIGPROF && XHANDLER (i) != SIG_DFL && XHANDLER (i) != SIG_IGN)
+ signal (XSIG (i), XHANDLER (i));
+#endif
+ }
+
+#endif /* !HAVE_POSIX_SIGNALS */
+
+ termsigs_initialized = 1;
+}
+
+static void
+initialize_shell_signals ()
+{
+ if (interactive)
+ initialize_terminating_signals ();
+
+#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
+ /* All shells use the signal mask they inherit, and pass it along
+ to child processes. Children will never block SIGCHLD, though. */
+ sigemptyset (&top_level_mask);
+ sigprocmask (SIG_BLOCK, (sigset_t *)NULL, &top_level_mask);
+# if defined (SIGCHLD)
+ sigdelset (&top_level_mask, SIGCHLD);
+# endif
+#endif /* JOB_CONTROL || HAVE_POSIX_SIGNALS */
+
+ /* And, some signals that are specifically ignored by the shell. */
+ set_signal_handler (SIGQUIT, SIG_IGN);
+
+ if (interactive)
+ {
+ set_signal_handler (SIGINT, sigint_sighandler);
+ get_original_signal (SIGTERM);
+ if (signal_is_hard_ignored (SIGTERM) == 0)
+ set_signal_handler (SIGTERM, sigterm_sighandler);
+ set_sigwinch_handler ();
+ }
+}
+
+void
+reset_terminating_signals ()
+{
+ register int i;
+#if defined (HAVE_POSIX_SIGNALS)
+ struct sigaction act;
+#endif
+
+ if (termsigs_initialized == 0)
+ return;
+
+#if defined (HAVE_POSIX_SIGNALS)
+ act.sa_flags = 0;
+ sigemptyset (&act.sa_mask);
+ for (i = 0; i < TERMSIGS_LENGTH; i++)
+ {
+ /* Skip a signal if it's trapped or handled specially, because the
+ trap code will restore the correct value. */
+ if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
+ continue;
+
+ act.sa_handler = XHANDLER (i);
+ act.sa_flags = XSAFLAGS (i);
+ sigaction (XSIG (i), &act, (struct sigaction *) NULL);
+ }
+#else /* !HAVE_POSIX_SIGNALS */
+ for (i = 0; i < TERMSIGS_LENGTH; i++)
+ {
+ if (signal_is_trapped (XSIG (i)) || signal_is_special (XSIG (i)))
+ continue;
+
+ signal (XSIG (i), XHANDLER (i));
+ }
+#endif /* !HAVE_POSIX_SIGNALS */
+
+ termsigs_initialized = 0;
+}
+#undef XSIG
+#undef XHANDLER
+
+/* Run some of the cleanups that should be performed when we run
+ jump_to_top_level from a builtin command context. XXX - might want to
+ also call reset_parser here. */
+void
+top_level_cleanup ()
+{
+ /* Clean up string parser environment. */
+ while (parse_and_execute_level)
+ parse_and_execute_cleanup ();
+
+#if defined (PROCESS_SUBSTITUTION)
+ unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+
+ run_unwind_protects ();
+ loop_level = continuing = breaking = funcnest = 0;
+ executing_list = comsub_ignore_return = return_catch_flag = 0;
+}
+
+/* What to do when we've been interrupted, and it is safe to handle it. */
+void
+throw_to_top_level ()
+{
+ int print_newline = 0;
+
+ if (interrupt_state)
+ {
+ if (last_command_exit_value < 128)
+ last_command_exit_value = 128 + SIGINT;
+ print_newline = 1;
+ DELINTERRUPT;
+ }
+
+ if (interrupt_state)
+ return;
+
+ last_command_exit_signal = (last_command_exit_value > 128) ?
+ (last_command_exit_value - 128) : 0;
+ last_command_exit_value |= 128;
+
+ /* Run any traps set on SIGINT. */
+ run_interrupt_trap ();
+
+ /* Clean up string parser environment. */
+ while (parse_and_execute_level)
+ parse_and_execute_cleanup ();
+
+#if defined (JOB_CONTROL)
+ give_terminal_to (shell_pgrp, 0);
+#endif /* JOB_CONTROL */
+
+#if defined (JOB_CONTROL) || defined (HAVE_POSIX_SIGNALS)
+ /* This needs to stay because jobs.c:make_child() uses it without resetting
+ the signal mask. */
+ sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
+#endif
+
+ reset_parser ();
+
+#if defined (READLINE)
+ if (interactive)
+ bashline_reset ();
+#endif /* READLINE */
+
+#if defined (PROCESS_SUBSTITUTION)
+ unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+
+ run_unwind_protects ();
+ loop_level = continuing = breaking = funcnest = 0;
+ executing_list = comsub_ignore_return = return_catch_flag = 0;
+
+ if (interactive && print_newline)
+ {
+ fflush (stdout);
+ fprintf (stderr, "\n");
+ fflush (stderr);
+ }
+
+ /* An interrupted `wait' command in a script does not exit the script. */
+ if (interactive || (interactive_shell && !shell_initialized) ||
+ (print_newline && signal_is_trapped (SIGINT)))
+ jump_to_top_level (DISCARD);
+ else
+ jump_to_top_level (EXITPROG);
+}
+
+/* This is just here to isolate the longjmp calls. */
+void
+jump_to_top_level (value)
+ int value;
+{
+ longjmp (top_level, value);
+}
+
+sighandler
+termsig_sighandler (sig)
+ int sig;
+{
+ /* If we get called twice with the same signal before handling it,
+ terminate right away. */
+ if (
+#ifdef SIGHUP
+ sig != SIGHUP &&
+#endif
+#ifdef SIGINT
+ sig != SIGINT &&
+#endif
+#ifdef SIGDANGER
+ sig != SIGDANGER &&
+#endif
+#ifdef SIGPIPE
+ sig != SIGPIPE &&
+#endif
+#ifdef SIGALRM
+ sig != SIGALRM &&
+#endif
+#ifdef SIGTERM
+ sig != SIGTERM &&
+#endif
+#ifdef SIGXCPU
+ sig != SIGXCPU &&
+#endif
+#ifdef SIGXFSZ
+ sig != SIGXFSZ &&
+#endif
+#ifdef SIGVTALRM
+ sig != SIGVTALRM &&
+#endif
+#ifdef SIGLOST
+ sig != SIGLOST &&
+#endif
+#ifdef SIGUSR1
+ sig != SIGUSR1 &&
+#endif
+#ifdef SIGUSR2
+ sig != SIGUSR2 &&
+#endif
+ sig == terminating_signal)
+ terminate_immediately = 1;
+
+ terminating_signal = sig;
+
+ /* XXX - should this also trigger when interrupt_immediately is set? */
+ if (terminate_immediately)
+ {
+#if defined (HISTORY)
+ /* XXX - will inhibit history file being written */
+# if defined (READLINE)
+ if (interactive_shell == 0 || interactive == 0 || (sig != SIGHUP && sig != SIGTERM) || no_line_editing || (RL_ISSTATE (RL_STATE_READCMD) == 0))
+# endif
+ history_lines_this_session = 0;
+#endif
+ terminate_immediately = 0;
+ termsig_handler (sig);
+ }
+
+#if defined (READLINE)
+ /* Set the event hook so readline will call it after the signal handlers
+ finish executing, so if this interrupted character input we can get
+ quick response. */
+ if (interactive_shell && interactive && no_line_editing == 0)
+ bashline_set_event_hook ();
+#endif
+
+ SIGRETURN (0);
+}
+
+void
+termsig_handler (sig)
+ int sig;
+{
+ static int handling_termsig = 0;
+
+ /* Simple semaphore to keep this function from being executed multiple
+ times. Since we no longer are running as a signal handler, we don't
+ block multiple occurrences of the terminating signals while running. */
+ if (handling_termsig)
+ return;
+ handling_termsig = 1;
+ terminating_signal = 0; /* keep macro from re-testing true. */
+
+ /* I don't believe this condition ever tests true. */
+ if (sig == SIGINT && signal_is_trapped (SIGINT))
+ run_interrupt_trap ();
+
+#if defined (HISTORY)
+ /* If we don't do something like this, the history will not be saved when
+ an interactive shell is running in a terminal window that gets closed
+ with the `close' button. We can't test for RL_STATE_READCMD because
+ readline no longer handles SIGTERM synchronously. */
+ if (interactive_shell && interactive && (sig == SIGHUP || sig == SIGTERM) && remember_on_history)
+ maybe_save_shell_history ();
+#endif /* HISTORY */
+
+#if defined (JOB_CONTROL)
+ if (sig == SIGHUP && (interactive || (subshell_environment & (SUBSHELL_COMSUB|SUBSHELL_PROCSUB))))
+ hangup_all_jobs ();
+ end_job_control ();
+#endif /* JOB_CONTROL */
+
+#if defined (PROCESS_SUBSTITUTION)
+ unlink_fifo_list ();
+#endif /* PROCESS_SUBSTITUTION */
+
+ /* Reset execution context */
+ loop_level = continuing = breaking = funcnest = 0;
+ executing_list = comsub_ignore_return = return_catch_flag = 0;
+
+ run_exit_trap (); /* XXX - run exit trap possibly in signal context? */
+ set_signal_handler (sig, SIG_DFL);
+ kill (getpid (), sig);
+}
+
+/* What we really do when SIGINT occurs. */
+sighandler
+sigint_sighandler (sig)
+ int sig;
+{
+#if defined (MUST_REINSTALL_SIGHANDLERS)
+ signal (sig, sigint_sighandler);
+#endif
+
+ /* interrupt_state needs to be set for the stack of interrupts to work
+ right. Should it be set unconditionally? */
+ if (interrupt_state == 0)
+ ADDINTERRUPT;
+
+ if (interrupt_immediately)
+ {
+ interrupt_immediately = 0;
+ last_command_exit_value = 128 + sig;
+ throw_to_top_level ();
+ }
+#if defined (READLINE)
+ /* Set the event hook so readline will call it after the signal handlers
+ finish executing, so if this interrupted character input we can get
+ quick response. */
+ else if (RL_ISSTATE (RL_STATE_SIGHANDLER))
+ bashline_set_event_hook ();
+#endif
+
+ SIGRETURN (0);
+}
+
+#if defined (SIGWINCH)
+sighandler
+sigwinch_sighandler (sig)
+ int sig;
+{
+#if defined (MUST_REINSTALL_SIGHANDLERS)
+ set_signal_handler (SIGWINCH, sigwinch_sighandler);
+#endif /* MUST_REINSTALL_SIGHANDLERS */
+ sigwinch_received = 1;
+ SIGRETURN (0);
+}
+#endif /* SIGWINCH */
+
+void
+set_sigwinch_handler ()
+{
+#if defined (SIGWINCH)
+ old_winch = set_signal_handler (SIGWINCH, sigwinch_sighandler);
+#endif
+}
+
+void
+unset_sigwinch_handler ()
+{
+#if defined (SIGWINCH)
+ set_signal_handler (SIGWINCH, old_winch);
+#endif
+}
+
+sighandler
+sigterm_sighandler (sig)
+ int sig;
+{
+ sigterm_received = 1; /* XXX - counter? */
+ SIGRETURN (0);
+}
+
+/* Signal functions used by the rest of the code. */
+#if !defined (HAVE_POSIX_SIGNALS)
+
+/* Perform OPERATION on NEWSET, perhaps leaving information in OLDSET. */
+sigprocmask (operation, newset, oldset)
+ int operation, *newset, *oldset;
+{
+ int old, new;
+
+ if (newset)
+ new = *newset;
+ else
+ new = 0;
+
+ switch (operation)
+ {
+ case SIG_BLOCK:
+ old = sigblock (new);
+ break;
+
+ case SIG_SETMASK:
+ old = sigsetmask (new);
+ break;
+
+ default:
+ internal_error (_("sigprocmask: %d: invalid operation"), operation);
+ }
+
+ if (oldset)
+ *oldset = old;
+}
+
+#else
+
+#if !defined (SA_INTERRUPT)
+# define SA_INTERRUPT 0
+#endif
+
+#if !defined (SA_RESTART)
+# define SA_RESTART 0
+#endif
+
+SigHandler *
+set_signal_handler (sig, handler)
+ int sig;
+ SigHandler *handler;
+{
+ struct sigaction act, oact;
+
+ act.sa_handler = handler;
+ act.sa_flags = 0;
+
+ /* XXX - bash-4.2 */
+ /* We don't want a child death to interrupt interruptible system calls, even
+ if we take the time to reap children */
+#if defined (SIGCHLD)
+ if (sig == SIGCHLD)
+ act.sa_flags |= SA_RESTART; /* XXX */
+#endif
+ /* If we're installing a SIGTERM handler for interactive shells, we want
+ it to be as close to SIG_IGN as possible. */
+ if (sig == SIGTERM && handler == sigterm_sighandler)
+ act.sa_flags |= SA_RESTART; /* XXX */
+
+ sigemptyset (&act.sa_mask);
+ sigemptyset (&oact.sa_mask);
+ sigaction (sig, &act, &oact);
+ return (oact.sa_handler);
+}
+#endif /* HAVE_POSIX_SIGNALS */