commit bash-20070308 snapshot

This commit is contained in:
Chet Ramey
2011-12-07 09:04:35 -05:00
parent b5fabbae5c
commit 6ec48275ea
31 changed files with 4135 additions and 60 deletions
+16
View File
@@ -1 +1,17 @@
quit
break _rl_move_cursor_relative
att 29981
c
where
p _rl_last_c_pos
break rl_redisplay
c
break update_line
c
detach
att 29981
c
i break
att 112
c
quit
+34
View File
@@ -14347,3 +14347,37 @@ CWRU/audit-patch
- patch from Steve Grubb of RedHat <sgrubb@redhat.com> to make bash
audit root's behavior by logging commands using his audit
framework. Enabled if the shell's name is `aubash'.
3/8
---
jobs.c
- use WSTATUS (p->status) instead of bare p->status. Fix from
Jim Brown <jim.brown@rsmas.miami.edu>
3/9
---
lib/readline/{complete,input,isearch,misc,readline,text,vi_mode}.c
- make sure cases where rl_read_key returns -1 (usually due to EIO
because the controlling tty has gone away) are handled correctly.
Prompted by report from Thomas Loeber <ifp@loeber1.de>
3/10
----
sig.c
- new function, top_level_cleanup, callable from contexts where some
cleanup needs to be performed before a non-fatal call to
jump_to_top_level
sig.h
- new extern declaration for top_level_cleanup
builtins/common.c
- add calls to top_level_cleanup before calls to jump_to_top_level
in a builtin command context (no_args(), get_numeric_arg()). Fixes
bug reported by Ian Watson
lib/readline/display.c
- in _rl_move_cursor_relative, use `new' when comparing against
the last invisible character in the prompt, since they both denote
buffer indices when in a multibyte locale, whereas `dpos' is a
display position
+36 -1
View File
@@ -14339,4 +14339,39 @@ lib/readline/text.c
- change rl_forward_char to allow moving to the end of the line when
using the arrow keys in vi insertion mode, rather than having the
behavior identical between vi command and insertion modes. Change
suggested by Hugh Sasse
suggested by Hugh Sasse <hgs@dmu.ac.uk>
2/19
----
CWRU/audit-patch
- patch from Steve Grubb of RedHat <sgrubb@redhat.com> to make bash
audit root's behavior by logging commands using his audit
framework. Enabled if the shell's name is `aubash'.
3/8
---
jobs.c
- use WSTATUS (p->status) instead of bare p->status. Fix from
Jim Brown <jim.brown@rsmas.miami.edu>
3/9
---
lib/readline/{complete,input,isearch,misc,readline,text,vi_mode}.c
- make sure cases where rl_read_key returns -1 (usually due to EIO
because the controlling tty has gone away) are handled correctly.
Prompted by report from Thomas Loeber <ifp@loeber1.de>
3/10
----
sig.c
- new function, top_level_cleanup, callable from contexts where some
cleanup needs to be performed before a non-fatal call to
jump_to_top_level
sig.h
- new extern declaration for top_level_cleanup
builtins/common.c
- add calls to top_level_cleanup before calls to jump_to_top_level
in a builtin command context (no_args(), get_numeric_arg()). Fixes
bug reported by Ian Watson
+6 -2
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -131,6 +131,7 @@ no_args (list)
if (list)
{
builtin_error (_("too many arguments"));
top_level_cleanup ();
jump_to_top_level (DISCARD);
}
}
@@ -395,7 +396,10 @@ get_numeric_arg (list, fatal)
if (fatal)
throw_to_top_level ();
else
jump_to_top_level (DISCARD);
{
top_level_cleanup ();
jump_to_top_level (DISCARD);
}
}
no_args (list->next);
}
+10 -3
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -69,7 +69,7 @@ extern int last_command_exit_value;
extern int running_trap;
extern int posixly_correct;
extern char *this_command_name, *shell_name;
extern char *bash_getcwd_errstr;
extern const char * const bash_getcwd_errstr;
/* Used by some builtins and the mainline code. */
sh_builtin_func_t *last_shell_builtin = (sh_builtin_func_t *)NULL;
@@ -395,7 +395,10 @@ get_numeric_arg (list, fatal)
if (fatal)
throw_to_top_level ();
else
jump_to_top_level (DISCARD);
{
top_level_cleanup ();
jump_to_top_level (DISCARD);
}
}
no_args (list->next);
}
@@ -475,7 +478,11 @@ get_working_directory (for_whom)
if (the_current_working_directory == 0)
{
#if defined (GETCWD_BROKEN)
the_current_working_directory = getcwd (0, PATH_MAX);
#else
the_current_working_directory = getcwd (0, 0);
#endif
if (the_current_working_directory == 0)
{
fprintf (stderr, _("%s: error retrieving current directory: %s: %s\n"),
+1 -1
View File
@@ -1,7 +1,7 @@
/* config-bot.h */
/* modify settings or make new ones based on what autoconf tells us. */
/* Copyright (C) 1989-2002 Free Software Foundation, Inc.
/* Copyright (C) 1989-2007 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
+2 -2
View File
@@ -2228,7 +2228,7 @@ raw_job_exit_status (job)
p = jobs[job]->pipe;
do
{
if (p->status != EXECUTION_SUCCESS) fail = p->status;
if (WSTATUS (p->status) != EXECUTION_SUCCESS) fail = WSTATUS(p->status);
p = p->next;
}
while (p != jobs[job]->pipe);
@@ -2370,7 +2370,7 @@ wait_for (pid)
if (r == -1 && errno == ECHILD)
{
child->running = PS_DONE;
child->status = 0; /* XXX -- can't find true status */
WSTATUS (child->status) = 0; /* XXX -- can't find true status */
js.c_living = 0; /* no living child processes */
if (job != NO_JOB)
{
+1 -1
View File
@@ -438,7 +438,7 @@ get_y_or_n (for_pager)
return (1);
if (c == 'n' || c == 'N' || c == RUBOUT)
return (0);
if (c == ABORT_CHAR)
if (c == ABORT_CHAR || c < 0)
_rl_abort_internal ();
if (for_pager && (c == NEWLINE || c == RETURN))
return (2);
+18 -5
View File
@@ -325,6 +325,12 @@ int rl_completion_mark_symlink_dirs;
/* If non-zero, inhibit completion (temporarily). */
int rl_inhibit_completion;
/* Set to the last key used to invoke one of the completion functions */
int rl_completion_invoking_key;
/* If non-zero, sort the completion matches. On by default. */
int rl_sort_completion_matches = 1;
/* Variables local to this file. */
/* Local variable states what happened during the last completion attempt. */
@@ -343,6 +349,8 @@ int
rl_complete (ignore, invoking_key)
int ignore, invoking_key;
{
rl_completion_invoking_key = invoking_key;
if (rl_inhibit_completion)
return (_rl_insert_char (ignore, invoking_key));
else if (rl_last_func == rl_complete && !completion_changed_buffer)
@@ -360,6 +368,7 @@ int
rl_possible_completions (ignore, invoking_key)
int ignore, invoking_key;
{
rl_completion_invoking_key = invoking_key;
return (rl_complete_internal ('?'));
}
@@ -367,6 +376,7 @@ int
rl_insert_completions (ignore, invoking_key)
int ignore, invoking_key;
{
rl_completion_invoking_key = invoking_key;
return (rl_complete_internal ('*'));
}
@@ -999,7 +1009,7 @@ remove_duplicate_matches (matches)
/* Sort the array without matches[0], since we need it to
stay in place no matter what. */
if (i)
if (i && rl_sort_completion_matches)
qsort (matches+1, i-1, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
/* Remember the lowest common denominator for it may be unique. */
@@ -1167,7 +1177,8 @@ compute_lcd_of_matches (match_list, matches, text)
}
/* sort the list to get consistent answers. */
qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
if (rl_sort_completion_matches)
qsort (match_list+1, matches, sizeof(char *), (QSFUNC *)_rl_qsort_string_compare);
si = strlen (text);
if (si <= low)
@@ -1285,7 +1296,7 @@ rl_display_match_list (matches, len, max)
0 < len <= limit implies count = 1. */
/* Sort the items if they are not already sorted. */
if (rl_ignore_completion_duplicates == 0)
if (rl_ignore_completion_duplicates == 0 && rl_sort_completion_matches)
qsort (matches + 1, len, sizeof (char *), (QSFUNC *)_rl_qsort_string_compare);
rl_crlf ();
@@ -2116,8 +2127,8 @@ rl_filename_completion_function (text, state)
hit the end of the match list, we restore the original unmatched text,
ring the bell, and reset the counter to zero. */
int
rl_menu_complete (count, ignore)
int count, ignore;
rl_menu_complete (count, invoking_key)
int count, invoking_key;
{
rl_compentry_func_t *our_func;
int matching_filenames, found_quote;
@@ -2142,6 +2153,8 @@ rl_menu_complete (count, ignore)
match_list_index = match_list_size = 0;
matches = (char **)NULL;
rl_completion_invoking_key = invoking_key;
/* Only the completion entry function can change these. */
set_completion_defaults ('%');
+13 -2
View File
@@ -1,6 +1,6 @@
/* display.c -- readline redisplay facility. */
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -164,6 +164,7 @@ int _rl_last_v_pos = 0;
static int cpos_adjusted;
static int cpos_buffer_position;
static int prompt_multibyte_chars;
/* Number of lines currently on screen minus 1. */
int _rl_vis_botlin = 0;
@@ -300,6 +301,11 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
*r++ = *p++;
if (!ignoring)
{
/* rl ends up being assigned to prompt_visible_length,
which is the number of characters in the buffer that
contribute to characters on the screen, which might
not be the same as the number of physical characters
on the screen in the presence of multibyte characters */
rl += ind - pind;
physchars += _rl_col_width (pmt, pind, ind);
}
@@ -506,6 +512,8 @@ rl_redisplay ()
/* Draw the line into the buffer. */
cpos_buffer_position = -1;
prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
line = invisible_line;
out = inv_botlin = 0;
@@ -1756,7 +1764,10 @@ _rl_move_cursor_relative (new, data)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
dpos = _rl_col_width (data, 0, new);
if (dpos > prompt_last_invisible) /* XXX - don't use woff here */
/* Use NEW when comparing against the last invisible character in the
prompt string, since they're both buffer indices and DPOS is a
desired display position. */
if (new > prompt_last_invisible) /* XXX - don't use woff here */
{
dpos -= woff;
/* Since this will be assigned to _rl_last_c_pos at the end (more
File diff suppressed because it is too large Load Diff
+28 -9
View File
@@ -1,6 +1,6 @@
/* display.c -- readline redisplay facility. */
/* Copyright (C) 1987-2006 Free Software Foundation, Inc.
/* Copyright (C) 1987-2007 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
@@ -164,6 +164,7 @@ int _rl_last_v_pos = 0;
static int cpos_adjusted;
static int cpos_buffer_position;
static int prompt_multibyte_chars;
/* Number of lines currently on screen minus 1. */
int _rl_vis_botlin = 0;
@@ -300,6 +301,11 @@ expand_prompt (pmt, lp, lip, niflp, vlp)
*r++ = *p++;
if (!ignoring)
{
/* rl ends up being assigned to prompt_visible_length,
which is the number of characters in the buffer that
contribute to characters on the screen, which might
not be the same as the number of physical characters
on the screen in the presence of multibyte characters */
rl += ind - pind;
physchars += _rl_col_width (pmt, pind, ind);
}
@@ -465,10 +471,10 @@ init_line_structures (minsize)
vis_lbreaks = (int *)xmalloc (vis_lbsize * sizeof (int));
#if defined (HANDLE_MULTIBYTE)
line_state_visible->wbsize = vis_lbsize;
line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int);
line_state_visible->wrapped_line = (int *)xmalloc (line_state_visible->wbsize * sizeof (int));
line_state_invisible->wbsize = inv_lbsize;
line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int);
line_state_invisible->wrapped_line = (int *)xmalloc (line_state_invisible->wbsize * sizeof (int));
#endif
inv_lbreaks[0] = vis_lbreaks[0] = 0;
}
@@ -506,6 +512,8 @@ rl_redisplay ()
/* Draw the line into the buffer. */
cpos_buffer_position = -1;
prompt_multibyte_chars = prompt_visible_length - prompt_physical_chars;
line = invisible_line;
out = inv_botlin = 0;
@@ -684,6 +692,8 @@ rl_redisplay ()
temp = ((newlines + 1) * _rl_screenwidth);
/* Now account for invisible characters in the current line. */
/* XXX - this assumes that all of the invisible characters are before
the line wrap. */
temp += ((local_prompt_prefix == 0) ? ((newlines == 0) ? prompt_invis_chars_first_line
: ((newlines == 1) ? wrap_offset : 0))
: ((newlines == 0) ? wrap_offset :0));
@@ -1754,7 +1764,16 @@ _rl_move_cursor_relative (new, data)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
{
dpos = _rl_col_width (data, 0, new);
if (dpos > prompt_last_invisible) /* XXX - don't use woff here */
/* PROMPT_MULTIBYTE_CHARS is the difference between the number of
non-invisible characters in the prompt string and the number of
physical characters displayed on the screen. wrap_offset is
computed using the former. The computation above doesn't take
this into account. */
#if 0
if ((dpos+prompt_multibyte_chars) > prompt_last_invisible) /* XXX - don't use woff here */
#else
if (new > prompt_last_invisible) /* XXX - don't use woff here */
#endif
{
dpos -= woff;
/* Since this will be assigned to _rl_last_c_pos at the end (more
@@ -2167,7 +2186,7 @@ insert_some_chars (string, count, col)
/* DEBUGGING */
if (MB_CUR_MAX == 1 || rl_byte_oriented)
if (count != col)
fprintf(stderr, "readline: debug: insert_some_chars: count (%d) != col (%d)\n", count, col);
_rl_ttymsg ("debug: insert_some_chars: count (%d) != col (%d)", count, col);
/* If IC is defined, then we do not have to "enter" insert mode. */
if (_rl_term_IC)
@@ -2406,11 +2425,11 @@ _rl_col_width (str, start, end)
if (end <= start)
return 0;
if (MB_CUR_MAX == 1 || rl_byte_oriented)
{
fprintf (stderr, "_rl_col_width: called with MB_CUR_MAX == 1\n");
if (MB_CUR_MAX == 1 || rl_byte_oriented)
{
_rl_ttymsg ("_rl_col_width: called with MB_CUR_MAX == 1");
return (end - start);
}
}
memset (&ps, 0, sizeof (mbstate_t));
+10 -4
View File
@@ -513,20 +513,26 @@ _rl_read_mbchar (mbchar, size)
char *mbchar;
int size;
{
int mb_len = 0;
int mb_len, c;
size_t mbchar_bytes_length;
wchar_t wc;
mbstate_t ps, ps_back;
memset(&ps, 0, sizeof (mbstate_t));
memset(&ps_back, 0, sizeof (mbstate_t));
mb_len = 0;
while (mb_len < size)
{
RL_SETSTATE(RL_STATE_MOREINPUT);
mbchar[mb_len++] = rl_read_key ();
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
break;
mbchar[mb_len++] = c;
mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps);
if (mbchar_bytes_length == (size_t)(-1))
break; /* invalid byte sequence for the current locale */
@@ -564,7 +570,7 @@ _rl_read_mbstring (first, mb, mlen)
c = first;
memset (mb, 0, mlen);
for (i = 0; i < mlen; i++)
for (i = 0; c > 0 && i < mlen; i++)
{
mb[i] = (char)c;
memset (&ps, 0, sizeof (mbstate_t));
+583
View File
@@ -0,0 +1,583 @@
/* input.c -- character input functions for readline. */
/* Copyright (C) 1994-2005 Free Software Foundation, Inc.
This file is part of the GNU Readline Library, a library for
reading lines of text with interactive input and history editing.
The GNU Readline Library 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 2, or
(at your option) any later version.
The GNU Readline Library 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.
The GNU General Public License is often shipped with GNU software, and
is generally kept in a file called COPYING or LICENSE. If you do not
have a copy of the license, write to the Free Software Foundation,
59 Temple Place, Suite 330, Boston, MA 02111 USA. */
#define READLINE_LIBRARY
#if defined (__TANDEM)
# include <floss.h>
#endif
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <sys/types.h>
#include <fcntl.h>
#if defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
#endif /* HAVE_SYS_FILE_H */
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
#if defined (HAVE_STDLIB_H)
# include <stdlib.h>
#else
# include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */
#if defined (HAVE_SELECT)
# if !defined (HAVE_SYS_SELECT_H) || !defined (M_UNIX)
# include <sys/time.h>
# endif
#endif /* HAVE_SELECT */
#if defined (HAVE_SYS_SELECT_H)
# include <sys/select.h>
#endif
#if defined (FIONREAD_IN_SYS_IOCTL)
# include <sys/ioctl.h>
#endif
#include <stdio.h>
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
/* System-specific feature definitions and include files. */
#include "rldefs.h"
#include "rlmbutil.h"
/* Some standard library routines. */
#include "readline.h"
#include "rlprivate.h"
#include "rlshell.h"
#include "xmalloc.h"
/* What kind of non-blocking I/O do we have? */
#if !defined (O_NDELAY) && defined (O_NONBLOCK)
# define O_NDELAY O_NONBLOCK /* Posix style */
#endif
/* Non-null means it is a pointer to a function to run while waiting for
character input. */
rl_hook_func_t *rl_event_hook = (rl_hook_func_t *)NULL;
rl_getc_func_t *rl_getc_function = rl_getc;
static int _keyboard_input_timeout = 100000; /* 0.1 seconds; it's in usec */
static int ibuffer_space PARAMS((void));
static int rl_get_char PARAMS((int *));
static int rl_gather_tyi PARAMS((void));
/* **************************************************************** */
/* */
/* Character Input Buffering */
/* */
/* **************************************************************** */
static int pop_index, push_index;
static unsigned char ibuffer[512];
static int ibuffer_len = sizeof (ibuffer) - 1;
#define any_typein (push_index != pop_index)
int
_rl_any_typein ()
{
return any_typein;
}
/* Return the amount of space available in the buffer for stuffing
characters. */
static int
ibuffer_space ()
{
if (pop_index > push_index)
return (pop_index - push_index - 1);
else
return (ibuffer_len - (push_index - pop_index));
}
/* Get a key from the buffer of characters to be read.
Return the key in KEY.
Result is KEY if there was a key, or 0 if there wasn't. */
static int
rl_get_char (key)
int *key;
{
if (push_index == pop_index)
return (0);
*key = ibuffer[pop_index++];
if (pop_index >= ibuffer_len)
pop_index = 0;
return (1);
}
/* Stuff KEY into the *front* of the input buffer.
Returns non-zero if successful, zero if there is
no space left in the buffer. */
int
_rl_unget_char (key)
int key;
{
if (ibuffer_space ())
{
pop_index--;
if (pop_index < 0)
pop_index = ibuffer_len - 1;
ibuffer[pop_index] = key;
return (1);
}
return (0);
}
int
_rl_pushed_input_available ()
{
return (push_index != pop_index);
}
/* If a character is available to be read, then read it and stuff it into
IBUFFER. Otherwise, just return. Returns number of characters read
(0 if none available) and -1 on error (EIO). */
static int
rl_gather_tyi ()
{
int tty;
register int tem, result;
int chars_avail, k;
char input;
#if defined(HAVE_SELECT)
fd_set readfds, exceptfds;
struct timeval timeout;
#endif
chars_avail = 0;
tty = fileno (rl_instream);
#if defined (HAVE_SELECT)
FD_ZERO (&readfds);
FD_ZERO (&exceptfds);
FD_SET (tty, &readfds);
FD_SET (tty, &exceptfds);
timeout.tv_sec = 0;
timeout.tv_usec = _keyboard_input_timeout;
result = select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout);
if (result <= 0)
return 0; /* Nothing to read. */
#endif
result = -1;
#if defined (FIONREAD)
errno = 0;
result = ioctl (tty, FIONREAD, &chars_avail);
if (result == -1 && errno == EIO)
return -1;
#endif
#if defined (O_NDELAY)
if (result == -1)
{
tem = fcntl (tty, F_GETFL, 0);
fcntl (tty, F_SETFL, (tem | O_NDELAY));
chars_avail = read (tty, &input, 1);
fcntl (tty, F_SETFL, tem);
if (chars_avail == -1 && errno == EAGAIN)
return 0;
if (chars_avail == 0) /* EOF */
{
rl_stuff_char (EOF);
return (0);
}
}
#endif /* O_NDELAY */
#if defined (__MINGW32__)
/* Use getch/_kbhit to check for available console input, in the same way
that we read it normally. */
chars_avail = isatty (tty) ? _kbhit () : 0;
result = 0;
#endif
/* If there's nothing available, don't waste time trying to read
something. */
if (chars_avail <= 0)
return 0;
tem = ibuffer_space ();
if (chars_avail > tem)
chars_avail = tem;
/* One cannot read all of the available input. I can only read a single
character at a time, or else programs which require input can be
thwarted. If the buffer is larger than one character, I lose.
Damn! */
if (tem < ibuffer_len)
chars_avail = 0;
if (result != -1)
{
while (chars_avail--)
{
k = (*rl_getc_function) (rl_instream);
rl_stuff_char (k);
if (k == NEWLINE || k == RETURN)
break;
}
}
else
{
if (chars_avail)
rl_stuff_char (input);
}
return 1;
}
int
rl_set_keyboard_input_timeout (u)
int u;
{
int o;
o = _keyboard_input_timeout;
if (u >= 0)
_keyboard_input_timeout = u;
return (o);
}
/* Is there input available to be read on the readline input file
descriptor? Only works if the system has select(2) or FIONREAD.
Uses the value of _keyboard_input_timeout as the timeout; if another
readline function wants to specify a timeout and not leave it up to
the user, it should use _rl_input_queued(timeout_value_in_microseconds)
instead. */
int
_rl_input_available ()
{
#if defined(HAVE_SELECT)
fd_set readfds, exceptfds;
struct timeval timeout;
#endif
#if !defined (HAVE_SELECT) && defined(FIONREAD)
int chars_avail;
#endif
int tty;
tty = fileno (rl_instream);
#if defined (HAVE_SELECT)
FD_ZERO (&readfds);
FD_ZERO (&exceptfds);
FD_SET (tty, &readfds);
FD_SET (tty, &exceptfds);
timeout.tv_sec = 0;
timeout.tv_usec = _keyboard_input_timeout;
return (select (tty + 1, &readfds, (fd_set *)NULL, &exceptfds, &timeout) > 0);
#else
#if defined (FIONREAD)
if (ioctl (tty, FIONREAD, &chars_avail) == 0)
return (chars_avail);
#endif
#endif
#if defined (__MINGW32__)
if (isatty (tty))
return (_kbhit ());
#endif
return 0;
}
int
_rl_input_queued (t)
int t;
{
int old_timeout, r;
old_timeout = rl_set_keyboard_input_timeout (t);
r = _rl_input_available ();
rl_set_keyboard_input_timeout (old_timeout);
return r;
}
void
_rl_insert_typein (c)
int c;
{
int key, t, i;
char *string;
i = key = 0;
string = (char *)xmalloc (ibuffer_len + 1);
string[i++] = (char) c;
while ((t = rl_get_char (&key)) &&
_rl_keymap[key].type == ISFUNC &&
_rl_keymap[key].function == rl_insert)
string[i++] = key;
if (t)
_rl_unget_char (key);
string[i] = '\0';
rl_insert_text (string);
xfree (string);
}
/* Add KEY to the buffer of characters to be read. Returns 1 if the
character was stuffed correctly; 0 otherwise. */
int
rl_stuff_char (key)
int key;
{
if (ibuffer_space () == 0)
return 0;
if (key == EOF)
{
key = NEWLINE;
rl_pending_input = EOF;
RL_SETSTATE (RL_STATE_INPUTPENDING);
}
ibuffer[push_index++] = key;
if (push_index >= ibuffer_len)
push_index = 0;
return 1;
}
/* Make C be the next command to be executed. */
int
rl_execute_next (c)
int c;
{
rl_pending_input = c;
RL_SETSTATE (RL_STATE_INPUTPENDING);
return 0;
}
/* Clear any pending input pushed with rl_execute_next() */
int
rl_clear_pending_input ()
{
rl_pending_input = 0;
RL_UNSETSTATE (RL_STATE_INPUTPENDING);
return 0;
}
/* **************************************************************** */
/* */
/* Character Input */
/* */
/* **************************************************************** */
/* Read a key, including pending input. */
int
rl_read_key ()
{
int c;
rl_key_sequence_length++;
if (rl_pending_input)
{
c = rl_pending_input;
rl_clear_pending_input ();
}
else
{
/* If input is coming from a macro, then use that. */
if (c = _rl_next_macro_key ())
return (c);
/* If the user has an event function, then call it periodically. */
if (rl_event_hook)
{
while (rl_event_hook && rl_get_char (&c) == 0)
{
(*rl_event_hook) ();
if (rl_done) /* XXX - experimental */
return ('\n');
if (rl_gather_tyi () < 0) /* XXX - EIO */
{
rl_done = 1;
return ('\n');
}
}
}
else
{
if (rl_get_char (&c) == 0)
c = (*rl_getc_function) (rl_instream);
}
}
return (c);
}
int
rl_getc (stream)
FILE *stream;
{
int result;
unsigned char c;
while (1)
{
#if defined (__MINGW32__)
if (isatty (fileno (stream)))
return (getch ());
#endif
result = read (fileno (stream), &c, sizeof (unsigned char));
if (result == sizeof (unsigned char))
return (c);
/* If zero characters are returned, then the file that we are
reading from is empty! Return EOF in that case. */
if (result == 0)
return (EOF);
#if defined (__BEOS__)
if (errno == EINTR)
continue;
#endif
#if defined (EWOULDBLOCK)
# define X_EWOULDBLOCK EWOULDBLOCK
#else
# define X_EWOULDBLOCK -99
#endif
#if defined (EAGAIN)
# define X_EAGAIN EAGAIN
#else
# define X_EAGAIN -99
#endif
if (errno == X_EWOULDBLOCK || errno == X_EAGAIN)
{
if (sh_unset_nodelay_mode (fileno (stream)) < 0)
return (EOF);
continue;
}
#undef X_EWOULDBLOCK
#undef X_EAGAIN
/* If the error that we received was SIGINT, then try again,
this is simply an interrupted system call to read ().
Otherwise, some error ocurred, also signifying EOF. */
if (errno != EINTR)
return (RL_ISSTATE (RL_STATE_READCMD) ? READERR : EOF);
}
}
#if defined (HANDLE_MULTIBYTE)
/* read multibyte char */
int
_rl_read_mbchar (mbchar, size)
char *mbchar;
int size;
{
int mb_len = 0;
size_t mbchar_bytes_length;
wchar_t wc;
mbstate_t ps, ps_back;
memset(&ps, 0, sizeof (mbstate_t));
memset(&ps_back, 0, sizeof (mbstate_t));
while (mb_len < size)
{
RL_SETSTATE(RL_STATE_MOREINPUT);
mbchar[mb_len++] = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
mbchar_bytes_length = mbrtowc (&wc, mbchar, mb_len, &ps);
if (mbchar_bytes_length == (size_t)(-1))
break; /* invalid byte sequence for the current locale */
else if (mbchar_bytes_length == (size_t)(-2))
{
/* shorted bytes */
ps = ps_back;
continue;
}
else if (mbchar_bytes_length == 0)
{
mbchar[0] = '\0'; /* null wide character */
mb_len = 1;
break;
}
else if (mbchar_bytes_length > (size_t)(0))
break;
}
return mb_len;
}
/* Read a multibyte-character string whose first character is FIRST into
the buffer MB of length MLEN. Returns the last character read, which
may be FIRST. Used by the search functions, among others. Very similar
to _rl_read_mbchar. */
int
_rl_read_mbstring (first, mb, mlen)
int first;
char *mb;
int mlen;
{
int i, c;
mbstate_t ps;
c = first;
memset (mb, 0, mlen);
for (i = 0; i < mlen; i++)
{
mb[i] = (char)c;
memset (&ps, 0, sizeof (mbstate_t));
if (_rl_get_char_len (mb, &ps) == -2)
{
/* Read more for multibyte character */
RL_SETSTATE (RL_STATE_MOREINPUT);
c = rl_read_key ();
RL_UNSETSTATE (RL_STATE_MOREINPUT);
}
else
break;
}
return c;
}
#endif /* HANDLE_MULTIBYTE */
+9 -2
View File
@@ -327,8 +327,15 @@ _rl_isearch_dispatch (cxt, c)
rl_command_func_t *f;
f = (rl_command_func_t *)NULL;
/* Translate the keys we do something with to opcodes. */
if (c < 0)
{
cxt->sflags |= SF_FAILED;
cxt->history_pos = cxt->last_found_line;
return -1;
}
/* Translate the keys we do something with to opcodes. */
if (c >= 0 && _rl_keymap[c].type == ISFUNC)
{
f = _rl_keymap[c].function;
+9 -6
View File
@@ -211,7 +211,6 @@ _rl_isearch_init (direction)
cxt->search_terminators = _rl_isearch_terminators ? _rl_isearch_terminators
: default_isearch_terminators;
itrace("_rl_isearch_init: set search_terminators to %s", cxt->search_terminators);
/* Create an arrary of pointers to the lines that we want to search. */
hlist = history_list ();
rl_maybe_replace_line ();
@@ -328,8 +327,15 @@ _rl_isearch_dispatch (cxt, c)
rl_command_func_t *f;
f = (rl_command_func_t *)NULL;
/* Translate the keys we do something with to opcodes. */
if (c < 0)
{
cxt->flags |= SF_FAILED;
cxt->history_pos = cxt->last_found_line;
return -1;
}
/* Translate the keys we do something with to opcodes. */
if (c >= 0 && _rl_keymap[c].type == ISFUNC)
{
f = _rl_keymap[c].function;
@@ -348,14 +354,12 @@ _rl_isearch_dispatch (cxt, c)
cxt->lastc = -6;
}
itrace("_rl_isearch_dispatch: looking for %d in cxt->search_terminators", cxt->lastc);
/* The characters in isearch_terminators (set from the user-settable
variable isearch-terminators) are used to terminate the search but
not subsequently execute the character as a command. The default
value is "\033\012" (ESC and C-J). */
if (strchr (cxt->search_terminators, cxt->lastc))
{
itrace("_rl_isearch_dispatch: found %d in search_terminators", cxt->lastc);
/* ESC still terminates the search, but if there is pending
input or if input arrives within 0.1 seconds (on systems
with select(2)) it is used as a prefix character
@@ -367,7 +371,6 @@ itrace("_rl_isearch_dispatch: found %d in search_terminators", cxt->lastc);
use _rl_input_queued(100000) */
if (cxt->lastc == ESC && _rl_input_available ())
rl_execute_next (ESC);
itrace("_rl_isearch_dispatch: exiting search based on char %d", cxt->lastc);
return (0);
}
+2
View File
@@ -146,6 +146,8 @@ _rl_arg_dispatch (cxt, c)
rl_restore_prompt ();
rl_clear_message ();
RL_UNSETSTATE(RL_STATE_NUMERICARG);
if (key < 0)
return -1;
return (_rl_dispatch (key, _rl_keymap));
}
}
+5 -2
View File
@@ -449,7 +449,6 @@ _rl_revert_all_lines ()
hpos = where_history ();
entry = (hpos == history_length) ? previous_history () : current_history ();
while (entry)
{
if (ul = (UNDO_LIST *)entry->data)
@@ -470,12 +469,16 @@ _rl_revert_all_lines ()
entry = previous_history ();
}
/* Restore history state */
rl_undo_list = saved_undo_list; /* may have been set to null */
history_set_pos (hpos);
/* And reset the line buffer */
/* reset the line buffer */
rl_replace_line (lbuf, 0);
_rl_set_the_line ();
/* and clean up */
free (lbuf);
}
/* **************************************************************** */
+5
View File
@@ -668,6 +668,11 @@ _rl_dispatch_callback (cxt)
if ((cxt->flags & KSEQ_DISPATCHED) == 0)
{
nkey = _rl_subseq_getchar (cxt->okey);
if (nkey < 0)
{
_rl_abort_internal ();
return -1;
}
r = _rl_dispatch_subseq (nkey, cxt->dmap, cxt->subseq_arg);
cxt->flags |= KSEQ_DISPATCHED;
}
+7 -2
View File
@@ -273,7 +273,7 @@ int _rl_bind_stty_chars = 1;
/* Non-zero means to go through the history list at every newline (or
whenever rl_done is set and readline returns) and revert each line to
its initial state. */
int _rl_revert_all_at_newline = 1;
int _rl_revert_all_at_newline = 0;
/* **************************************************************** */
/* */
@@ -314,11 +314,14 @@ readline (prompt)
return ((char *)NULL);
}
#if 0
/* If readline() is called after installing a callback handler, temporarily
turn off the callback state to avoid ensuing messiness. Patch supplied
by the gdb folks. */
by the gdb folks. XXX -- disabled. This can be fooled and readline
left in a strange state by a poorly-timed longjmp. */
if (in_callback = RL_ISSTATE (RL_STATE_CALLBACK))
RL_UNSETSTATE (RL_STATE_CALLBACK);
#endif
rl_set_prompt (prompt);
@@ -338,8 +341,10 @@ readline (prompt)
rl_clear_signals ();
#endif
#if 0
if (in_callback)
RL_SETSTATE (RL_STATE_CALLBACK);
#endif
return (value);
}
+1 -1
View File
@@ -862,7 +862,7 @@ set_special_char (kmap, tiop, sc, func)
}
#define RESET_SPECIAL(c) \
if (c != -1 && kmap[(unsigned char)c].type == ISFUNC)
if (c != -1 && kmap[(unsigned char)c].type == ISFUNC) \
kmap[(unsigned char)c].function = rl_insert;
static void
+9
View File
@@ -857,6 +857,9 @@ _rl_insert_next (count)
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
return -1;
#if defined (HANDLE_SIGNALS)
if (RL_ISSTATE (RL_STATE_CALLBACK) == 0)
_rl_restore_tty_signals ();
@@ -1520,6 +1523,9 @@ _rl_char_search (count, fdir, bdir)
mb_len = _rl_read_mbchar (mbchar, MB_LEN_MAX);
if (mb_len <= 0)
return -1;
if (count < 0)
return (_rl_char_search_internal (-count, bdir, mbchar, mb_len));
else
@@ -1536,6 +1542,9 @@ _rl_char_search (count, fdir, bdir)
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
return -1;
if (count < 0)
return (_rl_char_search_internal (-count, bdir, c));
else
+2 -2
View File
@@ -260,7 +260,7 @@ rl_forward_byte (count, key)
{
int end = rl_point + count;
#if defined (VI_MODE)
int lend = rl_end > 0 ? rl_end - (rl_editing_mode == vi_mode) : rl_end;
int lend = rl_end > 0 ? rl_end - (VI_COMMAND_MODE()) : rl_end;
#else
int lend = rl_end;
#endif
@@ -299,7 +299,7 @@ rl_forward_char (count, key)
point = _rl_find_next_mbchar (rl_line_buffer, rl_point, count, MB_FIND_NONZERO);
#if defined (VI_MODE)
if (rl_end <= point && rl_editing_mode == vi_mode)
if (point >= rl_end && VI_COMMAND_MODE())
point = _rl_find_prev_mbchar (rl_line_buffer, rl_end, MB_FIND_NONZERO);
#endif
+42 -6
View File
@@ -886,6 +886,13 @@ rl_vi_domove (key, nextkey)
RL_SETSTATE(RL_STATE_MOREINPUT);
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
{
*nextkey = 0;
return -1;
}
*nextkey = c;
if (!member (c, vi_motion))
@@ -902,6 +909,11 @@ rl_vi_domove (key, nextkey)
RL_SETSTATE(RL_STATE_MOREINPUT);
c = rl_read_key (); /* real command */
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
{
*nextkey = 0;
return -1;
}
*nextkey = c;
}
else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
@@ -1230,14 +1242,22 @@ static int
_rl_vi_callback_char_search (data)
_rl_callback_generic_arg *data;
{
int c;
#if defined (HANDLE_MULTIBYTE)
_rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
#else
RL_SETSTATE(RL_STATE_MOREINPUT);
_rl_vi_last_search_char = rl_read_key ();
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
#endif
if (c <= 0)
return -1;
#if !defined (HANDLE_MULTIBYTE)
_rl_vi_last_search_char = c;
#endif
_rl_callback_func = 0;
_rl_want_redisplay = 1;
@@ -1253,6 +1273,7 @@ int
rl_vi_char_search (count, key)
int count, key;
{
int c;
#if defined (HANDLE_MULTIBYTE)
static char *target;
static int tlen;
@@ -1299,11 +1320,17 @@ rl_vi_char_search (count, key)
else
{
#if defined (HANDLE_MULTIBYTE)
_rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
if (c <= 0)
return -1;
_rl_vi_last_search_mblen = c;
#else
RL_SETSTATE(RL_STATE_MOREINPUT);
_rl_vi_last_search_char = rl_read_key ();
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
return -1;
_rl_vi_last_search_char = c;
#endif
}
}
@@ -1473,6 +1500,9 @@ _rl_vi_callback_getchar (mb, mlen)
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
return -1;
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
c = _rl_read_mbstring (c, mb, mlen);
@@ -1491,6 +1521,9 @@ _rl_vi_callback_change_char (data)
_rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
if (c < 0)
return -1;
_rl_callback_func = 0;
_rl_want_redisplay = 1;
@@ -1522,6 +1555,9 @@ rl_vi_change_char (count, key)
else
_rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
if (c < 0)
return -1;
return (_rl_vi_change_char (count, c, mb));
}
@@ -1656,7 +1692,7 @@ _rl_vi_set_mark ()
ch = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (ch < 'a' || ch > 'z')
if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
{
rl_ding ();
return -1;
@@ -1708,7 +1744,7 @@ _rl_vi_goto_mark ()
rl_point = rl_mark;
return 0;
}
else if (ch < 'a' || ch > 'z')
else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
{
rl_ding ();
return -1;
+40 -7
View File
@@ -101,7 +101,7 @@ static int _rl_vi_last_key_before_insert;
static int vi_redoing;
/* Text modification commands. These are the `redoable' commands. */
static const char *vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
static const char * const vi_textmod = "_*\\AaIiCcDdPpYyRrSsXx~";
/* Arrays for the saved marks. */
static int vi_mark_chars['z' - 'a' + 1];
@@ -886,6 +886,13 @@ rl_vi_domove (key, nextkey)
RL_SETSTATE(RL_STATE_MOREINPUT);
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
{
*nextkey = 0;
return -1;
}
*nextkey = c;
if (!member (c, vi_motion))
@@ -902,6 +909,11 @@ rl_vi_domove (key, nextkey)
RL_SETSTATE(RL_STATE_MOREINPUT);
c = rl_read_key (); /* real command */
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
{
*nextkey = 0;
return -1;
}
*nextkey = c;
}
else if (key == c && (key == 'd' || key == 'y' || key == 'c'))
@@ -1230,14 +1242,19 @@ static int
_rl_vi_callback_char_search (data)
_rl_callback_generic_arg *data;
{
int c;
#if defined (HANDLE_MULTIBYTE)
_rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
c = _rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
#else
RL_SETSTATE(RL_STATE_MOREINPUT);
_rl_vi_last_search_char = rl_read_key ();
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
#endif
if (c < 0)
return -1;
_rl_vi_last_search_char = c;
_rl_callback_func = 0;
_rl_want_redisplay = 1;
@@ -1253,6 +1270,7 @@ int
rl_vi_char_search (count, key)
int count, key;
{
int c;
#if defined (HANDLE_MULTIBYTE)
static char *target;
static int tlen;
@@ -1299,11 +1317,17 @@ rl_vi_char_search (count, key)
else
{
#if defined (HANDLE_MULTIBYTE)
_rl_vi_last_search_mblen = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
c = _rl_read_mbchar (_rl_vi_last_search_mbchar, MB_LEN_MAX);
if (c <= 0)
return -1;
_rl_vi_last_search_mblen = c;
#else
RL_SETSTATE(RL_STATE_MOREINPUT);
_rl_vi_last_search_char = rl_read_key ();
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
return -1;
_rl_vi_last_search_char = c;
#endif
}
}
@@ -1473,6 +1497,9 @@ _rl_vi_callback_getchar (mb, mlen)
c = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (c < 0)
return -1;
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1 && rl_byte_oriented == 0)
c = _rl_read_mbstring (c, mb, mlen);
@@ -1491,6 +1518,9 @@ _rl_vi_callback_change_char (data)
_rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
if (c < 0)
return -1;
_rl_callback_func = 0;
_rl_want_redisplay = 1;
@@ -1522,6 +1552,9 @@ rl_vi_change_char (count, key)
else
_rl_vi_last_replacement = c = _rl_vi_callback_getchar (mb, MB_LEN_MAX);
if (c < 0)
return -1;
return (_rl_vi_change_char (count, c, mb));
}
@@ -1656,7 +1689,7 @@ _rl_vi_set_mark ()
ch = rl_read_key ();
RL_UNSETSTATE(RL_STATE_MOREINPUT);
if (ch < 'a' || ch > 'z')
if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
{
rl_ding ();
return -1;
@@ -1708,7 +1741,7 @@ _rl_vi_goto_mark ()
rl_point = rl_mark;
return 0;
}
else if (ch < 'a' || ch > 'z')
else if (ch < 0 || ch < 'a' || ch > 'z') /* make test against 0 explicit */
{
rl_ding ();
return -1;
+20 -1
View File
@@ -350,6 +350,25 @@ reset_terminating_signals ()
#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 = 0;
return_catch_flag = 0;
}
/* What to do when we've been interrupted, and it is safe to handle it. */
void
throw_to_top_level ()
@@ -372,7 +391,7 @@ throw_to_top_level ()
/* Run any traps set on SIGINT. */
run_interrupt_trap ();
/* Cleanup string parser environment. */
/* Clean up string parser environment. */
while (parse_and_execute_level)
parse_and_execute_cleanup ();
+595
View File
@@ -0,0 +1,595 @@
/* sig.c - interface for shell signal handlers and signal initialization. */
/* Copyright (C) 1994-2006 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 2, 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; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
#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"
#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;
extern int parse_and_execute_level, shell_initialized;
/* Non-zero after SIGINT. */
volatile int interrupt_state = 0;
/* Non-zero after SIGWINCH */
volatile int sigwinch_received = 0;
/* Set to the value of any terminating signal received. */
volatile int 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). */
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. */
if (!interactive_shell && 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. */
if (!interactive_shell && 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);
set_signal_handler (SIGTERM, SIG_IGN);
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 */
}
#undef XSIG
#undef XHANDLER
/* 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)
{
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 ();
/* Cleanup 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 should not be necessary on systems using sigsetjmp/siglongjmp. */
sigprocmask (SIG_SETMASK, &top_level_mask, (sigset_t *)NULL);
#endif
reset_parser ();
#if defined (READLINE)
if (interactive)
bashline_reinitialize ();
#endif /* READLINE */
#if defined (PROCESS_SUBSTITUTION)
unlink_fifo_list ();
#endif /* PROCESS_SUBSTITUTION */
run_unwind_protects ();
loop_level = continuing = breaking = 0;
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;
{
terminating_signal = sig;
if (terminate_immediately)
{
terminate_immediately = 0;
termsig_handler (sig);
}
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 (interactive_shell && sig != SIGABRT)
maybe_save_shell_history ();
#endif /* HISTORY */
#if defined (JOB_CONTROL)
if (interactive && sig == SIGHUP)
hangup_all_jobs ();
end_job_control ();
#endif /* JOB_CONTROL */
#if defined (PROCESS_SUBSTITUTION)
unlink_fifo_list ();
#endif /* PROCESS_SUBSTITUTION */
run_exit_trap ();
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;
throw_to_top_level ();
}
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
}
/* Signal functions used by the rest of the code. */
#if !defined (HAVE_POSIX_SIGNALS)
#if defined (JOB_CONTROL)
/* 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:
sigsetmask (new);
break;
default:
internal_error (_("sigprocmask: %d: invalid operation"), operation);
}
if (oldset)
*oldset = old;
}
#endif /* JOB_CONTROL */
#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;
#if 0
if (sig == SIGALRM)
act.sa_flags |= SA_INTERRUPT; /* XXX */
else
act.sa_flags |= SA_RESTART; /* XXX */
#endif
sigemptyset (&act.sa_mask);
sigemptyset (&oact.sa_mask);
sigaction (sig, &act, &oact);
return (oact.sa_handler);
}
#endif /* HAVE_POSIX_SIGNALS */
+1
View File
@@ -121,6 +121,7 @@ extern sighandler sigint_sighandler __P((int));
extern void initialize_signals __P((int));
extern void initialize_terminating_signals __P((void));
extern void reset_terminating_signals __P((void));
extern void top_level_cleanup __P((void));
extern void throw_to_top_level __P((void));
extern void jump_to_top_level __P((int)) __attribute__((__noreturn__));
+136
View File
@@ -0,0 +1,136 @@
/* sig.h -- header file for signal handler definitions. */
/* Copyright (C) 1994-2006 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 2, 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; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
/* Make sure that this is included *after* config.h! */
#if !defined (_SIG_H_)
# define _SIG_H_
#include "stdc.h"
#if !defined (SIGABRT) && defined (SIGIOT)
# define SIGABRT SIGIOT
#endif
#define sighandler RETSIGTYPE
typedef RETSIGTYPE SigHandler __P((int));
#if defined (VOID_SIGHANDLER)
# define SIGRETURN(n) return
#else
# define SIGRETURN(n) return(n)
#endif /* !VOID_SIGHANDLER */
/* Here is a definition for set_signal_handler () which simply expands to
a call to signal () for non-Posix systems. The code for set_signal_handler
in the Posix case resides in general.c. */
#if !defined (HAVE_POSIX_SIGNALS)
# define set_signal_handler(sig, handler) (SigHandler *)signal (sig, handler)
#else
extern SigHandler *set_signal_handler __P((int, SigHandler *)); /* in sig.c */
#endif /* _POSIX_VERSION */
/* Definitions used by the job control code. */
#if defined (JOB_CONTROL)
#if !defined (SIGCHLD) && defined (SIGCLD)
# define SIGCHLD SIGCLD
#endif
#if !defined (HAVE_POSIX_SIGNALS) && !defined (sigmask)
# define sigmask(x) (1 << ((x)-1))
#endif /* !HAVE_POSIX_SIGNALS && !sigmask */
#if !defined (HAVE_POSIX_SIGNALS)
# if !defined (SIG_BLOCK)
# define SIG_BLOCK 2
# define SIG_SETMASK 3
# endif /* SIG_BLOCK */
/* sigset_t defined in config.h */
/* Make sure there is nothing inside the signal set. */
# define sigemptyset(set) (*(set) = 0)
/* Initialize the signal set to hold all signals. */
# define sigfillset(set) (*set) = sigmask (NSIG) - 1
/* Add SIG to the contents of SET. */
# define sigaddset(set, sig) *(set) |= sigmask (sig)
/* Delete SIG from signal set SET. */
# define sigdelset(set, sig) *(set) &= ~sigmask (sig)
/* Is SIG a member of the signal set SET? */
# define sigismember(set, sig) ((*(set) & sigmask (sig)) != 0)
/* Suspend the process until the reception of one of the signals
not present in SET. */
# define sigsuspend(set) sigpause (*(set))
#endif /* !HAVE_POSIX_SIGNALS */
/* These definitions are used both in POSIX and non-POSIX implementations. */
#define BLOCK_SIGNAL(sig, nvar, ovar) \
do { \
sigemptyset (&nvar); \
sigaddset (&nvar, sig); \
sigemptyset (&ovar); \
sigprocmask (SIG_BLOCK, &nvar, &ovar); \
} while (0)
#if defined (HAVE_POSIX_SIGNALS)
# define BLOCK_CHILD(nvar, ovar) \
BLOCK_SIGNAL (SIGCHLD, nvar, ovar)
# define UNBLOCK_CHILD(ovar) \
sigprocmask (SIG_SETMASK, &ovar, (sigset_t *) NULL)
#else /* !HAVE_POSIX_SIGNALS */
# define BLOCK_CHILD(nvar, ovar) ovar = sigblock (sigmask (SIGCHLD))
# define UNBLOCK_CHILD(ovar) sigsetmask (ovar)
#endif /* !HAVE_POSIX_SIGNALS */
#endif /* JOB_CONTROL */
/* Extern variables */
extern volatile int sigwinch_received;
extern int interrupt_immediately;
extern int terminate_immediately;
/* Functions from sig.c. */
extern sighandler termsig_sighandler __P((int));
extern void termsig_handler __P((int));
extern sighandler sigint_sighandler __P((int));
extern void initialize_signals __P((int));
extern void initialize_terminating_signals __P((void));
extern void reset_terminating_signals __P((void));
extern void throw_to_top_level __P((void));
extern void jump_to_top_level __P((int)) __attribute__((__noreturn__));
extern sighandler sigwinch_sighandler __P((int));
extern void set_sigwinch_handler __P((void));
extern void unset_sigwinch_handler __P((void));
/* Functions defined in trap.c. */
extern SigHandler *set_sigint_handler __P((void));
extern SigHandler *trap_to_sighandler __P((int));
extern sighandler trap_handler __P((int));
#endif /* _SIG_H_ */
+7 -1
View File
@@ -33,4 +33,10 @@ then
fi
[[ $REPAT =~ "$REPAT" ]] && echo rematch 1
v="one two buckle my shoe"
[[ ${v} =~ "one two" ]] && echo matches 7
[[ ${v} =~ (one two) ]] && echo matches 8
[[ ${v} =~ one\ two ]] && echo matches 9
+3
View File
@@ -55,3 +55,6 @@ yes 6
Dog 01 is Wiggles
Dog 01 is Wiggles
rematch 1
matches 7
matches 8
matches 9