mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-25 14:55:25 +02:00
commit bash-20100415 snapshot
This commit is contained in:
@@ -9697,3 +9697,42 @@ builtins/declare.def
|
||||
allocated memory for the key argument when using an implicit key
|
||||
of "0". Bug report and fix from Andreas Schwab
|
||||
<schwab@linux-m68k.org>
|
||||
|
||||
4/14
|
||||
----
|
||||
lib/readline/input.c
|
||||
- restructure the rl_event_hook loop in rl_read_key to call the
|
||||
event hook after rl_gather_tyi() returns and rl_get_char has
|
||||
a chance to collect the input. Previous behavior was to call
|
||||
the event hook before attempting to read input. Problem
|
||||
reported by Anant Shankar <anantshankar17@gmail.com>
|
||||
|
||||
4/15
|
||||
----
|
||||
builtins/fc.def
|
||||
- fc_builtin needs to check whether the calculation of last_hist
|
||||
leaves hlist[last_hist] == 0, and keep decrementing it until it
|
||||
leaves a non-null history entry or goes < 0. Currently only
|
||||
does this if saved_command_line_count > 0, indicating we're
|
||||
trying to edit a multi-line command. Fixes bug reported by
|
||||
Roman Rakus <rrakus@redhat.com>
|
||||
|
||||
4/17
|
||||
----
|
||||
subst.c
|
||||
- new process substitution helper functions:
|
||||
unlink_fifo - closes a single FD or FIFO
|
||||
num_fifos - returns number of open FDs or active FIFOs
|
||||
copy_fifo_list - returns a bitmap of open FDs or active FIFOs
|
||||
by index into appropriate list (dev_fd_list or fifo_list)
|
||||
close_new_fifos - take a bitmap saved by copy_fifo_list and
|
||||
call unlink_fifo on any FD or FIFO open at the time of the
|
||||
call that is not marked as active in list
|
||||
|
||||
execute_cmd.c
|
||||
- execute_builtin_or_function: use new framework to close process
|
||||
substitution FDs or FIFOs created by a shell builtin or shell
|
||||
function. Fixes bug reported by Charles Duffy <charles@dyfis.net>
|
||||
|
||||
doc/{bash.1,bashref.texi}
|
||||
- document 'C and "C constants for printf builtin
|
||||
|
||||
+39
-1
@@ -9690,10 +9690,48 @@ parser.h
|
||||
subst.c
|
||||
- include parser.h
|
||||
|
||||
4/8
|
||||
4/9
|
||||
---
|
||||
builtins/declare.def
|
||||
- make sure declare_internal calls bind_assoc_variable with newly-
|
||||
allocated memory for the key argument when using an implicit key
|
||||
of "0". Bug report and fix from Andreas Schwab
|
||||
<schwab@linux-m68k.org>
|
||||
|
||||
4/14
|
||||
----
|
||||
lib/readline/input.c
|
||||
- restructure the rl_event_hook loop in rl_read_key to call the
|
||||
event hook after rl_gather_tyi() returns and rl_get_char has
|
||||
a chance to collect the input. Previous behavior was to call
|
||||
the event hook before attempting to read input. Problem
|
||||
reported by Anant Shankar <anantshankar17@gmail.com>
|
||||
|
||||
4/15
|
||||
----
|
||||
builtins/fc.def
|
||||
- fc_builtin needs to check whether the calculation of last_hist
|
||||
leaves hlist[last_hist] == 0, and keep decrementing it until it
|
||||
leaves a non-null history entry or goes < 0. Currently only
|
||||
does this if saved_command_line_count > 0, indicating we're
|
||||
trying to edit a multi-line command. Fixes bug reported by
|
||||
Roman Rakus <rrakus@redhat.com>
|
||||
|
||||
4/17
|
||||
----
|
||||
subst.c
|
||||
- new process substitution helper functions:
|
||||
unlink_fifo - closes a single FD or FIFO
|
||||
num_fifos - returns number of open FDs or active FIFOs
|
||||
copy_fifo_list - returns a bitmap of open FDs or active FIFOs
|
||||
by index into appropriate list (dev_fd_list or fifo_list)
|
||||
close_new_fifos - take a bitmap saved by copy_fifo_list and
|
||||
call unlink_fifo on any FD or FIFO open at the time of the
|
||||
call that is not marked as active in list
|
||||
|
||||
execute_cmd.c
|
||||
- execute_builtin_or_function: use new framework to close process
|
||||
substitution FDs or FIFOs created by a shell builtin or shell
|
||||
function. Fixes bug reported by Charles Duffy <charles@dyfis.net>
|
||||
|
||||
|
||||
|
||||
+7
-4
@@ -175,7 +175,8 @@ static char **prog_complete_matches;
|
||||
extern int hist_verify;
|
||||
#endif
|
||||
|
||||
extern int current_command_line_count, last_command_exit_value;
|
||||
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;
|
||||
@@ -862,11 +863,11 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
char *edit_command;
|
||||
{
|
||||
char *command, *metaval;
|
||||
int r, cclc, rrs, metaflag;
|
||||
int r, rrs, metaflag;
|
||||
sh_parser_state_t ps;
|
||||
|
||||
rrs = rl_readline_state;
|
||||
cclc = current_command_line_count;
|
||||
saved_command_line_count = current_command_line_count;
|
||||
|
||||
/* Accept the current line. */
|
||||
rl_newline (1, c);
|
||||
@@ -882,6 +883,8 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
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 ();
|
||||
bash_add_history (rl_line_buffer);
|
||||
bash_add_history ("");
|
||||
@@ -904,7 +907,7 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
if (rl_prep_term_function)
|
||||
(*rl_prep_term_function) (metaflag);
|
||||
|
||||
current_command_line_count = cclc;
|
||||
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
|
||||
|
||||
+7
-1
@@ -175,7 +175,8 @@ static char **prog_complete_matches;
|
||||
extern int hist_verify;
|
||||
#endif
|
||||
|
||||
extern int current_command_line_count, last_command_exit_value;
|
||||
extern int current_command_line_count, fc_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;
|
||||
@@ -863,6 +864,7 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
{
|
||||
char *command, *metaval;
|
||||
int r, cclc, rrs, metaflag;
|
||||
sh_parser_state_t ps;
|
||||
|
||||
rrs = rl_readline_state;
|
||||
cclc = current_command_line_count;
|
||||
@@ -881,6 +883,8 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
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 ();
|
||||
bash_add_history (rl_line_buffer);
|
||||
bash_add_history ("");
|
||||
@@ -897,7 +901,9 @@ edit_and_execute_command (count, c, editing_mode, edit_command)
|
||||
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);
|
||||
|
||||
|
||||
+11
-1
@@ -85,7 +85,7 @@ $END
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
extern int current_command_line_count;
|
||||
extern int current_command_line_count, saved_command_line_count;
|
||||
extern int literal_history;
|
||||
extern int posixly_correct;
|
||||
extern int subshell_environment, interactive_shell;
|
||||
@@ -303,6 +303,16 @@ fc_builtin (list)
|
||||
rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
|
||||
last_hist = i - rh - hist_last_line_added;
|
||||
|
||||
/* XXX */
|
||||
if (saved_command_line_count > 0 && i == last_hist && hlist[last_hist] == 0)
|
||||
while (last_hist >= 0 && hlist[last_hist] == 0)
|
||||
last_hist--;
|
||||
if (last_hist < 0)
|
||||
{
|
||||
sh_erange ((char *)NULL, _("history specification"));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (list)
|
||||
{
|
||||
histbeg = fc_gethnum (list->word->word, hlist);
|
||||
|
||||
@@ -0,0 +1,675 @@
|
||||
This file is fc.def, from which is created fc.c.
|
||||
It implements the builtin "fc" in Bash.
|
||||
|
||||
Copyright (C) 1987-2009 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/>.
|
||||
|
||||
$PRODUCES fc.c
|
||||
|
||||
$BUILTIN fc
|
||||
$FUNCTION fc_builtin
|
||||
$DEPENDS_ON HISTORY
|
||||
$SHORT_DOC fc [-e ename] [-lnr] [first] [last] or fc -s [pat=rep] [command]
|
||||
Display or execute commands from the history list.
|
||||
|
||||
fc is used to list or edit and re-execute commands from the history list.
|
||||
FIRST and LAST can be numbers specifying the range, or FIRST can be a
|
||||
string, which means the most recent command beginning with that
|
||||
string.
|
||||
|
||||
Options:
|
||||
-e ENAME select which editor to use. Default is FCEDIT, then EDITOR,
|
||||
then vi
|
||||
-l list lines instead of editing
|
||||
-n omit line numbers when listing
|
||||
-r reverse the order of the lines (newest listed first)
|
||||
|
||||
With the `fc -s [pat=rep ...] [command]' format, COMMAND is
|
||||
re-executed after the substitution OLD=NEW is performed.
|
||||
|
||||
A useful alias to use with this is r='fc -s', so that typing `r cc'
|
||||
runs the last command beginning with `cc' and typing `r' re-executes
|
||||
the last command.
|
||||
|
||||
Exit Status:
|
||||
Returns success or status of executed command; non-zero if an error occurs.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (HISTORY)
|
||||
#ifndef _MINIX
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#include "../bashtypes.h"
|
||||
#include "posixstat.h"
|
||||
#if ! defined(_MINIX) && defined (HAVE_SYS_FILE_H)
|
||||
# include <sys/file.h>
|
||||
#endif
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <chartypes.h>
|
||||
|
||||
#include "../bashansi.h"
|
||||
#include "../bashintl.h"
|
||||
#include <errno.h>
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../builtins.h"
|
||||
#include "../flags.h"
|
||||
#include "../bashhist.h"
|
||||
#include "maxpath.h"
|
||||
#include <readline/history.h>
|
||||
#include "bashgetopt.h"
|
||||
#include "common.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
extern int current_command_line_count, saved_command_line_count;
|
||||
extern int literal_history;
|
||||
extern int posixly_correct;
|
||||
extern int subshell_environment, interactive_shell;
|
||||
|
||||
extern int unlink __P((const char *));
|
||||
|
||||
extern FILE *sh_mktmpfp __P((char *, int, char **));
|
||||
|
||||
/* **************************************************************** */
|
||||
/* */
|
||||
/* The K*rn shell style fc command (Fix Command) */
|
||||
/* */
|
||||
/* **************************************************************** */
|
||||
|
||||
/* fc builtin command (fix command) for Bash for those who
|
||||
like K*rn-style history better than csh-style.
|
||||
|
||||
fc [-e ename] [-nlr] [first] [last]
|
||||
|
||||
FIRST and LAST can be numbers specifying the range, or FIRST can be
|
||||
a string, which means the most recent command beginning with that
|
||||
string.
|
||||
|
||||
-e ENAME selects which editor to use. Default is FCEDIT, then EDITOR,
|
||||
then the editor which corresponds to the current readline editing
|
||||
mode, then vi.
|
||||
|
||||
-l means list lines instead of editing.
|
||||
-n means no line numbers listed.
|
||||
-r means reverse the order of the lines (making it newest listed first).
|
||||
|
||||
fc -e - [pat=rep ...] [command]
|
||||
fc -s [pat=rep ...] [command]
|
||||
|
||||
Equivalent to !command:sg/pat/rep execpt there can be multiple PAT=REP's.
|
||||
*/
|
||||
|
||||
/* Data structure describing a list of global replacements to perform. */
|
||||
typedef struct repl {
|
||||
struct repl *next;
|
||||
char *pat;
|
||||
char *rep;
|
||||
} REPL;
|
||||
|
||||
/* Accessors for HIST_ENTRY lists that are called HLIST. */
|
||||
#define histline(i) (hlist[(i)]->line)
|
||||
#define histdata(i) (hlist[(i)]->data)
|
||||
|
||||
#define FREE_RLIST() \
|
||||
do { \
|
||||
for (rl = rlist; rl; ) { \
|
||||
REPL *r; \
|
||||
r = rl->next; \
|
||||
if (rl->pat) \
|
||||
free (rl->pat); \
|
||||
if (rl->rep) \
|
||||
free (rl->rep); \
|
||||
free (rl); \
|
||||
rl = r; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static char *fc_dosubs __P((char *, REPL *));
|
||||
static char *fc_gethist __P((char *, HIST_ENTRY **));
|
||||
static int fc_gethnum __P((char *, HIST_ENTRY **));
|
||||
static int fc_number __P((WORD_LIST *));
|
||||
static void fc_replhist __P((char *));
|
||||
#ifdef INCLUDE_UNUSED
|
||||
static char *fc_readline __P((FILE *));
|
||||
static void fc_addhist __P((char *));
|
||||
#endif
|
||||
|
||||
/* String to execute on a file that we want to edit. */
|
||||
#define FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-vi}}"
|
||||
#if defined (STRICT_POSIX)
|
||||
# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-ed}"
|
||||
#else
|
||||
# define POSIX_FC_EDIT_COMMAND "${FCEDIT:-${EDITOR:-ed}}"
|
||||
#endif
|
||||
|
||||
int
|
||||
fc_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
register int i;
|
||||
register char *sep;
|
||||
int numbering, reverse, listing, execute;
|
||||
int histbeg, histend, last_hist, retval, opt, rh;
|
||||
FILE *stream;
|
||||
REPL *rlist, *rl;
|
||||
char *ename, *command, *newcom, *fcedit;
|
||||
HIST_ENTRY **hlist;
|
||||
char *fn;
|
||||
|
||||
numbering = 1;
|
||||
reverse = listing = execute = 0;
|
||||
ename = (char *)NULL;
|
||||
|
||||
/* Parse out the options and set which of the two forms we're in. */
|
||||
reset_internal_getopt ();
|
||||
lcurrent = list; /* XXX */
|
||||
while (fc_number (loptend = lcurrent) == 0 &&
|
||||
(opt = internal_getopt (list, ":e:lnrs")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'n':
|
||||
numbering = 0;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
listing = 1;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
reverse = 1;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
execute = 1;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
ename = list_optarg;
|
||||
break;
|
||||
|
||||
default:
|
||||
builtin_usage ();
|
||||
return (EX_USAGE);
|
||||
}
|
||||
}
|
||||
|
||||
list = loptend;
|
||||
|
||||
if (ename && (*ename == '-') && (ename[1] == '\0'))
|
||||
execute = 1;
|
||||
|
||||
/* The "execute" form of the command (re-run, with possible string
|
||||
substitutions). */
|
||||
if (execute)
|
||||
{
|
||||
rlist = (REPL *)NULL;
|
||||
while (list && ((sep = (char *)strchr (list->word->word, '=')) != NULL))
|
||||
{
|
||||
*sep++ = '\0';
|
||||
rl = (REPL *)xmalloc (sizeof (REPL));
|
||||
rl->next = (REPL *)NULL;
|
||||
rl->pat = savestring (list->word->word);
|
||||
rl->rep = savestring (sep);
|
||||
|
||||
if (rlist == NULL)
|
||||
rlist = rl;
|
||||
else
|
||||
{
|
||||
rl->next = rlist;
|
||||
rlist = rl;
|
||||
}
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
/* If we have a list of substitutions to do, then reverse it
|
||||
to get the replacements in the proper order. */
|
||||
|
||||
rlist = REVERSE_LIST (rlist, REPL *);
|
||||
|
||||
hlist = history_list ();
|
||||
|
||||
/* If we still have something in list, it is a command spec.
|
||||
Otherwise, we use the most recent command in time. */
|
||||
command = fc_gethist (list ? list->word->word : (char *)NULL, hlist);
|
||||
|
||||
if (command == NULL)
|
||||
{
|
||||
builtin_error (_("no command found"));
|
||||
if (rlist)
|
||||
FREE_RLIST ();
|
||||
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (rlist)
|
||||
{
|
||||
newcom = fc_dosubs (command, rlist);
|
||||
free (command);
|
||||
FREE_RLIST ();
|
||||
command = newcom;
|
||||
}
|
||||
|
||||
fprintf (stderr, "%s\n", command);
|
||||
fc_replhist (command); /* replace `fc -s' with command */
|
||||
/* Posix says that the re-executed commands should be entered into the
|
||||
history. */
|
||||
return (parse_and_execute (command, "fc", SEVAL_NOHIST));
|
||||
}
|
||||
|
||||
/* This is the second form of the command (the list-or-edit-and-rerun
|
||||
form). */
|
||||
hlist = history_list ();
|
||||
if (hlist == 0)
|
||||
return (EXECUTION_SUCCESS);
|
||||
for (i = 0; hlist[i]; i++);
|
||||
|
||||
/* With the Bash implementation of history, the current command line
|
||||
("fc blah..." and so on) is already part of the history list by
|
||||
the time we get to this point. This just skips over that command
|
||||
and makes the last command that this deals with be the last command
|
||||
the user entered before the fc. We need to check whether the
|
||||
line was actually added (HISTIGNORE may have caused it to not be),
|
||||
so we check hist_last_line_added. */
|
||||
|
||||
/* Even though command substitution through parse_and_execute turns off
|
||||
remember_on_history, command substitution in a shell when set -o history
|
||||
has been enabled (interactive or not) should use it in the last_hist
|
||||
calculation as if it were on. */
|
||||
rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
|
||||
last_hist = i - rh - hist_last_line_added;
|
||||
|
||||
/* XXX */
|
||||
if (i == last_hist && hlist[last_hist] == 0)
|
||||
while (saved_command_line_count > 0 && last_hist >= 0 && hlist[last_hist] == 0)
|
||||
last_hist--;
|
||||
if (last_hist < 0)
|
||||
{
|
||||
sh_erange ((char *)NULL, _("history specification"));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (list)
|
||||
{
|
||||
histbeg = fc_gethnum (list->word->word, hlist);
|
||||
list = list->next;
|
||||
|
||||
if (list)
|
||||
histend = fc_gethnum (list->word->word, hlist);
|
||||
else
|
||||
histend = listing ? last_hist : histbeg;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The default for listing is the last 16 history items. */
|
||||
if (listing)
|
||||
{
|
||||
histend = last_hist;
|
||||
histbeg = histend - 16 + 1; /* +1 because loop below uses >= */
|
||||
if (histbeg < 0)
|
||||
histbeg = 0;
|
||||
}
|
||||
else
|
||||
/* For editing, it is the last history command. */
|
||||
histbeg = histend = last_hist;
|
||||
}
|
||||
|
||||
/* "When not listing, the fc command that caused the editing shall not be
|
||||
entered into the history list." */
|
||||
if (listing == 0 && hist_last_line_added)
|
||||
{
|
||||
bash_delete_last_history ();
|
||||
/* If we're editing a single command -- the last command in the
|
||||
history -- and we just removed the dummy command added by
|
||||
edit_and_execute_command (), we need to check whether or not we
|
||||
just removed the last command in the history and need to back
|
||||
the pointer up. remember_on_history is off because we're running
|
||||
in parse_and_execute(). */
|
||||
if (histbeg == histend && histend == last_hist && hlist[last_hist] == 0)
|
||||
last_hist = histbeg = --histend;
|
||||
}
|
||||
|
||||
/* We print error messages for line specifications out of range. */
|
||||
if ((histbeg < 0) || (histend < 0))
|
||||
{
|
||||
sh_erange ((char *)NULL, _("history specification"));
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (histend < histbeg)
|
||||
{
|
||||
i = histend;
|
||||
histend = histbeg;
|
||||
histbeg = i;
|
||||
|
||||
reverse = 1;
|
||||
}
|
||||
|
||||
if (listing)
|
||||
stream = stdout;
|
||||
else
|
||||
{
|
||||
numbering = 0;
|
||||
stream = sh_mktmpfp ("bash-fc", MT_USERANDOM|MT_USETMPDIR, &fn);
|
||||
if (stream == 0)
|
||||
{
|
||||
builtin_error (_("%s: cannot open temp file: %s"), fn ? fn : "", strerror (errno));
|
||||
FREE (fn);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = reverse ? histend : histbeg; reverse ? i >= histbeg : i <= histend; reverse ? i-- : i++)
|
||||
{
|
||||
QUIT;
|
||||
if (numbering)
|
||||
fprintf (stream, "%d", i + history_base);
|
||||
if (listing)
|
||||
{
|
||||
if (posixly_correct)
|
||||
fputs ("\t", stream);
|
||||
else
|
||||
fprintf (stream, "\t%c", histdata (i) ? '*' : ' ');
|
||||
}
|
||||
fprintf (stream, "%s\n", histline (i));
|
||||
}
|
||||
|
||||
if (listing)
|
||||
return (sh_chkwrite (EXECUTION_SUCCESS));
|
||||
|
||||
fflush (stream);
|
||||
if (ferror (stream))
|
||||
{
|
||||
sh_wrerror ();
|
||||
fclose (stream);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
fclose (stream);
|
||||
|
||||
/* Now edit the file of commands. */
|
||||
if (ename)
|
||||
{
|
||||
command = (char *)xmalloc (strlen (ename) + strlen (fn) + 2);
|
||||
sprintf (command, "%s %s", ename, fn);
|
||||
}
|
||||
else
|
||||
{
|
||||
fcedit = posixly_correct ? POSIX_FC_EDIT_COMMAND : FC_EDIT_COMMAND;
|
||||
command = (char *)xmalloc (3 + strlen (fcedit) + strlen (fn));
|
||||
sprintf (command, "%s %s", fcedit, fn);
|
||||
}
|
||||
retval = parse_and_execute (command, "fc", SEVAL_NOHIST);
|
||||
if (retval != EXECUTION_SUCCESS)
|
||||
{
|
||||
unlink (fn);
|
||||
free (fn);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
/* Make sure parse_and_execute doesn't turn this off, even though a
|
||||
call to parse_and_execute farther up the function call stack (e.g.,
|
||||
if this is called by vi_edit_and_execute_command) may have already
|
||||
called bash_history_disable. */
|
||||
remember_on_history = 1;
|
||||
|
||||
/* Turn on the `v' flag while fc_execute_file runs so the commands
|
||||
will be echoed as they are read by the parser. */
|
||||
begin_unwind_frame ("fc builtin");
|
||||
add_unwind_protect ((Function *)xfree, fn);
|
||||
add_unwind_protect (unlink, fn);
|
||||
unwind_protect_int (echo_input_at_read);
|
||||
echo_input_at_read = 1;
|
||||
|
||||
retval = fc_execute_file (fn);
|
||||
|
||||
run_unwind_frame ("fc builtin");
|
||||
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* Return 1 if LIST->word->word is a legal number for fc's use. */
|
||||
static int
|
||||
fc_number (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (list == 0)
|
||||
return 0;
|
||||
s = list->word->word;
|
||||
if (*s == '-')
|
||||
s++;
|
||||
return (legal_number (s, (intmax_t *)NULL));
|
||||
}
|
||||
|
||||
/* Return an absolute index into HLIST which corresponds to COMMAND. If
|
||||
COMMAND is a number, then it was specified in relative terms. If it
|
||||
is a string, then it is the start of a command line present in HLIST. */
|
||||
static int
|
||||
fc_gethnum (command, hlist)
|
||||
char *command;
|
||||
HIST_ENTRY **hlist;
|
||||
{
|
||||
int sign, n, clen, rh;
|
||||
register int i, j;
|
||||
register char *s;
|
||||
|
||||
sign = 1;
|
||||
/* Count history elements. */
|
||||
for (i = 0; hlist[i]; i++);
|
||||
|
||||
/* With the Bash implementation of history, the current command line
|
||||
("fc blah..." and so on) is already part of the history list by
|
||||
the time we get to this point. This just skips over that command
|
||||
and makes the last command that this deals with be the last command
|
||||
the user entered before the fc. We need to check whether the
|
||||
line was actually added (HISTIGNORE may have caused it to not be),
|
||||
so we check hist_last_line_added. This needs to agree with the
|
||||
calculation of last_hist in fc_builtin above. */
|
||||
/* Even though command substitution through parse_and_execute turns off
|
||||
remember_on_history, command substitution in a shell when set -o history
|
||||
has been enabled (interactive or not) should use it in the last_hist
|
||||
calculation as if it were on. */
|
||||
rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
|
||||
i -= rh + hist_last_line_added;
|
||||
|
||||
/* No specification defaults to most recent command. */
|
||||
if (command == NULL)
|
||||
return (i);
|
||||
|
||||
/* Otherwise, there is a specification. It can be a number relative to
|
||||
the current position, or an absolute history number. */
|
||||
s = command;
|
||||
|
||||
/* Handle possible leading minus sign. */
|
||||
if (s && (*s == '-'))
|
||||
{
|
||||
sign = -1;
|
||||
s++;
|
||||
}
|
||||
|
||||
if (s && DIGIT(*s))
|
||||
{
|
||||
n = atoi (s);
|
||||
n *= sign;
|
||||
|
||||
/* If the value is negative or zero, then it is an offset from
|
||||
the current history item. */
|
||||
if (n < 0)
|
||||
{
|
||||
n += i + 1;
|
||||
return (n < 0 ? 0 : n);
|
||||
}
|
||||
else if (n == 0)
|
||||
return (i);
|
||||
else
|
||||
{
|
||||
n -= history_base;
|
||||
return (i < n ? i : n);
|
||||
}
|
||||
}
|
||||
|
||||
clen = strlen (command);
|
||||
for (j = i; j >= 0; j--)
|
||||
{
|
||||
if (STREQN (command, histline (j), clen))
|
||||
return (j);
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Locate the most recent history line which begins with
|
||||
COMMAND in HLIST, and return a malloc()'ed copy of it. */
|
||||
static char *
|
||||
fc_gethist (command, hlist)
|
||||
char *command;
|
||||
HIST_ENTRY **hlist;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (hlist == 0)
|
||||
return ((char *)NULL);
|
||||
|
||||
i = fc_gethnum (command, hlist);
|
||||
|
||||
if (i >= 0)
|
||||
return (savestring (histline (i)));
|
||||
else
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_UNUSED
|
||||
/* Read the edited history lines from STREAM and return them
|
||||
one at a time. This can read unlimited length lines. The
|
||||
caller should free the storage. */
|
||||
static char *
|
||||
fc_readline (stream)
|
||||
FILE *stream;
|
||||
{
|
||||
register int c;
|
||||
int line_len = 0, lindex = 0;
|
||||
char *line = (char *)NULL;
|
||||
|
||||
while ((c = getc (stream)) != EOF)
|
||||
{
|
||||
if ((lindex + 2) >= line_len)
|
||||
line = (char *)xrealloc (line, (line_len += 128));
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
line[lindex++] = '\n';
|
||||
line[lindex++] = '\0';
|
||||
return (line);
|
||||
}
|
||||
else
|
||||
line[lindex++] = c;
|
||||
}
|
||||
|
||||
if (!lindex)
|
||||
{
|
||||
if (line)
|
||||
free (line);
|
||||
|
||||
return ((char *)NULL);
|
||||
}
|
||||
|
||||
if (lindex + 2 >= line_len)
|
||||
line = (char *)xrealloc (line, lindex + 3);
|
||||
|
||||
line[lindex++] = '\n'; /* Finish with newline if none in file */
|
||||
line[lindex++] = '\0';
|
||||
return (line);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Perform the SUBS on COMMAND.
|
||||
SUBS is a list of substitutions, and COMMAND is a simple string.
|
||||
Return a pointer to a malloc'ed string which contains the substituted
|
||||
command. */
|
||||
static char *
|
||||
fc_dosubs (command, subs)
|
||||
char *command;
|
||||
REPL *subs;
|
||||
{
|
||||
register char *new, *t;
|
||||
register REPL *r;
|
||||
|
||||
for (new = savestring (command), r = subs; r; r = r->next)
|
||||
{
|
||||
t = strsub (new, r->pat, r->rep, 1);
|
||||
free (new);
|
||||
new = t;
|
||||
}
|
||||
return (new);
|
||||
}
|
||||
|
||||
/* Use `command' to replace the last entry in the history list, which,
|
||||
by this time, is `fc blah...'. The intent is that the new command
|
||||
become the history entry, and that `fc' should never appear in the
|
||||
history list. This way you can do `r' to your heart's content. */
|
||||
static void
|
||||
fc_replhist (command)
|
||||
char *command;
|
||||
{
|
||||
int n;
|
||||
|
||||
if (command == 0 || *command == '\0')
|
||||
return;
|
||||
|
||||
n = strlen (command);
|
||||
if (command[n - 1] == '\n')
|
||||
command[n - 1] = '\0';
|
||||
|
||||
if (command && *command)
|
||||
{
|
||||
bash_delete_last_history ();
|
||||
maybe_add_history (command); /* Obeys HISTCONTROL setting. */
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef INCLUDE_UNUSED
|
||||
/* Add LINE to the history, after removing a single trailing newline. */
|
||||
static void
|
||||
fc_addhist (line)
|
||||
char *line;
|
||||
{
|
||||
register int n;
|
||||
|
||||
if (line == 0 || *line == 0)
|
||||
return;
|
||||
|
||||
n = strlen (line);
|
||||
|
||||
if (line[n - 1] == '\n')
|
||||
line[n - 1] = '\0';
|
||||
|
||||
if (line && *line)
|
||||
maybe_add_history (line); /* Obeys HISTCONTROL setting. */
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* HISTORY */
|
||||
+11
-5
@@ -5,12 +5,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Fri Jan 15 10:50:42 EST 2010
|
||||
.\" Last Change: Sat Apr 17 23:24:15 EDT 2010
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2010 January 15" "GNU Bash-4.1"
|
||||
.TH BASH 1 "2010 April 17" "GNU Bash-4.1"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -50,8 +50,8 @@ bash \- GNU Bourne-Again SHell
|
||||
[options]
|
||||
[file]
|
||||
.SH COPYRIGHT
|
||||
.if n Bash is Copyright (C) 1989-2009 by the Free Software Foundation, Inc.
|
||||
.if t Bash is Copyright \(co 1989-2009 by the Free Software Foundation, Inc.
|
||||
.if n Bash is Copyright (C) 1989-2010 by the Free Software Foundation, Inc.
|
||||
.if t Bash is Copyright \(co 1989-2010 by the Free Software Foundation, Inc.
|
||||
.SH DESCRIPTION
|
||||
.B Bash
|
||||
is an \fBsh\fR-compatible command language interpreter that
|
||||
@@ -5159,7 +5159,8 @@ have a slash appended (subject to the value of
|
||||
.B match\-hidden\-files (On)
|
||||
This variable, when set to \fBOn\fP, causes readline to match files whose
|
||||
names begin with a `.' (hidden files) when performing filename
|
||||
completion, unless the leading `.' is
|
||||
completion.
|
||||
If set to \fBOff\fP, the leading `.' must be
|
||||
supplied by the user in the filename to be completed.
|
||||
.TP
|
||||
.B output\-meta (Off)
|
||||
@@ -8064,6 +8065,11 @@ beginning with \fB\e0\fP may contain up to four digits),
|
||||
and \fB%q\fP causes \fBprintf\fP to output the corresponding
|
||||
\fIargument\fP in a format that can be reused as shell input.
|
||||
.sp 1
|
||||
Arguments to non-string format specifiers are treated as C constants,
|
||||
except that a leading plus or minus sign is allowed, and if the leading
|
||||
character is a single or double quote, the value is the ASCII value of
|
||||
the following character.
|
||||
.sp 1
|
||||
The \fB\-v\fP option causes the output to be assigned to the variable
|
||||
\fIvar\fP rather than being printed to the standard output.
|
||||
.sp 1
|
||||
|
||||
+10
-4
@@ -5,12 +5,12 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@po.cwru.edu
|
||||
.\"
|
||||
.\" Last Change: Fri Jan 15 10:50:42 EST 2010
|
||||
.\" Last Change: Sat Apr 17 23:24:15 EDT 2010
|
||||
.\"
|
||||
.\" bash_builtins, strip all but Built-Ins section
|
||||
.if \n(zZ=1 .ig zZ
|
||||
.if \n(zY=1 .ig zY
|
||||
.TH BASH 1 "2010 January 15" "GNU Bash-4.1"
|
||||
.TH BASH 1 "2010 April 17" "GNU Bash-4.1"
|
||||
.\"
|
||||
.\" There's some problem with having a `@'
|
||||
.\" in a tagged paragraph with the BSD man macros.
|
||||
@@ -3902,7 +3902,7 @@ turned on to be used in an expression.
|
||||
.PP
|
||||
Constants with a leading 0 are interpreted as octal numbers.
|
||||
A leading 0x or 0X denotes hexadecimal.
|
||||
Otherwise, numbers take the form [\fIbase#\fP]n, where \fIbase\fP
|
||||
Otherwise, numbers take the form [\fIbase#\fP]n, where the optional \fIbase\fP
|
||||
is a decimal number between 2 and 64 representing the arithmetic
|
||||
base, and \fIn\fP is a number in that base.
|
||||
If \fIbase#\fP is omitted, then base 10 is used.
|
||||
@@ -5159,7 +5159,8 @@ have a slash appended (subject to the value of
|
||||
.B match\-hidden\-files (On)
|
||||
This variable, when set to \fBOn\fP, causes readline to match files whose
|
||||
names begin with a `.' (hidden files) when performing filename
|
||||
completion, unless the leading `.' is
|
||||
completion.
|
||||
If set to \fBOff\fP, the leading `.' must be
|
||||
supplied by the user in the filename to be completed.
|
||||
.TP
|
||||
.B output\-meta (Off)
|
||||
@@ -8064,6 +8065,11 @@ beginning with \fB\e0\fP may contain up to four digits),
|
||||
and \fB%q\fP causes \fBprintf\fP to output the corresponding
|
||||
\fIargument\fP in a format that can be reused as shell input.
|
||||
.sp 1
|
||||
Arguments to non-string format specifiers are treated as C constants,
|
||||
except that a leading plus or minus sign is allowed, and if the leading
|
||||
character is a single or double quote, the value is the ASCII value of
|
||||
the following character.
|
||||
.sp 1
|
||||
The \fB\-v\fP option causes the output to be assigned to the variable
|
||||
\fIvar\fP rather than being printed to the standard output.
|
||||
.sp 1
|
||||
|
||||
+6
-1
@@ -16,7 +16,7 @@ This is Edition @value{EDITION}, last updated @value{UPDATED},
|
||||
of @cite{The GNU Bash Reference Manual},
|
||||
for @code{Bash}, Version @value{VERSION}.
|
||||
|
||||
Copyright @copyright{} 1988--2009 Free Software Foundation, Inc.
|
||||
Copyright @copyright{} 1988--2010 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
@@ -3713,6 +3713,11 @@ beginning with @samp{\0} may contain up to four digits),
|
||||
and @samp{%q} causes @code{printf} to output the
|
||||
corresponding @var{argument} in a format that can be reused as shell input.
|
||||
|
||||
Arguments to non-string format specifiers are treated as C language constants,
|
||||
except that a leading plus or minus sign is allowed, and if the leading
|
||||
character is a single or double quote, the value is the ASCII value of
|
||||
the following character.
|
||||
|
||||
The @option{-v} option causes the output to be assigned to the variable
|
||||
@var{var} rather than being printed to the standard output.
|
||||
|
||||
|
||||
+6
-1
@@ -3713,6 +3713,11 @@ beginning with @samp{\0} may contain up to four digits),
|
||||
and @samp{%q} causes @code{printf} to output the
|
||||
corresponding @var{argument} in a format that can be reused as shell input.
|
||||
|
||||
Arguments to non-string format specifiers are treated as C language constants,
|
||||
except that a leading plus or minus sign is allowed, and if the leading
|
||||
character is a single or double quote, the value is the ASCII value of
|
||||
the following character.
|
||||
|
||||
The @option{-v} option causes the output to be assigned to the variable
|
||||
@var{var} rather than being printed to the standard output.
|
||||
|
||||
@@ -5966,7 +5971,7 @@ to be used in an expression.
|
||||
|
||||
Constants with a leading 0 are interpreted as octal numbers.
|
||||
A leading @samp{0x} or @samp{0X} denotes hexadecimal. Otherwise,
|
||||
numbers take the form [@var{base}@code{#}]@var{n}, where @var{base}
|
||||
numbers take the form [@var{base}@code{#}]@var{n}, where the optional @var{base}
|
||||
is a decimal number between 2 and 64 representing the arithmetic
|
||||
base, and @var{n} is a number in that base. If @var{base}@code{#} is
|
||||
omitted, then base 10 is used.
|
||||
|
||||
+3
-3
@@ -2,9 +2,9 @@
|
||||
Copyright (C) 1988-2010 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Fri Jan 15 10:50:20 EST 2010
|
||||
@set LASTCHANGE Sat Apr 17 23:23:55 EDT 2010
|
||||
|
||||
@set EDITION 4.1
|
||||
@set VERSION 4.1
|
||||
@set UPDATED 15 January 2010
|
||||
@set UPDATED-MONTH January 2010
|
||||
@set UPDATED 17 April 2010
|
||||
@set UPDATED-MONTH April 2010
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
@ignore
|
||||
Copyright (C) 1988-2010 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set LASTCHANGE Fri Jan 15 10:50:20 EST 2010
|
||||
|
||||
@set EDITION 4.1
|
||||
@set VERSION 4.1
|
||||
@set UPDATED 15 January 2010
|
||||
@set UPDATED-MONTH January 2010
|
||||
@@ -4381,12 +4381,25 @@ execute_builtin_or_function (words, builtin, var, redirects,
|
||||
{
|
||||
int result;
|
||||
REDIRECT *saved_undo_list;
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
int ofifo, nfifo, osize;
|
||||
char *ofifo_list;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
ofifo = num_fifos ();
|
||||
ofifo_list = copy_fifo_list (&osize);
|
||||
#endif
|
||||
|
||||
if (do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE) != 0)
|
||||
{
|
||||
cleanup_redirects (redirection_undo_list);
|
||||
redirection_undo_list = (REDIRECT *)NULL;
|
||||
dispose_exec_redirects ();
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
free (ofifo_list);
|
||||
#endif
|
||||
return (EX_REDIRFAIL); /* was EXECUTION_FAILURE */
|
||||
}
|
||||
|
||||
@@ -4448,6 +4461,14 @@ execute_builtin_or_function (words, builtin, var, redirects,
|
||||
redirection_undo_list = (REDIRECT *)NULL;
|
||||
}
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
/* Close any FIFOs created by this builtin or function. */
|
||||
nfifo = num_fifos ();
|
||||
if (nfifo > ofifo)
|
||||
close_new_fifos (ofifo_list, osize);
|
||||
free (ofifo_list);
|
||||
#endif
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
+19
-3
@@ -3812,15 +3812,13 @@ run_builtin:
|
||||
if (already_forked)
|
||||
{
|
||||
/* reset_terminating_signals (); */ /* XXX */
|
||||
#if 1 /* XXX - bash-4.2 */
|
||||
itrace("execute_simple_command: forked builtin or shell function: calling restore_original_signals");
|
||||
#if 0 /* XXX - bash-4.2 */
|
||||
/* Reset the signal handlers in the child, but don't free the
|
||||
trap strings. Set a flag noting that we have to free the
|
||||
trap strings if we run trap to change a signal disposition. */
|
||||
reset_signal_handlers ();
|
||||
subshell_environment |= SUBSHELL_RESETTRAP;
|
||||
#else
|
||||
itrace("execute_simple_command: forked builtin or shell function: calling restore_original_signals");
|
||||
/* Cancel traps, in trap.c. */
|
||||
restore_original_signals ();
|
||||
#endif
|
||||
@@ -4383,6 +4381,16 @@ execute_builtin_or_function (words, builtin, var, redirects,
|
||||
{
|
||||
int result;
|
||||
REDIRECT *saved_undo_list;
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
int ofifo, nfifo, osize;
|
||||
char *ofifo_list;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
ofifo = num_fifos ();
|
||||
ofifo_list = copy_fifo_list (&osize);
|
||||
#endif
|
||||
|
||||
if (do_redirections (redirects, RX_ACTIVE|RX_UNDOABLE) != 0)
|
||||
{
|
||||
@@ -4450,6 +4458,14 @@ execute_builtin_or_function (words, builtin, var, redirects,
|
||||
redirection_undo_list = (REDIRECT *)NULL;
|
||||
}
|
||||
|
||||
#if defined (PROCESS_SUBSTITUTION)
|
||||
/* Close any FIFOs created by this builtin or function. */
|
||||
nfifo = num_fifos ();
|
||||
if (nfifo > ofifo)
|
||||
close_new_fifos (ofifo_list, osize);
|
||||
free (ofifo_list);
|
||||
#endif
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ int _rl_completion_case_fold = 1;
|
||||
int _rl_completion_case_fold;
|
||||
#endif
|
||||
|
||||
/* If non-zero, don't match hidden files (filenames beginning with a `.' on
|
||||
/* If zero, don't match hidden files (filenames beginning with a `.' on
|
||||
Unix) when doing filename completion. */
|
||||
int _rl_match_hidden_files = 1;
|
||||
|
||||
|
||||
@@ -2094,9 +2094,9 @@ rl_filename_completion_function (text, state)
|
||||
else if (rl_completion_found_quote && rl_filename_dequoting_function)
|
||||
{
|
||||
/* delete single and double quotes */
|
||||
temp = (*rl_filename_dequoting_function) (users_dirname, rl_completion_quote_character);
|
||||
free (users_dirname);
|
||||
users_dirname = temp;
|
||||
temp = (*rl_filename_dequoting_function) (dirname, rl_completion_quote_character);
|
||||
free (dirname);
|
||||
dirname = temp;
|
||||
}
|
||||
directory = opendir (dirname);
|
||||
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
.\" Case Western Reserve University
|
||||
.\" chet@ins.CWRU.Edu
|
||||
.\"
|
||||
.\" Last Change: Fri Oct 9 12:57:27 EDT 2009
|
||||
.\" Last Change: Sat Apr 17 23:46:04 EDT 2010
|
||||
.\"
|
||||
.TH READLINE 3 "2009 October 9" "GNU Readline 6.1"
|
||||
.TH READLINE 3 "2009 April 17" "GNU Readline 6.1"
|
||||
.\"
|
||||
.\" File Name macro. This used to be `.PN', for Path Name,
|
||||
.\" but Sun doesn't seem to like that very much.
|
||||
@@ -34,8 +34,8 @@ readline \- get a line from a user with editing
|
||||
\fBreadline\fP (\fIconst char *prompt\fP);
|
||||
.fi
|
||||
.SH COPYRIGHT
|
||||
.if n Readline is Copyright (C) 1989\-2009 Free Software Foundation, Inc.
|
||||
.if t Readline is Copyright \(co 1989\-2009 Free Software Foundation, Inc.
|
||||
.if n Readline is Copyright (C) 1989\-2010 Free Software Foundation, Inc.
|
||||
.if t Readline is Copyright \(co 1989\-2010 Free Software Foundation, Inc.
|
||||
.SH DESCRIPTION
|
||||
.LP
|
||||
.B readline
|
||||
@@ -475,7 +475,8 @@ have a slash appended (subject to the value of
|
||||
.B match\-hidden\-files (On)
|
||||
This variable, when set to \fBOn\fP, causes readline to match files whose
|
||||
names begin with a `.' (hidden files) when performing filename
|
||||
completion, unless the leading `.' is
|
||||
completion.
|
||||
If set to \fBOff\fP, the leading `.' must be
|
||||
supplied by the user in the filename to be completed.
|
||||
.TP
|
||||
.B output\-meta (Off)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,7 +9,7 @@ use these features. There is a document entitled "readline.texinfo"
|
||||
which contains both end-user and programmer documentation for the
|
||||
GNU Readline Library.
|
||||
|
||||
Copyright (C) 1988--2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988--2010 Free Software Foundation, Inc.
|
||||
|
||||
Authored by Brian Fox and Chet Ramey.
|
||||
|
||||
@@ -570,7 +570,8 @@ The default is @samp{off}.
|
||||
@vindex match-hidden-files
|
||||
This variable, when set to @samp{on}, causes Readline to match files whose
|
||||
names begin with a @samp{.} (hidden files) when performing filename
|
||||
completion, unless the leading @samp{.} is
|
||||
completion.
|
||||
If set to @samp{off}, the leading @samp{.} must be
|
||||
supplied by the user in the filename to be completed.
|
||||
This variable is @samp{on} by default.
|
||||
|
||||
@@ -1579,7 +1580,7 @@ editing mode.
|
||||
While the Readline library does not have a full set of @code{vi}
|
||||
editing functions, it does contain enough to allow simple editing
|
||||
of the line. The Readline @code{vi} mode behaves as specified in
|
||||
the @sc{posix} 1003.2 standard.
|
||||
the @sc{posix} standard.
|
||||
|
||||
@ifset BashFeatures
|
||||
In order to switch interactively between @code{emacs} and @code{vi}
|
||||
|
||||
@@ -9,7 +9,7 @@ use these features. There is a document entitled "readline.texinfo"
|
||||
which contains both end-user and programmer documentation for the
|
||||
GNU Readline Library.
|
||||
|
||||
Copyright (C) 1988--2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988--2010 Free Software Foundation, Inc.
|
||||
|
||||
Authored by Brian Fox and Chet Ramey.
|
||||
|
||||
@@ -570,7 +570,8 @@ The default is @samp{off}.
|
||||
@vindex match-hidden-files
|
||||
This variable, when set to @samp{on}, causes Readline to match files whose
|
||||
names begin with a @samp{.} (hidden files) when performing filename
|
||||
completion, unless the leading @samp{.} is
|
||||
completion.
|
||||
If set to @samp{off}, the leading @samp{.} must be
|
||||
supplied by the user in the filename to be completed.
|
||||
This variable is @samp{on} by default.
|
||||
|
||||
@@ -1733,7 +1734,7 @@ exit status of 124. If a shell function returns 124, and changes
|
||||
the compspec associated with the command on which completion is being
|
||||
attempted (supplied as the first argument when the function is executed),
|
||||
programmable completion restarts from the beginning, with an
|
||||
attempt to find a compspec for that command. This allows a set of
|
||||
attempt to find a new compspec for that command. This allows a set of
|
||||
completions to be built dynamically as completion is attempted, rather than
|
||||
being loaded all at once.
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
@ignore
|
||||
Copyright (C) 1988-2009 Free Software Foundation, Inc.
|
||||
Copyright (C) 1988-2010 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set EDITION 6.1
|
||||
@set VERSION 6.1
|
||||
@set UPDATED 9 October 2009
|
||||
@set UPDATED-MONTH October 2009
|
||||
@set UPDATED April 17 2010
|
||||
@set UPDATED-MONTH April 2010
|
||||
|
||||
@set LASTCHANGE Fri Oct 9 12:57:58 EDT 2009
|
||||
@set LASTCHANGE Sat Apr 17 23:45:29 EDT 2010
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
@ignore
|
||||
Copyright (C) 1988-2010 Free Software Foundation, Inc.
|
||||
@end ignore
|
||||
|
||||
@set EDITION 6.1
|
||||
@set VERSION 6.1
|
||||
@set UPDATED April 17 2010
|
||||
@set UPDATED-MONTH April 2010
|
||||
|
||||
@set LASTCHANGE Sat Apr 17 23:45:29 EDT 2010
|
||||
@@ -427,17 +427,19 @@ rl_read_key ()
|
||||
/* If the user has an event function, then call it periodically. */
|
||||
if (rl_event_hook)
|
||||
{
|
||||
while (rl_event_hook && rl_get_char (&c) == 0)
|
||||
while (rl_event_hook)
|
||||
{
|
||||
(*rl_event_hook) ();
|
||||
RL_CHECK_SIGNALS ();
|
||||
if (rl_done) /* XXX - experimental */
|
||||
return ('\n');
|
||||
if (rl_gather_tyi () < 0) /* XXX - EIO */
|
||||
{
|
||||
rl_done = 1;
|
||||
return ('\n');
|
||||
}
|
||||
RL_CHECK_SIGNALS ();
|
||||
if (rl_get_char (&c) != 0)
|
||||
break;
|
||||
if (rl_done) /* XXX - experimental */
|
||||
return ('\n');
|
||||
(*rl_event_hook) ();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -250,6 +250,9 @@ int extended_quote = 1;
|
||||
/* The number of lines read from input while creating the current command. */
|
||||
int current_command_line_count;
|
||||
|
||||
/* The number of lines in a command saved while we run parse_and_execute */
|
||||
int saved_command_line_count;
|
||||
|
||||
/* The token that currently denotes the end of parse. */
|
||||
int shell_eof_token;
|
||||
|
||||
|
||||
@@ -3234,7 +3234,8 @@ parse_matched_pair (qc, open, close, lenp, flags)
|
||||
decide what the op is. We're really only concerned if it's % or
|
||||
#, so we can turn on a flag that says whether or not we should
|
||||
treat single quotes as special when inside a double-quoted
|
||||
${...} */
|
||||
${...}. This logic must agree with subst.c:extract_dollar_brace_string
|
||||
since they share the same defines. */
|
||||
if (flags & P_DOLBRACE)
|
||||
{
|
||||
if MBTEST(dolbrace_state == DOLBRACE_PARAM && ch == '%' && retind > 0)
|
||||
|
||||
@@ -439,7 +439,6 @@ here_document_to_fd (redirectee, ri)
|
||||
/* Make the document really temporary. Also make it the input. */
|
||||
fd2 = open (filename, O_RDONLY, 0600);
|
||||
|
||||
itrace("here_document_to_fd: %s open read-only to fd %d", filename, fd2);
|
||||
if (fd2 < 0)
|
||||
{
|
||||
r = errno;
|
||||
@@ -639,7 +638,8 @@ redir_open (filename, flags, mode, ri)
|
||||
#endif /* AFS */
|
||||
}
|
||||
|
||||
itrace("redir_open: %s opens to fd %d", filename, fd);
|
||||
itrace("redir_open: %s -> %d", filename, fd);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
@@ -4589,6 +4589,15 @@ static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
|
||||
static int nfifo;
|
||||
static int fifo_list_size;
|
||||
|
||||
char *
|
||||
copy_fifo_list (sizep)
|
||||
int *sizep;
|
||||
{
|
||||
if (sizep)
|
||||
*sizep = 0;
|
||||
return (char *)NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
add_fifo_list (pathname)
|
||||
char *pathname;
|
||||
@@ -4604,6 +4613,19 @@ add_fifo_list (pathname)
|
||||
nfifo++;
|
||||
}
|
||||
|
||||
void
|
||||
unlink_fifo (i)
|
||||
int i;
|
||||
{
|
||||
if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
|
||||
{
|
||||
unlink (fifo_list[i].file);
|
||||
free (fifo_list[i].file);
|
||||
fifo_list[i].file = (char *)NULL;
|
||||
fifo_list[i].proc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
unlink_fifo_list ()
|
||||
{
|
||||
@@ -4641,12 +4663,52 @@ unlink_fifo_list ()
|
||||
nfifo = 0;
|
||||
}
|
||||
|
||||
/* Take LIST, which is a bitmap denoting active FIFOs in fifo_list
|
||||
from some point in the past, and close all open FIFOs in fifo_list
|
||||
that are not marked as active in LIST. If LIST is NULL, close
|
||||
everything in fifo_list. LSIZE is the number of elements in LIST, in
|
||||
case it's larger than fifo_list_size (size of fifo_list). */
|
||||
void
|
||||
close_new_fifos (list, lsize)
|
||||
char *list;
|
||||
int lsize;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
itrace("close_new_fifos: list == 0, calling unlink_fifo_list");
|
||||
unlink_fifo_list ();
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < lsize; i++)
|
||||
if (list[i] == 0 && i < fifo_list_size && fifo_list[i].proc != -1)
|
||||
{
|
||||
itrace("close_new_fifos: closing %d", i);
|
||||
unlink_fifo (i);
|
||||
}
|
||||
|
||||
for (i = lsize; i < fifo_list_size; i++)
|
||||
{
|
||||
if (fifo_list[i].proc != -1)
|
||||
itrace("close_new_fifos: closing %d", i);
|
||||
unlink_fifo (i);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
fifos_pending ()
|
||||
{
|
||||
return nfifo;
|
||||
}
|
||||
|
||||
int
|
||||
num_fifos ()
|
||||
{
|
||||
return nfifo;
|
||||
}
|
||||
|
||||
static char *
|
||||
make_named_pipe ()
|
||||
{
|
||||
@@ -4673,11 +4735,30 @@ static char *dev_fd_list = (char *)NULL;
|
||||
static int nfds;
|
||||
static int totfds; /* The highest possible number of open files. */
|
||||
|
||||
char *
|
||||
copy_fifo_list (sizep)
|
||||
int *sizep;
|
||||
{
|
||||
char *ret;
|
||||
|
||||
if (nfds == 0 || totfds == 0)
|
||||
{
|
||||
if (sizep)
|
||||
*sizep = 0;
|
||||
return (char *)NULL;
|
||||
}
|
||||
|
||||
if (sizep)
|
||||
*sizep = totfds;
|
||||
ret = (char *)xmalloc (totfds);
|
||||
return (memcpy (ret, dev_fd_list, totfds));
|
||||
}
|
||||
|
||||
static void
|
||||
add_fifo_list (fd)
|
||||
int fd;
|
||||
{
|
||||
if (!dev_fd_list || fd >= totfds)
|
||||
if (dev_fd_list == 0 || fd >= totfds)
|
||||
{
|
||||
int ofds;
|
||||
|
||||
@@ -4702,6 +4783,24 @@ fifos_pending ()
|
||||
return 0; /* used for cleanup; not needed with /dev/fd */
|
||||
}
|
||||
|
||||
int
|
||||
num_fifos ()
|
||||
{
|
||||
return nfds;
|
||||
}
|
||||
|
||||
void
|
||||
unlink_fifo (fd)
|
||||
int fd;
|
||||
{
|
||||
if (dev_fd_list[fd])
|
||||
{
|
||||
close (fd);
|
||||
dev_fd_list[fd] = 0;
|
||||
nfds--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
unlink_fifo_list ()
|
||||
{
|
||||
@@ -4711,16 +4810,37 @@ unlink_fifo_list ()
|
||||
return;
|
||||
|
||||
for (i = 0; nfds && i < totfds; i++)
|
||||
if (dev_fd_list[i])
|
||||
{
|
||||
close (i);
|
||||
dev_fd_list[i] = 0;
|
||||
nfds--;
|
||||
}
|
||||
unlink_fifo (i);
|
||||
|
||||
nfds = 0;
|
||||
}
|
||||
|
||||
/* Take LIST, which is a snapshot copy of dev_fd_list from some point in
|
||||
the past, and close all open fds in dev_fd_list that are not marked
|
||||
as open in LIST. If LIST is NULL, close everything in dev_fd_list.
|
||||
LSIZE is the number of elements in LIST, in case it's larger than
|
||||
totfds (size of dev_fd_list). */
|
||||
void
|
||||
close_new_fifos (list, lsize)
|
||||
char *list;
|
||||
int lsize;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
unlink_fifo_list ();
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < lsize; i++)
|
||||
if (list[i] == 0 && i < totfds && dev_fd_list[i])
|
||||
unlink_fifo (i);
|
||||
|
||||
for (i = lsize; i < totfds; i++)
|
||||
unlink_fifo (i);
|
||||
}
|
||||
|
||||
#if defined (NOTDEF)
|
||||
print_dev_fd_list ()
|
||||
{
|
||||
|
||||
@@ -4589,6 +4589,15 @@ static struct temp_fifo *fifo_list = (struct temp_fifo *)NULL;
|
||||
static int nfifo;
|
||||
static int fifo_list_size;
|
||||
|
||||
char *
|
||||
copy_fifo_list (sizep)
|
||||
int *sizep;
|
||||
{
|
||||
if (sizep)
|
||||
*sizep = 0;
|
||||
return (char *)NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
add_fifo_list (pathname)
|
||||
char *pathname;
|
||||
@@ -4604,6 +4613,19 @@ add_fifo_list (pathname)
|
||||
nfifo++;
|
||||
}
|
||||
|
||||
void
|
||||
unlink_fifo (i)
|
||||
int i;
|
||||
{
|
||||
if ((fifo_list[i].proc == -1) || (kill(fifo_list[i].proc, 0) == -1))
|
||||
{
|
||||
unlink (fifo_list[i].file);
|
||||
free (fifo_list[i].file);
|
||||
fifo_list[i].file = (char *)NULL;
|
||||
fifo_list[i].proc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
unlink_fifo_list ()
|
||||
{
|
||||
@@ -4641,12 +4663,52 @@ unlink_fifo_list ()
|
||||
nfifo = 0;
|
||||
}
|
||||
|
||||
/* Take LIST, which is a bitmap denoting active FIFOs in fifo_list
|
||||
from some point in the past, and close all open FIFOs in fifo_list
|
||||
that are not marked as active in LIST. If LIST is NULL, close
|
||||
everything in fifo_list. LSIZE is the number of elements in LIST, in
|
||||
case it's larger than fifo_list_size (size of fifo_list). */
|
||||
void
|
||||
close_new_fifos (list, lsize)
|
||||
char *list;
|
||||
int lsize;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
itrace("close_new_fifos: list == 0, calling unlink_fifo_list");
|
||||
unlink_fifo_list ();
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < lsize; i++)
|
||||
if (list[i] == 0 && i < fifo_list_size && fifo_list[i].proc != -1)
|
||||
{
|
||||
itrace("close_new_fifos: closing %d", i);
|
||||
unlink_fifo (i);
|
||||
}
|
||||
|
||||
for (i = lsize; i < fifo_list_size; i++)
|
||||
{
|
||||
if (fifo_list[i].proc != -1)
|
||||
itrace("close_new_fifos: closing %d", i);
|
||||
unlink_fifo (i);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
fifos_pending ()
|
||||
{
|
||||
return nfifo;
|
||||
}
|
||||
|
||||
int
|
||||
num_fifos ()
|
||||
{
|
||||
return nfifo;
|
||||
}
|
||||
|
||||
static char *
|
||||
make_named_pipe ()
|
||||
{
|
||||
@@ -4673,11 +4735,31 @@ static char *dev_fd_list = (char *)NULL;
|
||||
static int nfds;
|
||||
static int totfds; /* The highest possible number of open files. */
|
||||
|
||||
char *
|
||||
copy_fifo_list (sizep)
|
||||
int *sizep;
|
||||
{
|
||||
char *ret;
|
||||
|
||||
if (nfds == 0 || totfds == 0)
|
||||
{
|
||||
if (sizep)
|
||||
*sizep = 0;
|
||||
return (char *)NULL;
|
||||
}
|
||||
|
||||
if (sizep)
|
||||
*sizep = totfds;
|
||||
ret = (char *)xmalloc (totfds);
|
||||
return (memcpy (ret, dev_fd_list, totfds));
|
||||
}
|
||||
|
||||
static void
|
||||
add_fifo_list (fd)
|
||||
int fd;
|
||||
{
|
||||
if (!dev_fd_list || fd >= totfds)
|
||||
itrace("add_fifo_list: adding %d", fd);
|
||||
if (dev_fd_list == 0 || fd >= totfds)
|
||||
{
|
||||
int ofds;
|
||||
|
||||
@@ -4702,6 +4784,24 @@ fifos_pending ()
|
||||
return 0; /* used for cleanup; not needed with /dev/fd */
|
||||
}
|
||||
|
||||
int
|
||||
num_fifos ()
|
||||
{
|
||||
return nfds;
|
||||
}
|
||||
|
||||
void
|
||||
unlink_fifo (fd)
|
||||
int fd;
|
||||
{
|
||||
if (dev_fd_list[fd])
|
||||
{
|
||||
close (fd);
|
||||
dev_fd_list[fd] = 0;
|
||||
nfds--;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
unlink_fifo_list ()
|
||||
{
|
||||
@@ -4711,16 +4811,45 @@ unlink_fifo_list ()
|
||||
return;
|
||||
|
||||
for (i = 0; nfds && i < totfds; i++)
|
||||
if (dev_fd_list[i])
|
||||
{
|
||||
close (i);
|
||||
dev_fd_list[i] = 0;
|
||||
nfds--;
|
||||
}
|
||||
unlink_fifo (i);
|
||||
|
||||
nfds = 0;
|
||||
}
|
||||
|
||||
/* Take LIST, which is a snapshot copy of dev_fd_list from some point in
|
||||
the past, and close all open fds in dev_fd_list that are not marked
|
||||
as open in LIST. If LIST is NULL, close everything in dev_fd_list.
|
||||
LSIZE is the number of elements in LIST, in case it's larger than
|
||||
totfds (size of dev_fd_list). */
|
||||
void
|
||||
close_new_fifos (list, lsize)
|
||||
char *list;
|
||||
int lsize;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
itrace("close_new_fifos: list == 0, calling unlink_fifo_list");
|
||||
unlink_fifo_list ();
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < lsize; i++)
|
||||
if (list[i] == 0 && i < totfds && dev_fd_list[i])
|
||||
{
|
||||
itrace("close_new_fifos: closing %d", i);
|
||||
unlink_fifo (i);
|
||||
}
|
||||
|
||||
for (i = lsize; i < totfds; i++)
|
||||
{
|
||||
if (dev_fd_list[i])
|
||||
itrace("close_new_fifos: closing %d", i);
|
||||
unlink_fifo (i);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined (NOTDEF)
|
||||
print_dev_fd_list ()
|
||||
{
|
||||
|
||||
@@ -254,7 +254,12 @@ extern WORD_DESC *command_substitute __P((char *, int));
|
||||
extern char *pat_subst __P((char *, char *, char *, int));
|
||||
|
||||
extern int fifos_pending __P((void));
|
||||
extern int num_fifos __P((void));
|
||||
extern void unlink_fifo_list __P((void));
|
||||
extern void unlink_fifo __P((int));
|
||||
|
||||
extern char *copy_fifo_list __P((int *));
|
||||
extern void unlink_new_fifos __P((char *, int));
|
||||
|
||||
extern WORD_LIST *list_string_with_quotes __P((char *));
|
||||
|
||||
|
||||
@@ -47,14 +47,15 @@
|
||||
#define ASS_MKASSOC 0x04
|
||||
|
||||
/* Flags for the string extraction functions. */
|
||||
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
|
||||
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
|
||||
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
|
||||
#define SX_COMMAND 0x08 /* extracting a shell script/command */
|
||||
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
|
||||
#define SX_NOESCCTLNUL 0x20 /* don't let CTLESC quote CTLNUL */
|
||||
#define SX_NOLONGJMP 0x40 /* don't longjmp on fatal error */
|
||||
#define SX_ARITHSUB 0x80 /* extracting $(( ... )) (currently unused) */
|
||||
#define SX_NOALLOC 0x0001 /* just skip; don't return substring */
|
||||
#define SX_VARNAME 0x0002 /* variable name; for string_extract () */
|
||||
#define SX_REQMATCH 0x0004 /* closing/matching delimiter required */
|
||||
#define SX_COMMAND 0x0008 /* extracting a shell script/command */
|
||||
#define SX_NOCTLESC 0x0010 /* don't honor CTLESC quoting */
|
||||
#define SX_NOESCCTLNUL 0x0020 /* don't let CTLESC quote CTLNUL */
|
||||
#define SX_NOLONGJMP 0x0040 /* don't longjmp on fatal error */
|
||||
#define SX_ARITHSUB 0x0080 /* extracting $(( ... )) (currently unused) */
|
||||
#define SX_POSIXEXP 0x0100 /* extracting new Posix pattern removal expansions in extract_dollar_brace_string */
|
||||
|
||||
/* Remove backslashes which are quoting backquotes from STRING. Modifies
|
||||
STRING, and returns a pointer to it. */
|
||||
@@ -252,8 +253,11 @@ extern WORD_LIST *expand_words_shellexp __P((WORD_LIST *));
|
||||
extern WORD_DESC *command_substitute __P((char *, int));
|
||||
extern char *pat_subst __P((char *, char *, char *, int));
|
||||
|
||||
extern char *copy_fifo_list __P((int *));
|
||||
extern int fifos_pending __P((void));
|
||||
extern int num_fifos __P((void));
|
||||
extern void unlink_fifo_list __P((void));
|
||||
extern void unlink_fifo __P((int));
|
||||
|
||||
extern WORD_LIST *list_string_with_quotes __P((char *));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user