commit bash-20040916 snapshot

This commit is contained in:
Chet Ramey
2011-12-03 13:36:44 -05:00
parent b66cc81633
commit 633e5c6dee
43 changed files with 15318 additions and 111 deletions
+75
View File
@@ -10037,3 +10037,78 @@ variables.c
expr.c
- make exponentiation right-associative, as is apparently correct
9/16
----
arrayfunc.c
- make sure convert_var_to_array marks the environment as needing
recreation if the converted variable was exported
9/17
----
braces.c
- mark ${ as introducing an additional level of braces only if it's
not in a quoted string -- quoted strings are handled before brace
matching is done
parse.y
- fixed an obscure problem in history_delimiting_chars where the `in'
in a case statement could have a semicolon added after it, if the
`case word' was on a previous line
support/config.guess
- support for newest versions of tandem non-stop kernel
lib/readline/display.c
- in compute_lcd_of_matches, explicitly cast `text' to `char *' before
passing it to rl_filename_dequoting_function
lib/readline/terminal.c
- bind the key sequence sent by the keypad `delete' key to delete-char
(same as ^D in emacs mode)
builtins/ulimit.def
- in print_all_limits, don't print anything if get_limit returns
-1/EINVAL, indicating that the kernel doesn't support that particular
limit
- add -i (max number of pending signals), -q (max size of posix msg
queues), -x (max number of file locks) for systems (Linux) that
support them
doc/{bash.1,bashref.texi}
- fix description of correspondence between FUNCNAME, BASH_LINENO,
and BASH_SOURCE indices in description of BASH_LINENO
9/18
----
lib/sh/shquote.c
- don't quote CTLESC and CTLNUL with CTLESC in sh_backslash_quote, as
long as the resultant string never gets sent to the word expansion
functions without going through the shell parser
externs.h
- add extern declarations for strnlen and strpbkrk from lib/sh
subst.[ch]
- changes to handle case where IFS consists of multibyte characters.
Changed: string_extract_verbatim, split_at_delims,
string_list_dollar_star, string_list_dollar_at, list_string,
get_word_from_string, setifs
9/19
----
mailcheck.c
- change file_mod_date_changed to reset the cached mail file data if
the file size drops to zero
lib/readline/complete.c
- change append_to_match so that a non-zero value for
rl_completion_suppress_append will cause no `/' to be appended to a
directory name
bashline.c
- experimental change to suppress appending a slash for a completed
filename that is found in PATH as well as a directory in the current
directory under certain circumstances: a single instance found in
$PATH when `.' is not in $PATH, and multiple instances found in the
$PATH, even when `.' is in the $PATH
+80
View File
@@ -10025,3 +10025,83 @@ parse.y
arguments to a builtin that accepts assignment statement arguments
- turn on PST_ASSIGNOK in read_token_word when appropriate
- turn off PST_ASSIGNOK in read_token when appropriate
- don't attempt to parse a compound assignment specially unless we're
in a position where an assignment statement is acceptable, or
PST_ASSIGNOK is set
9/13
----
variables.c
- make BASH_ARGC, BASH_ARGV, BASH_LINENO, and BASH_SOURCE
non-unsettable, since the shell uses those values internally
expr.c
- make exponentiation right-associative, as is apparently correct
9/16
----
arrayfunc.c
- make sure convert_var_to_array marks the environment as needing
recreation if the converted variable was exported
9/17
----
braces.c
- mark ${ as introducing an additional level of braces only if it's
not in a quoted string -- quoted strings are handled before brace
matching is done
parse.y
- fixed an obscure problem in history_delimiting_chars where the `in'
in a case statement could have a semicolon added after it, if the
`case word' was on a previous line
support/config.guess
- support for newest versions of tandem non-stop kernel
lib/readline/display.c
- in compute_lcd_of_matches, explicitly cast `text' to `char *' before
passing it to rl_filename_dequoting_function
lib/readline/terminal.c
- bind the key sequence sent by the keypad `delete' key to delete-char
(same as ^D in emacs mode)
builtins/ulimit.def
- in print_all_limits, don't print anything if get_limit returns
-1/EINVAL, indicating that the kernel doesn't support that particular
limit
- add -i (max number of pending signals), -q (max size of posix msg
queues), -x (max number of file locks) for systems (Linux) that
support them
doc/{bash.1,bashref.texi}
- fix description of correspondence between FUNCNAME, BASH_LINENO,
and BASH_SOURCE indices in description of BASH_LINENO
9/18
----
lib/sh/shquote.c
- don't quote CTLESC and CTLNUL with CTLESC in sh_backslash_quote, as
long as the resultant string never gets sent to the word expansion
functions without going through the shell parser
externs.h
- add extern declarations for strnlen and strpbkrk from lib/sh
subst.[ch]
- changes to handle case where IFS consists of multibyte characters.
Changed: string_extract_verbatim, split_at_delims,
string_list_dollar_star, string_list_dollar_at, list_string,
get_word_from_string, setifs
9/19
----
mailcheck.c
- change file_mod_date_changed to reset the cached mail file data if
the file size drops to zero
lib/readline/complete.c
- change append_to_match so that a non-zero value for
rl_completion_suppress_append will cause no `/' to be appended to a
directory name
+3 -3
View File
@@ -1,4 +1,4 @@
# Makefile for bash-3.0, version 2.153
# Makefile for bash-3.0, version 2.154
#
# Copyright (C) 1996-2004 Free Software Foundation, Inc.
@@ -514,7 +514,7 @@ $(Program): .build $(OBJECTS) $(BUILTINS_DEP) $(LIBDEP)
$(RM) $@
$(PURIFY) $(CC) $(BUILTINS_LDFLAGS) $(LIBRARY_LDFLAGS) $(LDFLAGS) -o $(Program) $(OBJECTS) $(LIBS)
ls -l $(Program)
size $(Program)
-size $(Program)
.build: $(SOURCES) config.h Makefile version.h $(VERSPROG)
@echo
@@ -536,7 +536,7 @@ bashbug: $(SUPPORT_SRC)bashbug.sh config.h Makefile $(VERSPROG)
strip: $(Program) .made
strip $(Program)
ls -l $(Program)
size $(Program)
-size $(Program)
lint:
${MAKE} ${MFLAGS} CFLAGS='${GCC_LINT_FLAGS}' .made
+2 -2
View File
@@ -1,4 +1,4 @@
# Makefile for bash-3.0, version 2.152
# Makefile for bash-3.0, version 2.153
#
# Copyright (C) 1996-2004 Free Software Foundation, Inc.
@@ -669,7 +669,7 @@ $(srcdir)/configure: $(srcdir)/configure.in $(srcdir)/aclocal.m4 $(srcdir)/confi
# for chet
reconfig: force
sh $(srcdir)/configure
sh $(srcdir)/configure -C
#newversion: mkversion
# $(RM) .build
+3
View File
@@ -37,6 +37,7 @@
extern char *this_command_name;
extern int last_command_exit_value;
extern int array_needs_making;
static void quote_array_assignment_chars __P((WORD_LIST *));
static char *array_value_internal __P((char *, int, int, int *));
@@ -72,6 +73,8 @@ convert_var_to_array (var)
var->assign_func = (sh_var_assign_func_t *)NULL;
INVALIDATE_EXPORTSTR (var);
if (exported_p (var))
array_needs_making++;
VSETATTR (var, att_array);
VUNSETATTR (var, att_invisible);
+22 -15
View File
@@ -226,6 +226,8 @@ static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
static int dot_in_path = 0;
/* What kind of quoting is performed by bash_quote_filename:
COMPLETE_DQUOTE = double-quoting the filename
COMPLETE_SQUOTE = single_quoting the filename
@@ -1149,6 +1151,7 @@ bash_default_completion (text, start, end, qc, in_command_position)
{
#define CMD_IS_DIR(x) (absolute_pathname(x) == 0 && absolute_program(x) == 0 && *(x) != '~' && test_for_directory (x))
dot_in_path = 0;
matches = rl_completion_matches (text, command_word_completion_function);
/* If we are attempting command completion and nothing matches, we
@@ -1158,27 +1161,28 @@ bash_default_completion (text, start, end, qc, in_command_position)
filenames and leave directories in the match list. */
if (matches == (char **)NULL)
rl_ignore_some_completions_function = bash_ignore_filenames;
#if 0
else if (matches[1] == 0 && CMD_IS_DIR(matches[0]))
/* Turn off rl_filename_completion_desired so readline doesn't
append a slash if there is a directory with the same name
in the current directory, or other filename-specific things.
If the name begins with a slash, we're either completing a
full pathname or a directory pathname, and readline won't be
looking in the current directory anyway, so there's no
conflict. */
rl_filename_completion_desired = 0;
else if (matches[1] == 0 && CMD_IS_DIR(matches[0]) && dot_in_path == 0)
/* If we found a single match, without looking in the current
directory (because it's not in $PATH), but the found name is
also a command in the current directory, suppress appending any
terminating character, since it's ambiguous. */
{
rl_completion_suppress_append = 1;
rl_filename_completion_desired = 0;
}
else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) && CMD_IS_DIR (matches[0]))
/* There are multiple instances of the same match (duplicate
completions haven't yet been removed). In this case, all of
the matches will be the same, and the duplicate removal code
will distill them all down to one. We turn off
rl_filename_completion_desired for the same reason as above.
will distill them all down to one. We turn on
rl_completion_suppress_append for the same reason as above.
Remember: we only care if there's eventually a single unique
completion. If there are multiple completions this won't
make a difference and the problem won't occur. */
rl_filename_completion_desired = 0;
#endif
{
rl_completion_suppress_append = 1;
rl_filename_completion_desired = 0;
}
}
}
@@ -1256,7 +1260,7 @@ command_word_completion_function (hint_text, state)
hint_len = strlen (hint);
path = get_string_value ("PATH");
path_index = 0;
path_index = dot_in_path = 0;
/* Initialize the variables for each type of command word. */
local_index = 0;
@@ -1374,6 +1378,9 @@ command_word_completion_function (hint_text, state)
current_path = t;
}
if (current_path[0] == '.' && current_path[1] == '\0')
dot_in_path = 1;
if (filename_hint)
free (filename_hint);
+58 -21
View File
@@ -100,6 +100,7 @@ static int history_and_alias_expand_line __P((int, int));
#endif
/* Helper functions for Readline. */
static int bash_directory_expansion __P((char **));
static int bash_directory_completion_hook __P((char **));
static int filename_completion_ignore __P((char **));
static int bash_push_line __P((void));
@@ -225,6 +226,8 @@ static char *bash_nohostname_word_break_characters = " \t\n\"'><=;|&(:";
static rl_hook_func_t *old_rl_startup_hook = (rl_hook_func_t *)NULL;
static int dot_in_path = 0;
/* What kind of quoting is performed by bash_quote_filename:
COMPLETE_DQUOTE = double-quoting the filename
COMPLETE_SQUOTE = single_quoting the filename
@@ -1148,6 +1151,7 @@ bash_default_completion (text, start, end, qc, in_command_position)
{
#define CMD_IS_DIR(x) (absolute_pathname(x) == 0 && absolute_program(x) == 0 && *(x) != '~' && test_for_directory (x))
dot_in_path = 0;
matches = rl_completion_matches (text, command_word_completion_function);
/* If we are attempting command completion and nothing matches, we
@@ -1157,27 +1161,22 @@ bash_default_completion (text, start, end, qc, in_command_position)
filenames and leave directories in the match list. */
if (matches == (char **)NULL)
rl_ignore_some_completions_function = bash_ignore_filenames;
#if 0
else if (matches[1] == 0 && CMD_IS_DIR(matches[0]))
/* Turn off rl_filename_completion_desired so readline doesn't
append a slash if there is a directory with the same name
in the current directory, or other filename-specific things.
If the name begins with a slash, we're either completing a
full pathname or a directory pathname, and readline won't be
looking in the current directory anyway, so there's no
conflict. */
rl_filename_completion_desired = 0;
else if (matches[1] == 0 && CMD_IS_DIR(matches[0]) && dot_in_path == 0)
/* If we found a single match, without looking in the current
directory (because it's not in $PATH), but the found name is
also a command in the current directory, suppress appending any
terminating character, since it's ambiguous. */
rl_completion_suppress_append = 1;
else if (matches[0] && matches[1] && STREQ (matches[0], matches[1]) && CMD_IS_DIR (matches[0]))
/* There are multiple instances of the same match (duplicate
completions haven't yet been removed). In this case, all of
the matches will be the same, and the duplicate removal code
will distill them all down to one. We turn off
rl_filename_completion_desired for the same reason as above.
will distill them all down to one. We turn on
rl_completion_suppress_append for the same reason as above.
Remember: we only care if there's eventually a single unique
completion. If there are multiple completions this won't
make a difference and the problem won't occur. */
rl_filename_completion_desired = 0;
#endif
rl_completion_suppress_append = 1;
}
}
@@ -1255,7 +1254,7 @@ command_word_completion_function (hint_text, state)
hint_len = strlen (hint);
path = get_string_value ("PATH");
path_index = 0;
path_index = dot_in_path = 0;
/* Initialize the variables for each type of command word. */
local_index = 0;
@@ -1373,6 +1372,9 @@ command_word_completion_function (hint_text, state)
current_path = t;
}
if (current_path[0] == '.' && current_path[1] == '\0')
dot_in_path = 1;
if (filename_hint)
free (filename_hint);
@@ -1406,10 +1408,19 @@ command_word_completion_function (hint_text, state)
filename. */
if (*hint_text == '~')
{
int l, tl, vl;
int l, tl, vl, dl;
char *rd;
vl = strlen (val);
tl = strlen (hint_text);
#if 0
l = vl - hint_len; /* # of chars added */
#else
rd = savestring (filename_hint);
bash_directory_expansion (&rd);
dl = strlen (rd);
l = vl - dl; /* # of chars added */
free (rd);
#endif
temp = (char *)xmalloc (l + 2 + tl);
strcpy (temp, hint_text);
strcpy (temp + tl, val + vl - l);
@@ -2187,6 +2198,27 @@ bash_ignore_everything (names)
return 0;
}
/* Simulate the expansions that will be performed by
rl_filename_completion_function. This must be called with the address of
a pointer to malloc'd memory. */
static int
bash_directory_expansion (dirname)
char **dirname;
{
char *d;
d = savestring (*dirname);
if (rl_directory_rewrite_hook)
(*rl_directory_rewrite_hook) (&d);
if (rl_directory_completion_hook && (*rl_directory_completion_hook) (&d))
{
free (*dirname);
*dirname = d;
}
}
/* Handle symbolic link references and other directory name
expansions while hacking completion. */
static int
@@ -2513,7 +2545,7 @@ glob_complete_word (text, state)
static char **matches = (char **)NULL;
static int ind;
int glen;
char *ret;
char *ret, *ttext;
if (state == 0)
{
@@ -2523,17 +2555,22 @@ glob_complete_word (text, state)
FREE (globorig);
FREE (globtext);
ttext = bash_tilde_expand (text, 0);
if (rl_explicit_arg)
{
globorig = savestring (text);
glen = strlen (text);
globorig = savestring (ttext);
glen = strlen (ttext);
globtext = (char *)xmalloc (glen + 2);
strcpy (globtext, text);
strcpy (globtext, ttext);
globtext[glen] = '*';
globtext[glen+1] = '\0';
}
else
globtext = globorig = savestring (text);
globtext = globorig = savestring (ttext);
if (ttext != text)
free (ttext);
matches = shell_glob_filename (globtext);
if (GLOB_FAILED (matches))
+2 -1
View File
@@ -402,7 +402,8 @@ brace_gobbler (text, tlen, indx, satisfy)
{
pass_next = 1;
i++;
level++;
if (quoted == 0)
level++;
continue;
}
#endif
+560
View File
@@ -0,0 +1,560 @@
/* braces.c -- code for doing word expansion in curly braces. */
/* Copyright (C) 1987-2003 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. */
/* Stuff in curly braces gets expanded before all other shell expansions. */
#include "config.h"
#if defined (BRACE_EXPANSION)
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include "bashansi.h"
#if defined (SHELL)
# include "shell.h"
#endif /* SHELL */
#include "general.h"
#include "shmbutil.h"
#include "chartypes.h"
#define brace_whitespace(c) (!(c) || (c) == ' ' || (c) == '\t' || (c) == '\n')
#define BRACE_SEQ_SPECIFIER ".."
/* Basic idea:
Segregate the text into 3 sections: preamble (stuff before an open brace),
postamble (stuff after the matching close brace) and amble (stuff after
preamble, and before postamble). Expand amble, and then tack on the
expansions to preamble. Expand postamble, and tack on the expansions to
the result so far.
*/
/* The character which is used to separate arguments. */
int brace_arg_separator = ',';
#if defined (__P)
static int brace_gobbler __P((char *, size_t, int *, int));
static char **expand_amble __P((char *, size_t, int));
static char **expand_seqterm __P((char *, size_t));
static char **mkseq __P((int, int, int));
static char **array_concat __P((char **, char **));
#else
static int brace_gobbler ();
static char **expand_amble ();
static char **expand_seqterm ();
static char **mkseq();
static char **array_concat ();
#endif
/* Return an array of strings; the brace expansion of TEXT. */
char **
brace_expand (text)
char *text;
{
register int start;
size_t tlen;
char *preamble, *postamble, *amble;
size_t alen;
char **tack, **result;
int i, j, c;
DECLARE_MBSTATE;
/* Find the text of the preamble. */
tlen = strlen (text);
i = 0;
c = brace_gobbler (text, tlen, &i, '{');
preamble = (char *)xmalloc (i + 1);
strncpy (preamble, text, i);
preamble[i] = '\0';
result = (char **)xmalloc (2 * sizeof (char *));
result[0] = preamble;
result[1] = (char *)NULL;
/* Special case. If we never found an exciting character, then
the preamble is all of the text, so just return that. */
if (c != '{')
return (result);
/* Find the amble. This is the stuff inside this set of braces. */
start = ++i;
c = brace_gobbler (text, tlen, &i, '}');
/* What if there isn't a matching close brace? */
if (c == 0)
{
#if defined (NOTDEF)
/* Well, if we found an unquoted BRACE_ARG_SEPARATOR between START
and I, then this should be an error. Otherwise, it isn't. */
j = start;
while (j < i)
{
if (text[j] == '\\')
{
j++;
ADVANCE_CHAR (text, tlen, j);
continue;
}
if (text[j] == brace_arg_separator)
{ /* { */
strvec_dispose (result);
report_error ("no closing `%c' in %s", '}', text);
throw_to_top_level ();
}
ADVANCE_CHAR (text, tlen, j);
}
#endif
free (preamble); /* Same as result[0]; see initialization. */
result[0] = savestring (text);
return (result);
}
#if defined (SHELL)
amble = substring (text, start, i);
alen = i - start;
#else
amble = (char *)xmalloc (1 + (i - start));
strncpy (amble, &text[start], (i - start));
alen = i - start;
amble[alen] = '\0';
#endif
#if defined (SHELL)
INITIALIZE_MBSTATE;
/* If the amble does not contain an unquoted BRACE_ARG_SEPARATOR, then
just return without doing any expansion. */
j = 0;
while (amble[j])
{
if (amble[j] == '\\')
{
j++;
ADVANCE_CHAR (amble, alen, j);
continue;
}
if (amble[j] == brace_arg_separator)
break;
ADVANCE_CHAR (amble, alen, j);
}
if (amble[j] == 0)
{
tack = expand_seqterm (amble, alen);
if (tack)
goto add_tack;
else
{
free (amble);
free (preamble);
result[0] = savestring (text);
return (result);
}
}
#endif /* SHELL */
tack = expand_amble (amble, alen, 0);
add_tack:
result = array_concat (result, tack);
free (amble);
strvec_dispose (tack);
postamble = text + i + 1;
tack = brace_expand (postamble);
result = array_concat (result, tack);
strvec_dispose (tack);
return (result);
}
/* Expand the text found inside of braces. We simply try to split the
text at BRACE_ARG_SEPARATORs into separate strings. We then brace
expand each slot which needs it, until there are no more slots which
need it. */
static char **
expand_amble (text, tlen, flags)
char *text;
size_t tlen;
int flags;
{
char **result, **partial;
char *tem;
int start, i, c;
DECLARE_MBSTATE;
result = (char **)NULL;
start = i = 0;
c = 1;
while (c)
{
c = brace_gobbler (text, tlen, &i, brace_arg_separator);
#if defined (SHELL)
tem = substring (text, start, i);
#else
tem = (char *)xmalloc (1 + (i - start));
strncpy (tem, &text[start], (i - start));
tem[i- start] = '\0';
#endif
partial = brace_expand (tem);
if (!result)
result = partial;
else
{
register int lr, lp, j;
lr = strvec_len (result);
lp = strvec_len (partial);
result = strvec_resize (result, lp + lr + 1);
for (j = 0; j < lp; j++)
result[lr + j] = partial[j];
result[lr + j] = (char *)NULL;
free (partial);
}
free (tem);
ADVANCE_CHAR (text, tlen, i);
start = i;
}
return (result);
}
#define ST_BAD 0
#define ST_INT 1
#define ST_CHAR 2
static char **
mkseq (start, end, type)
int start, end, type;
{
int n, incr, i;
char **result, *t;
n = abs (end - start) + 1;
result = strvec_create (n + 1);
incr = (start < end) ? 1 : -1;
/* Make sure we go through the loop at least once, so {3..3} prints `3' */
i = 0;
n = start;
do
{
if (type == ST_INT)
result[i++] = itos (n);
else
{
t = (char *)xmalloc (2);
t[0] = n;
t[1] = '\0';
result[i++] = t;
}
if (n == end)
break;
n += incr;
}
while (1);
result[i] = (char *)0;
return (result);
}
static char **
expand_seqterm (text, tlen)
char *text;
size_t tlen;
{
char *t, *lhs, *rhs;
int i, lhs_t, rhs_t, lhs_v, rhs_v;
intmax_t tl, tr;
char **result;
t = strstr (text, BRACE_SEQ_SPECIFIER);
if (t == 0)
return ((char **)NULL);
i = t - text; /* index of start of BRACE_SEQ_SPECIFIER */
lhs = substring (text, 0, i);
rhs = substring (text, i + sizeof(BRACE_SEQ_SPECIFIER) - 1, tlen);
if (lhs[0] == 0 || rhs[0] == 0)
{
free (lhs);
free (rhs);
return ((char **)NULL);
}
/* Now figure out whether LHS and RHS are integers or letters. Both
sides have to match. */
lhs_t = (legal_number (lhs, &tl)) ? ST_INT :
((ISALPHA (lhs[0]) && lhs[1] == 0) ? ST_CHAR : ST_BAD);
rhs_t = (legal_number (rhs, &tr)) ? ST_INT :
((ISALPHA (rhs[0]) && rhs[1] == 0) ? ST_CHAR : ST_BAD);
if (lhs_t != rhs_t || lhs_t == ST_BAD || rhs_t == ST_BAD)
{
free (lhs);
free (rhs);
return ((char **)NULL);
}
/* OK, we have something. It's either a sequence of integers, ascending
or descending, or a sequence or letters, ditto. Generate the sequence,
put it into a string vector, and return it. */
if (lhs_t == ST_CHAR)
{
lhs_v = (unsigned char)lhs[0];
rhs_v = (unsigned char)rhs[0];
}
else
{
lhs_v = tl; /* integer truncation */
rhs_v = tr;
}
result = mkseq (lhs_v, rhs_v, lhs_t);
free (lhs);
free (rhs);
return (result);
}
/* Start at INDEX, and skip characters in TEXT. Set INDEX to the
index of the character matching SATISFY. This understands about
quoting. Return the character that caused us to stop searching;
this is either the same as SATISFY, or 0. */
static int
brace_gobbler (text, tlen, indx, satisfy)
char *text;
size_t tlen;
int *indx;
int satisfy;
{
register int i, c, quoted, level, pass_next;
#if defined (SHELL)
int si;
char *t;
#endif
DECLARE_MBSTATE;
level = quoted = pass_next = 0;
i = *indx;
while (c = text[i])
{
if (pass_next)
{
pass_next = 0;
ADVANCE_CHAR (text, tlen, i);
continue;
}
/* A backslash escapes the next character. This allows backslash to
escape the quote character in a double-quoted string. */
if (c == '\\' && (quoted == 0 || quoted == '"' || quoted == '`'))
{
pass_next = 1;
i++;
continue;
}
#if defined (SHELL)
/* If compiling for the shell, treat ${...} like \{...} */
if (c == '$' && text[i+1] == '{' && quoted != '\'') /* } */
{
pass_next = 1;
i++;
level++;
continue;
}
#endif
if (quoted)
{
if (c == quoted)
quoted = 0;
ADVANCE_CHAR (text, tlen, i);
continue;
}
if (c == '"' || c == '\'' || c == '`')
{
quoted = c;
i++;
continue;
}
#if defined (SHELL)
/* Pass new-style command substitutions through unchanged. */
if (c == '$' && text[i+1] == '(') /* ) */
{
si = i + 2;
t = extract_command_subst (text, &si);
i = si;
free (t);
i++;
continue;
}
#endif
if (c == satisfy && level == 0 && quoted == 0)
{
/* We ignore an open brace surrounded by whitespace, and also
an open brace followed immediately by a close brace preceded
by whitespace. */
if (c == '{' &&
((!i || brace_whitespace (text[i - 1])) &&
(brace_whitespace (text[i + 1]) || text[i + 1] == '}')))
{
i++;
continue;
}
break;
}
if (c == '{')
level++;
else if (c == '}' && level)
level--;
ADVANCE_CHAR (text, tlen, i);
}
*indx = i;
return (c);
}
/* Return a new array of strings which is the result of appending each
string in ARR2 to each string in ARR1. The resultant array is
len (arr1) * len (arr2) long. For convenience, ARR1 (and its contents)
are free ()'ed. ARR1 can be NULL, in that case, a new version of ARR2
is returned. */
static char **
array_concat (arr1, arr2)
char **arr1, **arr2;
{
register int i, j, len, len1, len2;
register char **result;
if (arr1 == 0)
return (strvec_copy (arr2));
if (arr2 == 0)
return (strvec_copy (arr1));
len1 = strvec_len (arr1);
len2 = strvec_len (arr2);
result = (char **)xmalloc ((1 + (len1 * len2)) * sizeof (char *));
len = 0;
for (i = 0; i < len1; i++)
{
int strlen_1 = strlen (arr1[i]);
for (j = 0; j < len2; j++)
{
result[len] = (char *)xmalloc (1 + strlen_1 + strlen (arr2[j]));
strcpy (result[len], arr1[i]);
strcpy (result[len] + strlen_1, arr2[j]);
len++;
}
free (arr1[i]);
}
free (arr1);
result[len] = (char *)NULL;
return (result);
}
#if defined (TEST)
#include <stdio.h>
fatal_error (format, arg1, arg2)
char *format, *arg1, *arg2;
{
report_error (format, arg1, arg2);
exit (1);
}
report_error (format, arg1, arg2)
char *format, *arg1, *arg2;
{
fprintf (stderr, format, arg1, arg2);
fprintf (stderr, "\n");
}
main ()
{
char example[256];
for (;;)
{
char **result;
int i;
fprintf (stderr, "brace_expand> ");
if ((!fgets (example, 256, stdin)) ||
(strncmp (example, "quit", 4) == 0))
break;
if (strlen (example))
example[strlen (example) - 1] = '\0';
result = brace_expand (example);
for (i = 0; result[i]; i++)
printf ("%s\n", result[i]);
free_array (result);
}
}
/*
* Local variables:
* compile-command: "gcc -g -Bstatic -DTEST -o brace_expand braces.c general.o"
* end:
*/
#endif /* TEST */
#endif /* BRACE_EXPANSION */
+17 -5
View File
@@ -35,14 +35,17 @@ option is given, it is interpreted as follows:
-c the maximum size of core files created
-d the maximum size of a process's data segment
-f the maximum size of files created by the shell
-i the maximum number of pending signals
-l the maximum size a process may lock into memory
-m the maximum resident set size
-n the maximum number of open file descriptors
-p the pipe buffer size
-q the maximum number of bytes in POSIX message queues
-s the maximum stack size
-t the maximum amount of cpu time in seconds
-u the maximum number of user processes
-v the size of virtual memory
-v the size of virtual memory
-x the maximum number of file locks
If LIMIT is given, it is the new value of the specified resource;
the special LIMIT values `soft', `hard', and `unlimited' stand for
@@ -200,6 +203,9 @@ static RESOURCE_LIMITS limits[] = {
{ 'd', RLIMIT_DATA, 1024, "data seg size", "kbytes" },
#endif
{ 'f', RLIMIT_FILESIZE, 1024, "file size", "blocks" },
#ifdef RLIMIT_SIGPENDING
{ 'i', RLIMIT_SIGPENDING, 1, "pending signals", (char *)NULL },
#endif
#ifdef RLIMIT_MEMLOCK
{ 'l', RLIMIT_MEMLOCK, 1024, "max locked memory", "kbytes" },
#endif
@@ -208,6 +214,9 @@ static RESOURCE_LIMITS limits[] = {
#endif /* RLIMIT_RSS */
{ 'n', RLIMIT_OPENFILES, 1, "open files", (char *)NULL},
{ 'p', RLIMIT_PIPESIZE, 512, "pipe size", "512 bytes" },
#ifdef RLIMIT_MSGQUEUE
{ 'q', RLIMIT_MSGQUEUE, 1, "POSIX message queues", "bytes" },
#endif
#ifdef RLIMIT_STACK
{ 's', RLIMIT_STACK, 1024, "stack size", "kbytes" },
#endif
@@ -220,6 +229,9 @@ static RESOURCE_LIMITS limits[] = {
#endif
#ifdef RLIMIT_SWAP
{ 'w', RLIMIT_SWAP, 1024, "swap size", "kbytes" },
#endif
#ifdef RLIMIT_LOCKS
{ 'w', RLIMIT_LOCKS, 1, "file locks", (char *)NULL },
#endif
{ -1, -1, -1, (char *)NULL, (char *)NULL }
};
@@ -647,11 +659,11 @@ print_all_limits (mode)
for (i = 0; limits[i].option > 0; i++)
{
if (get_limit (i, &softlim, &hardlim) < 0)
if (get_limit (i, &softlim, &hardlim) == 0)
printone (i, (mode & LIMIT_SOFT) ? softlim : hardlim, 1);
else if (errno != EINVAL)
builtin_error ("%s: cannot get limit: %s", limits[i].description,
strerror (errno));
else
printone (i, (mode & LIMIT_SOFT) ? softlim : hardlim, 1);
}
}
@@ -670,7 +682,7 @@ printone (limind, curlim, pdesc)
else
sprintf (unitstr, "(-%c) ", limits[limind].option);
printf ("%-18s %16s", limits[limind].description, unitstr);
printf ("%-20s %16s", limits[limind].description, unitstr);
}
if (curlim == RLIM_INFINITY)
puts ("unlimited");
+725
View File
@@ -0,0 +1,725 @@
This file is ulimit.def, from which is created ulimit.c.
It implements the builtin "ulimit" in Bash.
Copyright (C) 1987-2003 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.
$PRODUCES ulimit.c
$BUILTIN ulimit
$FUNCTION ulimit_builtin
$DEPENDS_ON !_MINIX
$SHORT_DOC ulimit [-SHacdflmnpstuv] [limit]
Ulimit provides control over the resources available to processes
started by the shell, on systems that allow such control. If an
option is given, it is interpreted as follows:
-S use the `soft' resource limit
-H use the `hard' resource limit
-a all current limits are reported
-c the maximum size of core files created
-d the maximum size of a process's data segment
-f the maximum size of files created by the shell
-l the maximum size a process may lock into memory
-m the maximum resident set size
-n the maximum number of open file descriptors
-p the pipe buffer size
-s the maximum stack size
-t the maximum amount of cpu time in seconds
-u the maximum number of user processes
-v the size of virtual memory
If LIMIT is given, it is the new value of the specified resource;
the special LIMIT values `soft', `hard', and `unlimited' stand for
the current soft limit, the current hard limit, and no limit, respectively.
Otherwise, the current value of the specified resource is printed.
If no option is given, then -f is assumed. Values are in 1024-byte
increments, except for -t, which is in seconds, -p, which is in
increments of 512 bytes, and -u, which is an unscaled number of
processes.
$END
#if !defined (_MINIX)
#include <config.h>
#include "../bashtypes.h"
#ifndef _MINIX
# include <sys/param.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <stdio.h>
#include <errno.h>
#include "../bashintl.h"
#include "../shell.h"
#include "common.h"
#include "bashgetopt.h"
#include "pipesize.h"
#if !defined (errno)
extern int errno;
#endif
/* For some reason, HPUX chose to make these definitions visible only if
_KERNEL is defined, so we define _KERNEL before including <sys/resource.h>
and #undef it afterward. */
#if defined (HAVE_RESOURCE)
# include <sys/time.h>
# if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
# define _KERNEL
# endif
# include <sys/resource.h>
# if defined (HPUX) && defined (RLIMIT_NEEDS_KERNEL)
# undef _KERNEL
# endif
#else
# include <sys/times.h>
#endif
#if defined (HAVE_LIMITS_H)
# include <limits.h>
#endif
/* Check for the most basic symbols. If they aren't present, this
system's <sys/resource.h> isn't very useful to us. */
#if !defined (RLIMIT_FSIZE) || !defined (HAVE_GETRLIMIT)
# undef HAVE_RESOURCE
#endif
#if !defined (RLIMTYPE)
# define RLIMTYPE long
# define string_to_rlimtype(s) strtol(s, (char **)NULL, 10)
# define print_rlimtype(num, nl) printf ("%ld%s", num, nl ? "\n" : "")
#endif
/* Some systems use RLIMIT_NOFILE, others use RLIMIT_OFILE */
#if defined (HAVE_RESOURCE) && defined (RLIMIT_OFILE) && !defined (RLIMIT_NOFILE)
# define RLIMIT_NOFILE RLIMIT_OFILE
#endif /* HAVE_RESOURCE && RLIMIT_OFILE && !RLIMIT_NOFILE */
/* Some systems have these, some do not. */
#ifdef RLIMIT_FSIZE
# define RLIMIT_FILESIZE RLIMIT_FSIZE
#else
# define RLIMIT_FILESIZE 256
#endif
#define RLIMIT_PIPESIZE 257
#ifdef RLIMIT_NOFILE
# define RLIMIT_OPENFILES RLIMIT_NOFILE
#else
# define RLIMIT_OPENFILES 258
#endif
#ifdef RLIMIT_VMEM
# define RLIMIT_VIRTMEM RLIMIT_VMEM
# define RLIMIT_VMBLKSZ 1024
#else
# ifdef RLIMIT_AS
# define RLIMIT_VIRTMEM RLIMIT_AS
# define RLIMIT_VMBLKSZ 1024
# else
# define RLIMIT_VIRTMEM 259
# define RLIMIT_VMBLKSZ 1
# endif
#endif
#ifdef RLIMIT_NPROC
# define RLIMIT_MAXUPROC RLIMIT_NPROC
#else
# define RLIMIT_MAXUPROC 260
#endif
#if !defined (RLIM_INFINITY)
# define RLIM_INFINITY 0x7fffffff
#endif
#if !defined (RLIM_SAVED_CUR)
# define RLIM_SAVED_CUR RLIM_INFINITY
#endif
#if !defined (RLIM_SAVED_MAX)
# define RLIM_SAVED_MAX RLIM_INFINITY
#endif
#define LIMIT_HARD 0x01
#define LIMIT_SOFT 0x02
static int _findlim __P((int));
static int ulimit_internal __P((int, char *, int, int));
static int get_limit __P((int, RLIMTYPE *, RLIMTYPE *));
static int set_limit __P((int, RLIMTYPE, int));
static void printone __P((int, RLIMTYPE, int));
static void print_all_limits __P((int));
static int set_all_limits __P((int, RLIMTYPE));
static int filesize __P((RLIMTYPE *));
static int pipesize __P((RLIMTYPE *));
static int getmaxuprc __P((RLIMTYPE *));
static int getmaxvm __P((RLIMTYPE *, RLIMTYPE *));
typedef struct {
int option; /* The ulimit option for this limit. */
int parameter; /* Parameter to pass to get_limit (). */
int block_factor; /* Blocking factor for specific limit. */
char *description; /* Descriptive string to output. */
char *units; /* scale */
} RESOURCE_LIMITS;
static RESOURCE_LIMITS limits[] = {
#ifdef RLIMIT_CORE
{ 'c', RLIMIT_CORE, 1024, "core file size", "blocks" },
#endif
#ifdef RLIMIT_DATA
{ 'd', RLIMIT_DATA, 1024, "data seg size", "kbytes" },
#endif
{ 'f', RLIMIT_FILESIZE, 1024, "file size", "blocks" },
#ifdef RLIMIT_MEMLOCK
{ 'l', RLIMIT_MEMLOCK, 1024, "max locked memory", "kbytes" },
#endif
#ifdef RLIMIT_RSS
{ 'm', RLIMIT_RSS, 1024, "max memory size", "kbytes" },
#endif /* RLIMIT_RSS */
{ 'n', RLIMIT_OPENFILES, 1, "open files", (char *)NULL},
{ 'p', RLIMIT_PIPESIZE, 512, "pipe size", "512 bytes" },
#ifdef RLIMIT_STACK
{ 's', RLIMIT_STACK, 1024, "stack size", "kbytes" },
#endif
#ifdef RLIMIT_CPU
{ 't', RLIMIT_CPU, 1, "cpu time", "seconds" },
#endif /* RLIMIT_CPU */
{ 'u', RLIMIT_MAXUPROC, 1, "max user processes", (char *)NULL },
#if defined (HAVE_RESOURCE)
{ 'v', RLIMIT_VIRTMEM, RLIMIT_VMBLKSZ, "virtual memory", "kbytes" },
#endif
#ifdef RLIMIT_SWAP
{ 'w', RLIMIT_SWAP, 1024, "swap size", "kbytes" },
#endif
{ -1, -1, -1, (char *)NULL, (char *)NULL }
};
#define NCMDS (sizeof(limits) / sizeof(limits[0]))
typedef struct _cmd {
int cmd;
char *arg;
} ULCMD;
static ULCMD *cmdlist;
static int ncmd;
static int cmdlistsz;
#if !defined (HAVE_RESOURCE) && !defined (HAVE_ULIMIT)
long
ulimit (cmd, newlim)
int cmd;
long newlim;
{
errno = EINVAL;
return -1;
}
#endif /* !HAVE_RESOURCE && !HAVE_ULIMIT */
static int
_findlim (opt)
int opt;
{
register int i;
for (i = 0; limits[i].option > 0; i++)
if (limits[i].option == opt)
return i;
return -1;
}
static char optstring[4 + 2 * NCMDS];
/* Report or set limits associated with certain per-process resources.
See the help documentation in builtins.c for a full description. */
int
ulimit_builtin (list)
register WORD_LIST *list;
{
register char *s;
int c, limind, mode, opt, all_limits;
mode = 0;
all_limits = 0;
/* Idea stolen from pdksh -- build option string the first time called. */
if (optstring[0] == 0)
{
s = optstring;
*s++ = 'a'; *s++ = 'S'; *s++ = 'H';
for (c = 0; limits[c].option > 0; c++)
{
*s++ = limits[c].option;
*s++ = ';';
}
*s = '\0';
}
/* Initialize the command list. */
if (cmdlistsz == 0)
cmdlist = (ULCMD *)xmalloc ((cmdlistsz = 16) * sizeof (ULCMD));
ncmd = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, optstring)) != -1)
{
switch (opt)
{
case 'a':
all_limits++;
break;
/* -S and -H are modifiers, not real options. */
case 'S':
mode |= LIMIT_SOFT;
break;
case 'H':
mode |= LIMIT_HARD;
break;
case '?':
builtin_usage ();
return (EX_USAGE);
default:
if (ncmd >= cmdlistsz)
cmdlist = (ULCMD *)xrealloc (cmdlist, (cmdlistsz *= 2) * sizeof (ULCMD));
cmdlist[ncmd].cmd = opt;
cmdlist[ncmd++].arg = list_optarg;
break;
}
}
list = loptend;
if (all_limits)
{
#ifdef NOTYET
if (list) /* setting */
{
if (STREQ (list->word->word, "unlimited") == 0)
{
builtin_error (_("%s: invalid limit argument"), list->word->word);
return (EXECUTION_FAILURE);
}
return (set_all_limits (mode == 0 ? LIMIT_SOFT|LIMIT_HARD : mode, RLIM_INFINITY));
}
#endif
print_all_limits (mode == 0 ? LIMIT_SOFT : mode);
return (EXECUTION_SUCCESS);
}
/* default is `ulimit -f' */
if (ncmd == 0)
{
cmdlist[ncmd].cmd = 'f';
/* `ulimit something' is same as `ulimit -f something' */
cmdlist[ncmd++].arg = list ? list->word->word : (char *)NULL;
if (list)
list = list->next;
}
/* verify each command in the list. */
for (c = 0; c < ncmd; c++)
{
limind = _findlim (cmdlist[c].cmd);
if (limind == -1)
{
builtin_error (_("`%c': bad command"), cmdlist[c].cmd);
return (EX_USAGE);
}
}
for (c = 0; c < ncmd; c++)
if (ulimit_internal (cmdlist[c].cmd, cmdlist[c].arg, mode, ncmd > 1) == EXECUTION_FAILURE)
return (EXECUTION_FAILURE);
return (EXECUTION_SUCCESS);
}
static int
ulimit_internal (cmd, cmdarg, mode, multiple)
int cmd;
char *cmdarg;
int mode, multiple;
{
int opt, limind, setting;
int block_factor;
RLIMTYPE soft_limit, hard_limit, real_limit, limit;
setting = cmdarg != 0;
limind = _findlim (cmd);
if (mode == 0)
mode = setting ? (LIMIT_HARD|LIMIT_SOFT) : LIMIT_SOFT;
opt = get_limit (limind, &soft_limit, &hard_limit);
if (opt < 0)
{
builtin_error (_("%s: cannot get limit: %s"), limits[limind].description,
strerror (errno));
return (EXECUTION_FAILURE);
}
if (setting == 0) /* print the value of the specified limit */
{
printone (limind, (mode & LIMIT_SOFT) ? soft_limit : hard_limit, multiple);
return (EXECUTION_SUCCESS);
}
/* Setting the limit. */
if (STREQ (cmdarg, "hard"))
real_limit = hard_limit;
else if (STREQ (cmdarg, "soft"))
real_limit = soft_limit;
else if (STREQ (cmdarg, "unlimited"))
real_limit = RLIM_INFINITY;
else if (all_digits (cmdarg))
{
limit = string_to_rlimtype (cmdarg);
block_factor = limits[limind].block_factor;
real_limit = limit * block_factor;
if ((real_limit / block_factor) != limit)
{
sh_erange (cmdarg, "limit");
return (EXECUTION_FAILURE);
}
}
else
{
sh_invalidnum (cmdarg);
return (EXECUTION_FAILURE);
}
if (set_limit (limind, real_limit, mode) < 0)
{
builtin_error (_("%s: cannot modify limit: %s"), limits[limind].description,
strerror (errno));
return (EXECUTION_FAILURE);
}
return (EXECUTION_SUCCESS);
}
static int
get_limit (ind, softlim, hardlim)
int ind;
RLIMTYPE *softlim, *hardlim;
{
RLIMTYPE value;
#if defined (HAVE_RESOURCE)
struct rlimit limit;
#endif
if (limits[ind].parameter >= 256)
{
switch (limits[ind].parameter)
{
case RLIMIT_FILESIZE:
if (filesize (&value) < 0)
return -1;
break;
case RLIMIT_PIPESIZE:
if (pipesize (&value) < 0)
return -1;
break;
case RLIMIT_OPENFILES:
value = (RLIMTYPE)getdtablesize ();
break;
case RLIMIT_VIRTMEM:
return (getmaxvm (softlim, hardlim));
case RLIMIT_MAXUPROC:
if (getmaxuprc (&value) < 0)
return -1;
break;
default:
errno = EINVAL;
return -1;
}
*softlim = *hardlim = value;
return (0);
}
else
{
#if defined (HAVE_RESOURCE)
if (getrlimit (limits[ind].parameter, &limit) < 0)
return -1;
*softlim = limit.rlim_cur;
*hardlim = limit.rlim_max;
# if defined (HPUX9)
if (limits[ind].parameter == RLIMIT_FILESIZE)
{
*softlim *= 512;
*hardlim *= 512; /* Ugh. */
}
else
# endif /* HPUX9 */
return 0;
#else
errno = EINVAL;
return -1;
#endif
}
}
static int
set_limit (ind, newlim, mode)
int ind;
RLIMTYPE newlim;
int mode;
{
#if defined (HAVE_RESOURCE)
struct rlimit limit;
RLIMTYPE val;
#endif
if (limits[ind].parameter >= 256)
switch (limits[ind].parameter)
{
case RLIMIT_FILESIZE:
#if !defined (HAVE_RESOURCE)
return (ulimit (2, newlim / 512L));
#else
errno = EINVAL;
return -1;
#endif
case RLIMIT_OPENFILES:
#if defined (HAVE_SETDTABLESIZE)
# if defined (__CYGWIN__)
/* Grrr... Cygwin declares setdtablesize as void. */
setdtablesize (newlim);
return 0;
# else
return (setdtablesize (newlim));
# endif
#endif
case RLIMIT_PIPESIZE:
case RLIMIT_VIRTMEM:
case RLIMIT_MAXUPROC:
default:
errno = EINVAL;
return -1;
}
else
{
#if defined (HAVE_RESOURCE)
if (getrlimit (limits[ind].parameter, &limit) < 0)
return -1;
# if defined (HPUX9)
if (limits[ind].parameter == RLIMIT_FILESIZE)
newlim /= 512; /* Ugh. */
# endif /* HPUX9 */
val = (current_user.euid != 0 && newlim == RLIM_INFINITY &&
(mode & LIMIT_HARD) == 0 && /* XXX -- test */
(limit.rlim_cur <= limit.rlim_max))
? limit.rlim_max : newlim;
if (mode & LIMIT_SOFT)
limit.rlim_cur = val;
if (mode & LIMIT_HARD)
limit.rlim_max = val;
return (setrlimit (limits[ind].parameter, &limit));
#else
errno = EINVAL;
return -1;
#endif
}
}
static int
getmaxvm (softlim, hardlim)
RLIMTYPE *softlim, *hardlim;
{
#if defined (HAVE_RESOURCE)
struct rlimit datalim, stacklim;
if (getrlimit (RLIMIT_DATA, &datalim) < 0)
return -1;
if (getrlimit (RLIMIT_STACK, &stacklim) < 0)
return -1;
/* Protect against overflow. */
*softlim = (datalim.rlim_cur / 1024L) + (stacklim.rlim_cur / 1024L);
*hardlim = (datalim.rlim_max / 1024L) + (stacklim.rlim_max / 1024L);
return 0;
#else
errno = EINVAL;
return -1;
#endif /* HAVE_RESOURCE */
}
static int
filesize(valuep)
RLIMTYPE *valuep;
{
#if !defined (HAVE_RESOURCE)
long result;
if ((result = ulimit (1, 0L)) < 0)
return -1;
else
*valuep = (RLIMTYPE) result * 512;
return 0;
#else
errno = EINVAL;
return -1;
#endif
}
static int
pipesize (valuep)
RLIMTYPE *valuep;
{
#if defined (PIPE_BUF)
/* This is defined on Posix systems. */
*valuep = (RLIMTYPE) PIPE_BUF;
return 0;
#else
# if defined (PIPESIZE)
/* This is defined by running a program from the Makefile. */
*valuep = (RLIMTYPE) PIPESIZE;
return 0;
# else
errno = EINVAL;
return -1;
# endif /* PIPESIZE */
#endif /* PIPE_BUF */
}
static int
getmaxuprc (valuep)
RLIMTYPE *valuep;
{
long maxchild;
maxchild = getmaxchild ();
if (maxchild < 0)
{
errno = EINVAL;
return -1;
}
else
{
*valuep = (RLIMTYPE) maxchild;
return 0;
}
}
static void
print_all_limits (mode)
int mode;
{
register int i;
RLIMTYPE softlim, hardlim;
if (mode == 0)
mode |= LIMIT_SOFT;
for (i = 0; limits[i].option > 0; i++)
{
if (get_limit (i, &softlim, &hardlim) < 0)
builtin_error ("%s: cannot get limit: %s", limits[i].description,
strerror (errno));
else
printone (i, (mode & LIMIT_SOFT) ? softlim : hardlim, 1);
}
}
static void
printone (limind, curlim, pdesc)
int limind;
RLIMTYPE curlim;
int pdesc;
{
char unitstr[64];
if (pdesc)
{
if (limits[limind].units)
sprintf (unitstr, "(%s, -%c) ", limits[limind].units, limits[limind].option);
else
sprintf (unitstr, "(-%c) ", limits[limind].option);
printf ("%-18s %16s", limits[limind].description, unitstr);
}
if (curlim == RLIM_INFINITY)
puts ("unlimited");
else if (curlim == RLIM_SAVED_MAX)
puts ("hard");
else if (curlim == RLIM_SAVED_CUR)
puts ("soft");
else
print_rlimtype ((curlim / limits[limind].block_factor), 1);
}
/* Set all limits to NEWLIM. NEWLIM currently must be RLIM_INFINITY, which
causes all limits to be set as high as possible depending on mode (like
csh `unlimit'). Returns -1 if NEWLIM is invalid, 0 if all limits
were set successfully, and 1 if at least one limit could not be set.
To raise all soft limits to their corresponding hard limits, use
ulimit -S -a unlimited
To attempt to raise all hard limits to infinity (superuser-only), use
ulimit -H -a unlimited
To attempt to raise all soft and hard limits to infinity, use
ulimit -a unlimited
*/
static int
set_all_limits (mode, newlim)
int mode;
RLIMTYPE newlim;
{
register int i;
int retval = 0;
if (newlim != RLIM_INFINITY)
{
errno = EINVAL;
return -1;
}
if (mode == 0)
mode = LIMIT_SOFT|LIMIT_HARD;
for (retval = i = 0; limits[i].option > 0; i++)
if (set_limit (i, newlim, mode) < 0)
{
builtin_error ("%s: cannot modify limit: %s", limits[i].description,
strerror (errno));
retval = 1;
}
return retval;
}
#endif /* !_MINIX */
+4 -4
View File
@@ -6,12 +6,12 @@
.\" Case Western Reserve University
.\" chet@po.CWRU.Edu
.\"
.\" Last Change: Fri Aug 27 12:14:46 EDT 2004
.\" Last Change: Fri Sep 17 22:44:17 EDT 2004
.\"
.\" bash_builtins, strip all but Built-Ins section
.if \n(zZ=1 .ig zZ
.if \n(zY=1 .ig zY
.TH BASH 1 "2004 June 26" "GNU Bash-3.0"
.TH BASH 1 "2004 Sep 17" "GNU Bash-3.0"
.\"
.\" There's some problem with having a `@'
.\" in a tagged paragraph with the BSD man macros.
@@ -1228,8 +1228,8 @@ The command argument to the \fB\-c\fP invocation option.
An array variable whose members are the line numbers in source files
corresponding to each member of \fBFUNCNAME\fP.
\fB${BASH_LINENO[\fP\fI$i\fP\fB]}\fP is the line number in the source
file where \fB${FUNCNAME[\fP\fI$i + 1\fP\fB]}\fP was called.
The corresponding source file name is \fB${BASH_SOURCE[\fP\fI$i + 1\fP\fB]}\fB.
file where \fB${FUNCNAME[\fP\fI$ifP\fB]}\fP was called.
The corresponding source file name is \fB${BASH_SOURCE[\fP\fI$i\fP\fB]}\fB.
Use \fBLINENO\fP to obtain the current line number.
.TP
.B BASH_REMATCH
+6 -1
View File
@@ -3935,7 +3935,7 @@ sends a
.B SIGHUP
to all jobs when an interactive login shell exits.
.PP
If \Bbash\fP is waiting for a command to complete and receives a signal
If \fBbash\fP is waiting for a command to complete and receives a signal
for which a trap has been set, the trap will not be executed until
the command completes.
When \fBbash\fP is waiting for an asynchronous command via the \fBwait\fP
@@ -6186,6 +6186,11 @@ suppressing trailing spaces). Intended to be used with shell functions.
.B nospace
Tell readline not to append a space (the default) to words completed at
the end of the line.
.TP 8
.B plusdirs
After any matches defined by the compspec are generated,
directory name completion is attempted and any
matches are added to the results of the other actions.
.RE
.TP 8
\fB\-A\fP \fIaction\fP
+2 -2
View File
@@ -4278,8 +4278,8 @@ The command argument to the @option{-c} invocation option.
An array variable whose members are the line numbers in source files
corresponding to each member of @var{FUNCNAME}.
@code{$@{BASH_LINENO[$i]@}} is the line number in the source file where
@code{$@{FUNCNAME[$i + 1]@}} was called.
The corresponding source file name is @code{$@{BASH_SOURCE[$i + 1]@}}.
@code{$@{FUNCNAME[$i]@}} was called.
The corresponding source file name is @code{$@{BASH_SOURCE[$i]@}}.
Use @code{LINENO} to obtain the current line number.
@item BASH_REMATCH
+12 -2
View File
@@ -1256,6 +1256,10 @@ Expands to the positional parameters, starting from one. When the
expansion occurs within double quotes, each parameter expands to a
separate word. That is, @code{"$@@"} is equivalent to
@code{"$1" "$2" @dots{}}.
If the double-quoted expansion occurs within a word, the expansion of
the first parameter is joined with the beginning part of the original
word, and the expansion of the last parameter is joined with the last
part of the original word.
When there are no positional parameters, @code{"$@@"} and
@code{$@@}
expand to nothing (i.e., they are removed).
@@ -5537,12 +5541,18 @@ The braces are required to avoid
conflicts with the shell's filename expansion operators. If the
@var{subscript} is @samp{@@} or @samp{*}, the word expands to all members
of the array @var{name}. These subscripts differ only when the word
appears within double quotes. If the word is double-quoted,
appears within double quotes.
If the word is double-quoted,
@code{$@{name[*]@}} expands to a single word with
the value of each array member separated by the first character of the
@env{IFS} variable, and @code{$@{name[@@]@}} expands each element of
@var{name} to a separate word. When there are no array members,
@code{$@{name[@@]@}} expands to nothing. This is analogous to the
@code{$@{name[@@]@}} expands to nothing.
If the double-quoted expansion occurs within a word, the expansion of
the first parameter is joined with the beginning part of the original
word, and the expansion of the last parameter is joined with the last
part of the original word.
This is analogous to the
expansion of the special parameters @samp{@@} and @samp{*}.
@code{$@{#name[}@var{subscript}@code{]@}} expands to the length of
@code{$@{name[}@var{subscript}@code{]@}}.
+2 -2
View File
@@ -4,7 +4,7 @@ Copyright (C) 1988-2004 Free Software Foundation, Inc.
@set EDITION 3.0
@set VERSION 3.0
@set UPDATED 11 September 2004
@set UPDATED 17 September 2004
@set UPDATED-MONTH September 2004
@set LASTCHANGE Sat Sep 11 10:13:36 EDT 2004
@set LASTCHANGE Fri Sep 17 22:43:56 EDT 2004
+3 -3
View File
@@ -4,7 +4,7 @@ Copyright (C) 1988-2004 Free Software Foundation, Inc.
@set EDITION 3.0
@set VERSION 3.0
@set UPDATED 27 August 2004
@set UPDATED-MONTH August 2004
@set UPDATED 11 September 2004
@set UPDATED-MONTH September 2004
@set LASTCHANGE Fri Aug 27 12:15:06 EDT 2004
@set LASTCHANGE Sat Sep 11 10:13:36 EDT 2004
+10
View File
@@ -302,6 +302,16 @@ extern void strvec_sort __P((char **));
extern char **strvec_from_word_list __P((WORD_LIST *, int, int, int *));
extern WORD_LIST *strvec_to_word_list __P((char **, int, int));
/* declarations for functions defined in lib/sh/strnlen.c */
#if !defined (HAVE_STRNLEN)
extern size_t strnlen __P((const char *, size_t));
#endif
/* declarations for functions defined in lib/sh/strpbrk.c */
#if !defined (HAVE_STRPBRK)
extern char *strpbrk __P((const char *, const char *));
#endif
/* declarations for functions defined in lib/sh/strtod.c */
#if !defined (HAVE_STRTOD)
extern double strtod __P((const char *, char **));
+378
View File
@@ -0,0 +1,378 @@
/* externs.h -- extern function declarations which do not appear in their
own header file. */
/* Copyright (C) 1993-2002 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 (_EXTERNS_H_)
# define _EXTERNS_H_
#include "stdc.h"
/* Functions from expr.c. */
extern intmax_t evalexp __P((char *, int *));
/* Functions from print_cmd.c. */
extern char *make_command_string __P((COMMAND *));
extern char *named_function_string __P((char *, COMMAND *, int));
extern void print_command __P((COMMAND *));
extern void print_simple_command __P((SIMPLE_COM *));
extern void print_word_list __P((WORD_LIST *, char *));
/* debugger support */
extern void print_for_command_head __P((FOR_COM *));
#if defined (SELECT_COMMAND)
extern void print_select_command_head __P((SELECT_COM *));
#endif
extern void print_case_command_head __P((CASE_COM *));
#if defined (DPAREN_ARITHMETIC)
extern void print_arith_command __P((WORD_LIST *));
#endif
#if defined (COND_COMMAND)
extern void print_cond_command __P((COND_COM *));
#endif
/* set -x support */
extern char *indirection_level_string __P((void));
extern void xtrace_print_assignment __P((char *, char *, int, int));
extern void xtrace_print_word_list __P((WORD_LIST *, int));
extern void xtrace_print_for_command_head __P((FOR_COM *));
#if defined (SELECT_COMMAND)
extern void xtrace_print_select_command_head __P((SELECT_COM *));
#endif
extern void xtrace_print_case_command_head __P((CASE_COM *));
#if defined (DPAREN_ARITHMETIC)
extern void xtrace_print_arith_cmd __P((WORD_LIST *));
#endif
#if defined (COND_COMMAND)
extern void xtrace_print_cond_term __P((int, int, WORD_DESC *, char *, char *));
#endif
/* Functions from shell.c. */
extern void exit_shell __P((int)) __attribute__((__noreturn__));
extern void sh_exit __P((int)) __attribute__((__noreturn__));
extern void disable_priv_mode __P((void));
extern void unbind_args __P((void));
#if defined (RESTRICTED_SHELL)
extern int shell_is_restricted __P((char *));
extern int maybe_make_restricted __P((char *));
#endif
extern void unset_bash_input __P((int));
extern void get_current_user_info __P((void));
/* Functions from eval.c. */
extern int reader_loop __P((void));
extern int parse_command __P((void));
extern int read_command __P((void));
/* Functions from braces.c. */
#if defined (BRACE_EXPANSION)
extern char **brace_expand __P((char *));
#endif
/* Miscellaneous functions from parse.y */
extern int yyparse __P((void));
extern int return_EOF __P((void));
extern void reset_parser __P((void));
extern WORD_LIST *parse_string_to_word_list __P((char *, int, const char *));
extern void free_pushed_string_input __P((void));
extern char *decode_prompt_string __P((char *));
extern int get_current_prompt_level __P((void));
extern void set_current_prompt_level __P((int));
#if defined (HISTORY)
extern char *history_delimiting_chars __P((void));
#endif
/* Declarations for functions defined in locale.c */
extern void set_default_locale __P((void));
extern void set_default_locale_vars __P((void));
extern int set_locale_var __P((char *, char *));
extern int set_lang __P((char *, char *));
extern char *get_locale_var __P((char *));
extern char *localetrans __P((char *, int, int *));
extern char *mk_msgstr __P((char *, int *));
extern char *localeexpand __P((char *, int, int, int, int *));
/* Declarations for functions defined in list.c. */
extern void list_walk __P((GENERIC_LIST *, sh_glist_func_t *));
extern void wlist_walk __P((WORD_LIST *, sh_icpfunc_t *));
extern GENERIC_LIST *list_reverse ();
extern int list_length ();
extern GENERIC_LIST *list_append ();
extern GENERIC_LIST *list_remove ();
/* Declarations for functions defined in stringlib.c */
extern int find_string_in_alist __P((char *, STRING_INT_ALIST *, int));
extern char *find_token_in_alist __P((int, STRING_INT_ALIST *, int));
extern int find_index_in_alist __P((char *, STRING_INT_ALIST *, int));
extern char *substring __P((char *, int, int));
extern char *strsub __P((char *, char *, char *, int));
extern char *strcreplace __P((char *, int, char *, int));
extern void strip_leading __P((char *));
extern void strip_trailing __P((char *, int, int));
extern void xbcopy __P((char *, char *, int));
/* Functions from version.c. */
extern char *shell_version_string __P((void));
extern void show_shell_version __P((int));
/* Functions from the bash library, lib/sh/libsh.a. These should really
go into a separate include file. */
/* declarations for functions defined in lib/sh/clktck.c */
extern long get_clk_tck __P((void));
/* declarations for functions defined in lib/sh/clock.c */
extern void clock_t_to_secs ();
extern void print_clock_t ();
/* Declarations for functions defined in lib/sh/fmtulong.c */
#define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
#define FL_ADDBASE 0x02 /* add base# prefix to converted value */
#define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
#define FL_UNSIGNED 0x08 /* don't add any sign */
extern char *fmtulong __P((unsigned long int, int, char *, size_t, int));
/* Declarations for functions defined in lib/sh/fmtulong.c */
#if defined (HAVE_LONG_LONG)
extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
#endif
/* Declarations for functions defined in lib/sh/fmtumax.c */
extern char *fmtumax __P((uintmax_t, int, char *, size_t, int));
/* Declarations for functions defined in lib/sh/getcwd.c */
#if !defined (HAVE_GETCWD)
extern char *getcwd __P((char *, size_t));
#endif
/* Declarations for functions defined in lib/sh/itos.c */
extern char *inttostr __P((intmax_t, char *, size_t));
extern char *itos __P((intmax_t));
extern char *uinttostr __P((uintmax_t, char *, size_t));
extern char *uitos __P((uintmax_t));
/* declarations for functions defined in lib/sh/makepath.c */
#define MP_DOTILDE 0x01
#define MP_DOCWD 0x02
#define MP_RMDOT 0x04
extern char *sh_makepath __P((const char *, const char *, int));
/* declarations for functions defined in lib/sh/netconn.c */
extern int isnetconn __P((int));
/* declarations for functions defined in lib/sh/netopen.c */
extern int netopen __P((char *));
/* Declarations for functions defined in lib/sh/oslib.c */
#if !defined (HAVE_DUP2) || defined (DUP2_BROKEN)
extern int dup2 __P((int, int));
#endif
#if !defined (HAVE_GETDTABLESIZE)
extern int getdtablesize __P((void));
#endif /* !HAVE_GETDTABLESIZE */
#if !defined (HAVE_GETHOSTNAME)
extern int gethostname __P((char *, int));
#endif /* !HAVE_GETHOSTNAME */
extern int getmaxgroups __P((void));
extern long getmaxchild __P((void));
/* declarations for functions defined in lib/sh/pathcanon.c */
#define PATH_CHECKDOTDOT 0x0001
#define PATH_CHECKEXISTS 0x0002
#define PATH_HARDPATH 0x0004
#define PATH_NOALLOC 0x0008
extern char *sh_canonpath __P((char *, int));
/* declarations for functions defined in lib/sh/pathphys.c */
extern char *sh_physpath __P((char *, int));
extern char *sh_realpath __P((const char *, char *));
/* declarations for functions defined in lib/sh/setlinebuf.c */
#ifdef NEED_SH_SETLINEBUF_DECL
extern int sh_setlinebuf __P((FILE *));
#endif
/* declarations for functions defined in lib/sh/shmatch.c */
extern int sh_regmatch __P((const char *, const char *, int));
/* defines for flags argument to sh_regmatch. */
#define SHMAT_SUBEXP 0x001 /* save subexpressions in SH_REMATCH */
#define SHMAT_PWARN 0x002 /* print a warning message on invalid regexp */
/* declarations for functions defined in lib/sh/shquote.c */
extern char *sh_single_quote __P((char *));
extern char *sh_double_quote __P((char *));
extern char *sh_un_double_quote __P((char *));
extern char *sh_backslash_quote __P((char *));
extern char *sh_backslash_quote_for_double_quotes __P((char *));
extern int sh_contains_shell_metas __P((char *));
/* declarations for functions defined in lib/sh/spell.c */
extern int spname __P((char *, char *));
/* declarations for functions defined in lib/sh/strcasecmp.c */
#if !defined (HAVE_STRCASECMP)
extern int strncasecmp __P((const char *, const char *, int));
extern int strcasecmp __P((const char *, const char *));
#endif /* HAVE_STRCASECMP */
/* declarations for functions defined in lib/sh/strerror.c */
#if !defined (strerror)
extern char *strerror __P((int));
#endif
/* declarations for functions defined in lib/sh/strftime.c */
#if !defined (HAVE_STRFTIME) && defined (NEED_STRFTIME_DECL)
extern size_t strftime __P((char *, size_t, const char *, const struct tm *));
#endif
/* declarations for functions defined in lib/sh/strindex.c */
extern char *strindex __P((const char *, const char *));
/* declarations for functions and structures defined in lib/sh/stringlist.c */
/* This is a general-purpose argv-style array struct. */
typedef struct _list_of_strings {
char **list;
int list_size;
int list_len;
} STRINGLIST;
typedef int sh_strlist_map_func_t __P((char *));
extern STRINGLIST *strlist_create __P((int));
extern STRINGLIST *strlist_resize __P((STRINGLIST *, int));
extern void strlist_flush __P((STRINGLIST *));
extern void strlist_dispose __P((STRINGLIST *));
extern int strlist_remove __P((STRINGLIST *, char *));
extern STRINGLIST *strlist_copy __P((STRINGLIST *));
extern STRINGLIST *strlist_merge __P((STRINGLIST *, STRINGLIST *));
extern STRINGLIST *strlist_append __P((STRINGLIST *, STRINGLIST *));
extern STRINGLIST *strlist_prefix_suffix __P((STRINGLIST *, char *, char *));
extern void strlist_print __P((STRINGLIST *, char *));
extern void strlist_walk __P((STRINGLIST *, sh_strlist_map_func_t *));
extern void strlist_sort __P((STRINGLIST *));
/* declarations for functions defined in lib/sh/stringvec.c */
extern char **strvec_create __P((int));
extern char **strvec_resize __P((char **, int));
extern void strvec_flush __P((char **));
extern void strvec_dispose __P((char **));
extern int strvec_remove __P((char **, char *));
extern int strvec_len __P((char **));
extern int strvec_search __P((char **, char *));
extern char **strvec_copy __P((char **));
extern int strvec_strcmp __P((char **, char **));
extern void strvec_sort __P((char **));
extern char **strvec_from_word_list __P((WORD_LIST *, int, int, int *));
extern WORD_LIST *strvec_to_word_list __P((char **, int, int));
/* declarations for functions defined in lib/sh/strtod.c */
#if !defined (HAVE_STRTOD)
extern double strtod __P((const char *, char **));
#endif
/* declarations for functions defined in lib/sh/strtol.c */
#if !HAVE_DECL_STRTOL
extern long strtol __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strtoll.c */
#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOLL
extern long long strtoll __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strtoul.c */
#if !HAVE_DECL_STRTOUL
extern unsigned long strtoul __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strtoull.c */
#if defined (HAVE_LONG_LONG) && !HAVE_DECL_STRTOULL
extern unsigned long long strtoull __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strimax.c */
#if !HAVE_DECL_STRTOIMAX
extern intmax_t strtoimax __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strumax.c */
#if !HAVE_DECL_STRTOUMAX
extern uintmax_t strtoumax __P((const char *, char **, int));
#endif
/* declarations for functions defined in lib/sh/strtrans.c */
extern char *ansicstr __P((char *, int, int, int *, int *));
extern char *ansic_quote __P((char *, int, int *));
extern int ansic_shouldquote __P((const char *));
extern char *ansiexpand __P((char *, int, int, int *));
/* declarations for functions defined in lib/sh/timeval.c. No prototypes
so we don't have to count on having a definition of struct timeval in
scope when this file is included. */
extern void timeval_to_secs ();
extern void print_timeval ();
/* declarations for functions defined in lib/sh/tmpfile.c */
#define MT_USETMPDIR 0x0001
#define MT_READWRITE 0x0002
#define MT_USERANDOM 0x0004
extern char *sh_mktmpname __P((char *, int));
extern int sh_mktmpfd __P((char *, int, char **));
/* extern FILE *sh_mktmpfp __P((char *, int, char **)); */
/* declarations for functions defined in lib/sh/xstrchr.c */
#undef xstrchr
extern char *xstrchr __P((const char *, int));
/* declarations for functions defined in lib/sh/zcatfd.c */
extern int zcatfd __P((int, int, char *));
/* declarations for functions defined in lib/sh/zread.c */
extern ssize_t zread __P((int, char *, size_t));
extern ssize_t zreadintr __P((int, char *, size_t));
extern ssize_t zreadc __P((int, char *));
extern void zreset __P((void));
extern void zsyncfd __P((int));
/* declarations for functions defined in lib/sh/zwrite.c */
extern int zwrite __P((int, char *, size_t));
#endif /* _EXTERNS_H_ */
+6
View File
@@ -43,6 +43,9 @@ extern char *xstrchr __P((const char *, int));
#define MBSLEN(s) (((s) && (s)[0]) ? ((s)[1] ? mbstrlen (s) : 1) : 0)
#define MB_STRLEN(s) ((MB_CUR_MAX > 1) ? MBSLEN (s) : STRLEN (s))
#define MBLEN(s, n) ((MB_CUR_MAX > 1) ? mblen ((s), (n)) : 1)
#define MBRLEN(s, n, p) ((MB_CUR_MAX > 1) ? mbrlen ((s), (n), (p)) : 1)
#else /* !HANDLE_MULTIBYTE */
#undef MB_LEN_MAX
@@ -61,6 +64,9 @@ extern char *xstrchr __P((const char *, int));
#define MB_STRLEN(s) (STRLEN(s))
#define MBLEN(s, n) 1
#define MBRLEN(s, n, p) 1
#endif /* !HANDLE_MULTIBYTE */
/* Declare and initialize a multibyte state. Call must be terminated
+2 -1
View File
@@ -40,7 +40,8 @@ extern char *xstrchr __P((const char *, int));
#define MB_NULLWCH(x) ((x) == 0)
#endif
#define MB_STRLEN(s) ((MB_CUR_MAX > 1) ? mb_strlen (s) : STRLEN (s))
#define MBSLEN(s) (((s) && (s)[0]) ? ((s)[1] ? mbstrlen (s) : 1) : 0)
#define MB_STRLEN(s) ((MB_CUR_MAX > 1) ? MBSLEN (s) : STRLEN (s))
#else /* !HANDLE_MULTIBYTE */
+2 -2
View File
@@ -1160,7 +1160,7 @@ compute_lcd_of_matches (match_list, matches, text)
rl_completion_found_quote &&
rl_filename_quoting_desired)
{
dtext = (*rl_filename_dequoting_function) (text, rl_completion_quote_character);
dtext = (*rl_filename_dequoting_function) ((char *)text, rl_completion_quote_character);
text = dtext;
}
@@ -1543,7 +1543,7 @@ append_to_match (text, delimiter, quote_char, nontrivial_match)
: stat (filename, &finfo);
if (s == 0 && S_ISDIR (finfo.st_mode))
{
if (_rl_complete_mark_directories)
if (_rl_complete_mark_directories /* && rl_completion_suppress_append == 0 */)
{
/* This is clumsy. Avoid putting in a double slash if point
is at the end of the line and the previous character is a
File diff suppressed because it is too large Load Diff
+7 -1
View File
@@ -145,6 +145,9 @@ static char *_rl_term_kh;
static char *_rl_term_kH;
static char *_rl_term_at7; /* @7 */
/* Delete key */
static char *_rl_term_kD;
/* Insert key */
static char *_rl_term_kI;
@@ -313,6 +316,7 @@ static struct _tc_string tc_strings[] =
{ "ei", &_rl_term_ei },
{ "ic", &_rl_term_ic },
{ "im", &_rl_term_im },
{ "kD", &_rl_term_kD }, /* delete */
{ "kH", &_rl_term_kH }, /* home down ?? */
{ "kI", &_rl_term_kI }, /* insert */
{ "kd", &_rl_term_kd },
@@ -416,7 +420,7 @@ _rl_init_terminal_io (terminal_name)
_rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
_rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
_rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
_rl_term_kh = _rl_term_kH = _rl_term_kI = (char *)NULL;
_rl_term_kh = _rl_term_kH = _rl_term_kI = _rl_term_kD = (char *)NULL;
_rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL;
_rl_term_mm = _rl_term_mo = (char *)NULL;
_rl_term_ve = _rl_term_vs = (char *)NULL;
@@ -493,6 +497,8 @@ bind_termcap_arrow_keys (map)
rl_bind_keyseq_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
rl_bind_keyseq_if_unbound (_rl_term_at7, rl_end_of_line); /* End */
rl_bind_keyseq_if_unbound (_rl_term_kD, rl_delete);
_rl_keymap = xkeymap;
}
+658
View File
@@ -0,0 +1,658 @@
/* terminal.c -- controlling the terminal with termcap. */
/* Copyright (C) 1996 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 (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <sys/types.h>
#include "posixstat.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_LOCALE_H)
# include <locale.h>
#endif
#include <stdio.h>
/* System-specific feature definitions and include files. */
#include "rldefs.h"
#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
# include <sys/ioctl.h>
#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
#include "rltty.h"
#include "tcap.h"
/* Some standard library routines. */
#include "readline.h"
#include "history.h"
#include "rlprivate.h"
#include "rlshell.h"
#include "xmalloc.h"
#define CUSTOM_REDISPLAY_FUNC() (rl_redisplay_function != rl_redisplay)
#define CUSTOM_INPUT_FUNC() (rl_getc_function != rl_getc)
/* **************************************************************** */
/* */
/* Terminal and Termcap */
/* */
/* **************************************************************** */
static char *term_buffer = (char *)NULL;
static char *term_string_buffer = (char *)NULL;
static int tcap_initialized;
#if !defined (__linux__)
# if defined (__EMX__) || defined (NEED_EXTERN_PC)
extern
# endif /* __EMX__ || NEED_EXTERN_PC */
char PC, *BC, *UP;
#endif /* __linux__ */
/* Some strings to control terminal actions. These are output by tputs (). */
char *_rl_term_clreol;
char *_rl_term_clrpag;
char *_rl_term_cr;
char *_rl_term_backspace;
char *_rl_term_goto;
char *_rl_term_pc;
/* Non-zero if we determine that the terminal can do character insertion. */
int _rl_terminal_can_insert = 0;
/* How to insert characters. */
char *_rl_term_im;
char *_rl_term_ei;
char *_rl_term_ic;
char *_rl_term_ip;
char *_rl_term_IC;
/* How to delete characters. */
char *_rl_term_dc;
char *_rl_term_DC;
#if defined (HACK_TERMCAP_MOTION)
char *_rl_term_forward_char;
#endif /* HACK_TERMCAP_MOTION */
/* How to go up a line. */
char *_rl_term_up;
/* A visible bell; char if the terminal can be made to flash the screen. */
static char *_rl_visible_bell;
/* Non-zero means the terminal can auto-wrap lines. */
int _rl_term_autowrap;
/* Non-zero means that this terminal has a meta key. */
static int term_has_meta;
/* The sequences to write to turn on and off the meta key, if this
terminal has one. */
static char *_rl_term_mm;
static char *_rl_term_mo;
/* The key sequences output by the arrow keys, if this terminal has any. */
static char *_rl_term_ku;
static char *_rl_term_kd;
static char *_rl_term_kr;
static char *_rl_term_kl;
/* How to initialize and reset the arrow keys, if this terminal has any. */
static char *_rl_term_ks;
static char *_rl_term_ke;
/* The key sequences sent by the Home and End keys, if any. */
static char *_rl_term_kh;
static char *_rl_term_kH;
static char *_rl_term_at7; /* @7 */
/* Insert key */
static char *_rl_term_kI;
/* Cursor control */
static char *_rl_term_vs; /* very visible */
static char *_rl_term_ve; /* normal */
static void bind_termcap_arrow_keys PARAMS((Keymap));
/* Variables that hold the screen dimensions, used by the display code. */
int _rl_screenwidth, _rl_screenheight, _rl_screenchars;
/* Non-zero means the user wants to enable the keypad. */
int _rl_enable_keypad;
/* Non-zero means the user wants to enable a meta key. */
int _rl_enable_meta = 1;
#if defined (__EMX__)
static void
_emx_get_screensize (swp, shp)
int *swp, *shp;
{
int sz[2];
_scrsize (sz);
if (swp)
*swp = sz[0];
if (shp)
*shp = sz[1];
}
#endif
/* Get readline's idea of the screen size. TTY is a file descriptor open
to the terminal. If IGNORE_ENV is true, we do not pay attention to the
values of $LINES and $COLUMNS. The tests for TERM_STRING_BUFFER being
non-null serve to check whether or not we have initialized termcap. */
void
_rl_get_screen_size (tty, ignore_env)
int tty, ignore_env;
{
char *ss;
#if defined (TIOCGWINSZ)
struct winsize window_size;
#endif /* TIOCGWINSZ */
#if defined (TIOCGWINSZ)
if (ioctl (tty, TIOCGWINSZ, &window_size) == 0)
{
_rl_screenwidth = (int) window_size.ws_col;
_rl_screenheight = (int) window_size.ws_row;
}
#endif /* TIOCGWINSZ */
#if defined (__EMX__)
_emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
#endif
/* Environment variable COLUMNS overrides setting of "co" if IGNORE_ENV
is unset. */
if (_rl_screenwidth <= 0)
{
if (ignore_env == 0 && (ss = sh_get_env_value ("COLUMNS")))
_rl_screenwidth = atoi (ss);
#if !defined (__DJGPP__)
if (_rl_screenwidth <= 0 && term_string_buffer)
_rl_screenwidth = tgetnum ("co");
#endif
}
/* Environment variable LINES overrides setting of "li" if IGNORE_ENV
is unset. */
if (_rl_screenheight <= 0)
{
if (ignore_env == 0 && (ss = sh_get_env_value ("LINES")))
_rl_screenheight = atoi (ss);
#if !defined (__DJGPP__)
if (_rl_screenheight <= 0 && term_string_buffer)
_rl_screenheight = tgetnum ("li");
#endif
}
/* If all else fails, default to 80x24 terminal. */
if (_rl_screenwidth <= 1)
_rl_screenwidth = 80;
if (_rl_screenheight <= 0)
_rl_screenheight = 24;
/* If we're being compiled as part of bash, set the environment
variables $LINES and $COLUMNS to new values. Otherwise, just
do a pair of putenv () or setenv () calls. */
sh_set_lines_and_columns (_rl_screenheight, _rl_screenwidth);
if (_rl_term_autowrap == 0)
_rl_screenwidth--;
_rl_screenchars = _rl_screenwidth * _rl_screenheight;
}
void
_rl_set_screen_size (rows, cols)
int rows, cols;
{
if (rows == 0 || cols == 0)
return;
_rl_screenheight = rows;
_rl_screenwidth = cols;
if (_rl_term_autowrap == 0)
_rl_screenwidth--;
_rl_screenchars = _rl_screenwidth * _rl_screenheight;
}
void
rl_set_screen_size (rows, cols)
int rows, cols;
{
_rl_set_screen_size (rows, cols);
}
void
rl_get_screen_size (rows, cols)
int *rows, *cols;
{
if (rows)
*rows = _rl_screenheight;
if (cols)
*cols = _rl_screenwidth;
}
void
rl_resize_terminal ()
{
if (readline_echoing_p)
{
_rl_get_screen_size (fileno (rl_instream), 1);
if (CUSTOM_REDISPLAY_FUNC ())
rl_forced_update_display ();
else
_rl_redisplay_after_sigwinch ();
}
}
struct _tc_string {
const char *tc_var;
char **tc_value;
};
/* This should be kept sorted, just in case we decide to change the
search algorithm to something smarter. */
static struct _tc_string tc_strings[] =
{
{ "@7", &_rl_term_at7 },
{ "DC", &_rl_term_DC },
{ "IC", &_rl_term_IC },
{ "ce", &_rl_term_clreol },
{ "cl", &_rl_term_clrpag },
{ "cr", &_rl_term_cr },
{ "dc", &_rl_term_dc },
{ "ei", &_rl_term_ei },
{ "ic", &_rl_term_ic },
{ "im", &_rl_term_im },
{ "kH", &_rl_term_kH }, /* home down ?? */
{ "kI", &_rl_term_kI }, /* insert */
{ "kd", &_rl_term_kd },
{ "ke", &_rl_term_ke }, /* end keypad mode */
{ "kh", &_rl_term_kh }, /* home */
{ "kl", &_rl_term_kl },
{ "kr", &_rl_term_kr },
{ "ks", &_rl_term_ks }, /* start keypad mode */
{ "ku", &_rl_term_ku },
{ "le", &_rl_term_backspace },
{ "mm", &_rl_term_mm },
{ "mo", &_rl_term_mo },
#if defined (HACK_TERMCAP_MOTION)
{ "nd", &_rl_term_forward_char },
#endif
{ "pc", &_rl_term_pc },
{ "up", &_rl_term_up },
{ "vb", &_rl_visible_bell },
{ "vs", &_rl_term_vs },
{ "ve", &_rl_term_ve },
};
#define NUM_TC_STRINGS (sizeof (tc_strings) / sizeof (struct _tc_string))
/* Read the desired terminal capability strings into BP. The capabilities
are described in the TC_STRINGS table. */
static void
get_term_capabilities (bp)
char **bp;
{
#if !defined (__DJGPP__) /* XXX - doesn't DJGPP have a termcap library? */
register int i;
for (i = 0; i < NUM_TC_STRINGS; i++)
*(tc_strings[i].tc_value) = tgetstr ((char *)tc_strings[i].tc_var, bp);
#endif
tcap_initialized = 1;
}
int
_rl_init_terminal_io (terminal_name)
const char *terminal_name;
{
const char *term;
char *buffer;
int tty, tgetent_ret;
term = terminal_name ? terminal_name : sh_get_env_value ("TERM");
_rl_term_clrpag = _rl_term_cr = _rl_term_clreol = (char *)NULL;
tty = rl_instream ? fileno (rl_instream) : 0;
_rl_screenwidth = _rl_screenheight = 0;
if (term == 0)
term = "dumb";
/* I've separated this out for later work on not calling tgetent at all
if the calling application has supplied a custom redisplay function,
(and possibly if the application has supplied a custom input function). */
if (CUSTOM_REDISPLAY_FUNC())
{
tgetent_ret = -1;
}
else
{
if (term_string_buffer == 0)
term_string_buffer = (char *)xmalloc(2032);
if (term_buffer == 0)
term_buffer = (char *)xmalloc(4080);
buffer = term_string_buffer;
tgetent_ret = tgetent (term_buffer, term);
}
if (tgetent_ret <= 0)
{
FREE (term_string_buffer);
FREE (term_buffer);
buffer = term_buffer = term_string_buffer = (char *)NULL;
_rl_term_autowrap = 0; /* used by _rl_get_screen_size */
#if defined (__EMX__)
_emx_get_screensize (&_rl_screenwidth, &_rl_screenheight);
_rl_screenwidth--;
#else /* !__EMX__ */
_rl_get_screen_size (tty, 0);
#endif /* !__EMX__ */
/* Defaults. */
if (_rl_screenwidth <= 0 || _rl_screenheight <= 0)
{
_rl_screenwidth = 79;
_rl_screenheight = 24;
}
/* Everything below here is used by the redisplay code (tputs). */
_rl_screenchars = _rl_screenwidth * _rl_screenheight;
_rl_term_cr = "\r";
_rl_term_im = _rl_term_ei = _rl_term_ic = _rl_term_IC = (char *)NULL;
_rl_term_up = _rl_term_dc = _rl_term_DC = _rl_visible_bell = (char *)NULL;
_rl_term_ku = _rl_term_kd = _rl_term_kl = _rl_term_kr = (char *)NULL;
_rl_term_kh = _rl_term_kH = _rl_term_kI = (char *)NULL;
_rl_term_ks = _rl_term_ke = _rl_term_at7 = (char *)NULL;
_rl_term_mm = _rl_term_mo = (char *)NULL;
_rl_term_ve = _rl_term_vs = (char *)NULL;
#if defined (HACK_TERMCAP_MOTION)
term_forward_char = (char *)NULL;
#endif
_rl_terminal_can_insert = term_has_meta = 0;
/* Reasonable defaults for tgoto(). Readline currently only uses
tgoto if _rl_term_IC or _rl_term_DC is defined, but just in case we
change that later... */
PC = '\0';
BC = _rl_term_backspace = "\b";
UP = _rl_term_up;
return 0;
}
get_term_capabilities (&buffer);
/* Set up the variables that the termcap library expects the application
to provide. */
PC = _rl_term_pc ? *_rl_term_pc : 0;
BC = _rl_term_backspace;
UP = _rl_term_up;
if (!_rl_term_cr)
_rl_term_cr = "\r";
_rl_term_autowrap = tgetflag ("am") && tgetflag ("xn");
_rl_get_screen_size (tty, 0);
/* "An application program can assume that the terminal can do
character insertion if *any one of* the capabilities `IC',
`im', `ic' or `ip' is provided." But we can't do anything if
only `ip' is provided, so... */
_rl_terminal_can_insert = (_rl_term_IC || _rl_term_im || _rl_term_ic);
/* Check to see if this terminal has a meta key and clear the capability
variables if there is none. */
term_has_meta = (tgetflag ("km") || tgetflag ("MT"));
if (!term_has_meta)
_rl_term_mm = _rl_term_mo = (char *)NULL;
/* Attempt to find and bind the arrow keys. Do not override already
bound keys in an overzealous attempt, however. */
bind_termcap_arrow_keys (emacs_standard_keymap);
#if defined (VI_MODE)
bind_termcap_arrow_keys (vi_movement_keymap);
bind_termcap_arrow_keys (vi_insertion_keymap);
#endif /* VI_MODE */
return 0;
}
/* Bind the arrow key sequences from the termcap description in MAP. */
static void
bind_termcap_arrow_keys (map)
Keymap map;
{
Keymap xkeymap;
xkeymap = _rl_keymap;
_rl_keymap = map;
rl_bind_keyseq_if_unbound (_rl_term_ku, rl_get_previous_history);
rl_bind_keyseq_if_unbound (_rl_term_kd, rl_get_next_history);
rl_bind_keyseq_if_unbound (_rl_term_kr, rl_forward_char);
rl_bind_keyseq_if_unbound (_rl_term_kl, rl_backward_char);
rl_bind_keyseq_if_unbound (_rl_term_kh, rl_beg_of_line); /* Home */
rl_bind_keyseq_if_unbound (_rl_term_at7, rl_end_of_line); /* End */
_rl_keymap = xkeymap;
}
char *
rl_get_termcap (cap)
const char *cap;
{
register int i;
if (tcap_initialized == 0)
return ((char *)NULL);
for (i = 0; i < NUM_TC_STRINGS; i++)
{
if (tc_strings[i].tc_var[0] == cap[0] && strcmp (tc_strings[i].tc_var, cap) == 0)
return *(tc_strings[i].tc_value);
}
return ((char *)NULL);
}
/* Re-initialize the terminal considering that the TERM/TERMCAP variable
has changed. */
int
rl_reset_terminal (terminal_name)
const char *terminal_name;
{
_rl_init_terminal_io (terminal_name);
return 0;
}
/* A function for the use of tputs () */
#ifdef _MINIX
void
_rl_output_character_function (c)
int c;
{
putc (c, _rl_out_stream);
}
#else /* !_MINIX */
int
_rl_output_character_function (c)
int c;
{
return putc (c, _rl_out_stream);
}
#endif /* !_MINIX */
/* Write COUNT characters from STRING to the output stream. */
void
_rl_output_some_chars (string, count)
const char *string;
int count;
{
fwrite (string, 1, count, _rl_out_stream);
}
/* Move the cursor back. */
int
_rl_backspace (count)
int count;
{
register int i;
if (_rl_term_backspace)
for (i = 0; i < count; i++)
tputs (_rl_term_backspace, 1, _rl_output_character_function);
else
for (i = 0; i < count; i++)
putc ('\b', _rl_out_stream);
return 0;
}
/* Move to the start of the next line. */
int
rl_crlf ()
{
#if defined (NEW_TTY_DRIVER)
if (_rl_term_cr)
tputs (_rl_term_cr, 1, _rl_output_character_function);
#endif /* NEW_TTY_DRIVER */
putc ('\n', _rl_out_stream);
return 0;
}
/* Ring the terminal bell. */
int
rl_ding ()
{
if (readline_echoing_p)
{
switch (_rl_bell_preference)
{
case NO_BELL:
default:
break;
case VISIBLE_BELL:
if (_rl_visible_bell)
{
tputs (_rl_visible_bell, 1, _rl_output_character_function);
break;
}
/* FALLTHROUGH */
case AUDIBLE_BELL:
fprintf (stderr, "\007");
fflush (stderr);
break;
}
return (0);
}
return (-1);
}
/* **************************************************************** */
/* */
/* Controlling the Meta Key and Keypad */
/* */
/* **************************************************************** */
void
_rl_enable_meta_key ()
{
#if !defined (__DJGPP__)
if (term_has_meta && _rl_term_mm)
tputs (_rl_term_mm, 1, _rl_output_character_function);
#endif
}
void
_rl_control_keypad (on)
int on;
{
#if !defined (__DJGPP__)
if (on && _rl_term_ks)
tputs (_rl_term_ks, 1, _rl_output_character_function);
else if (!on && _rl_term_ke)
tputs (_rl_term_ke, 1, _rl_output_character_function);
#endif
}
/* **************************************************************** */
/* */
/* Controlling the Cursor */
/* */
/* **************************************************************** */
/* Set the cursor appropriately depending on IM, which is one of the
insert modes (insert or overwrite). Insert mode gets the normal
cursor. Overwrite mode gets a very visible cursor. Only does
anything if we have both capabilities. */
void
_rl_set_cursor (im, force)
int im, force;
{
if (_rl_term_ve && _rl_term_vs)
{
if (force || im != rl_insert_mode)
{
if (im == RL_IM_OVERWRITE)
tputs (_rl_term_vs, 1, _rl_output_character_function);
else
tputs (_rl_term_ve, 1, _rl_output_character_function);
}
}
}
+7 -2
View File
@@ -128,7 +128,11 @@ sh_un_double_quote (string)
}
/* Quote special characters in STRING using backslashes. Return a new
string. */
string. NOTE: if the string is to be further expanded, we need a
way to protect the CTLESC and CTLNUL characters. As I write this,
the current callers will never cause the string to be expanded without
going through the shell parser, which will protect the internal
quoting characters. */
char *
sh_backslash_quote (string)
char *string;
@@ -160,11 +164,12 @@ sh_backslash_quote (string)
*r++ = '\\';
*r++ = c;
break;
#endif
case CTLESC: case CTLNUL: /* internal quoting characters */
*r++ = CTLESC; /* could be '\\'? */
*r++ = c;
break;
#endif
case '#': /* comment char */
if (s == string)
+244
View File
@@ -0,0 +1,244 @@
/* Copyright (C) 1999 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>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include <stdio.h>
#include "syntax.h"
#include <xmalloc.h>
/* **************************************************************** */
/* */
/* Functions for quoting strings to be re-read as input */
/* */
/* **************************************************************** */
/* Return a new string which is the single-quoted version of STRING.
Used by alias and trap, among others. */
char *
sh_single_quote (string)
char *string;
{
register int c;
char *result, *r, *s;
result = (char *)xmalloc (3 + (4 * strlen (string)));
r = result;
*r++ = '\'';
for (s = string; s && (c = *s); s++)
{
*r++ = c;
if (c == '\'')
{
*r++ = '\\'; /* insert escaped single quote */
*r++ = '\'';
*r++ = '\''; /* start new quoted string */
}
}
*r++ = '\'';
*r = '\0';
return (result);
}
/* Quote STRING using double quotes. Return a new string. */
char *
sh_double_quote (string)
char *string;
{
register unsigned char c;
char *result, *r, *s;
result = (char *)xmalloc (3 + (2 * strlen (string)));
r = result;
*r++ = '"';
for (s = string; s && (c = *s); s++)
{
if (sh_syntaxtab[c] & CBSDQUOTE)
*r++ = '\\';
else if (c == CTLESC || c == CTLNUL)
*r++ = CTLESC; /* could be '\\'? */
*r++ = c;
}
*r++ = '"';
*r = '\0';
return (result);
}
/* Remove backslashes that are quoting characters that are special between
double quotes. Return a new string. XXX - should this handle CTLESC
and CTLNUL? */
char *
sh_un_double_quote (string)
char *string;
{
register int c, pass_next;
char *result, *r, *s;
r = result = (char *)xmalloc (strlen (string) + 1);
for (pass_next = 0, s = string; s && (c = *s); s++)
{
if (pass_next)
{
*r++ = c;
pass_next = 0;
continue;
}
if (c == '\\' && (sh_syntaxtab[(unsigned char) s[1]] & CBSDQUOTE))
{
pass_next = 1;
continue;
}
*r++ = c;
}
*r = '\0';
return result;
}
/* Quote special characters in STRING using backslashes. Return a new
string. */
char *
sh_backslash_quote (string)
char *string;
{
int c;
char *result, *r, *s;
result = (char *)xmalloc (2 * strlen (string) + 1);
for (r = result, s = string; s && (c = *s); s++)
{
switch (c)
{
case ' ': case '\t': case '\n': /* IFS white space */
case '\'': case '"': case '\\': /* quoting chars */
case '|': case '&': case ';': /* shell metacharacters */
case '(': case ')': case '<': case '>':
case '!': case '{': case '}': /* reserved words */
case '*': case '[': case '?': case ']': /* globbing chars */
case '^':
case '$': case '`': /* expansion chars */
case ',': /* brace expansion */
*r++ = '\\';
*r++ = c;
break;
#if 0
case '~': /* tilde expansion */
if (s == string || s[-1] == '=' || s[-1] == ':')
*r++ = '\\';
*r++ = c;
break;
#endif
case CTLESC: case CTLNUL: /* internal quoting characters */
*r++ = CTLESC; /* could be '\\'? */
*r++ = c;
break;
case '#': /* comment char */
if (s == string)
*r++ = '\\';
/* FALLTHROUGH */
default:
*r++ = c;
break;
}
}
*r = '\0';
return (result);
}
#if defined (PROMPT_STRING_DECODE)
/* Quote characters that get special treatment when in double quotes in STRING
using backslashes. Return a new string. */
char *
sh_backslash_quote_for_double_quotes (string)
char *string;
{
unsigned char c;
char *result, *r, *s;
result = (char *)xmalloc (2 * strlen (string) + 1);
for (r = result, s = string; s && (c = *s); s++)
{
if (sh_syntaxtab[c] & CBSDQUOTE)
*r++ = '\\';
/* I should probably add flags for these to sh_syntaxtab[] */
else if (c == CTLESC || c == CTLNUL)
*r++ = CTLESC; /* could be '\\'? */
*r++ = c;
}
*r = '\0';
return (result);
}
#endif /* PROMPT_STRING_DECODE */
int
sh_contains_shell_metas (string)
char *string;
{
char *s;
for (s = string; s && *s; s++)
{
switch (*s)
{
case ' ': case '\t': case '\n': /* IFS white space */
case '\'': case '"': case '\\': /* quoting chars */
case '|': case '&': case ';': /* shell metacharacters */
case '(': case ')': case '<': case '>':
case '!': case '{': case '}': /* reserved words */
case '*': case '[': case '?': case ']': /* globbing chars */
case '^':
case '$': case '`': /* expansion chars */
return (1);
case '~': /* tilde expansion */
if (s == string || s[-1] == '=' || s[-1] == ':')
return (1);
break;
case '#':
if (s == string) /* comment char */
return (1);
/* FALLTHROUGH */
default:
break;
}
}
return (0);
}
+18 -14
View File
@@ -122,6 +122,15 @@ find_mail_file (file)
} \
while (0)
#define UPDATE_MAIL_FILE(i, finfo) \
do \
{ \
mailfiles[i]->access_time = finfo.st_atime; \
mailfiles[i]->mod_time = finfo.st_mtime; \
mailfiles[i]->file_size = finfo.st_size; \
} \
while (0)
static void
update_mail_file (i)
int i;
@@ -131,11 +140,7 @@ update_mail_file (i)
file = mailfiles[i]->name;
if (mailstat (file, &finfo) == 0)
{
mailfiles[i]->access_time = finfo.st_atime;
mailfiles[i]->mod_time = finfo.st_mtime;
mailfiles[i]->file_size = finfo.st_size;
}
UPDATE_MAIL_FILE (i, finfo);
else
RESET_MAIL_FILE (i);
}
@@ -155,11 +160,8 @@ add_mail_file (file, msg)
if (i >= 0)
{
if (mailstat (filename, &finfo) == 0)
{
mailfiles[i]->mod_time = finfo.st_mtime;
mailfiles[i]->access_time = finfo.st_atime;
mailfiles[i]->file_size = finfo.st_size;
}
UPDATE_MAIL_FILE (i, finfo);
free (filename);
return i;
}
@@ -182,9 +184,7 @@ reset_mail_files ()
register int i;
for (i = 0; i < mailfiles_count; i++)
{
RESET_MAIL_FILE (i);
}
RESET_MAIL_FILE (i);
}
/* Free the information that we have about the remembered mail files. */
@@ -208,7 +208,8 @@ free_mail_files ()
}
/* Return non-zero if FILE's mod date has changed and it has not been
accessed since modified. */
accessed since modified. If the size has dropped to zero, reset
the cached mail file info. */
static int
file_mod_date_changed (i)
int i;
@@ -223,6 +224,9 @@ file_mod_date_changed (i)
if ((mailstat (file, &finfo) == 0) && (finfo.st_size > 0))
return (mtime != finfo.st_mtime);
if (finfo.st_size == 0 && mailfiles[i]->file_size > 0)
UPDATE_MAIL_FILE (i, finfo);
return (0);
}
+440
View File
@@ -0,0 +1,440 @@
/* mailcheck.c -- The check is in the mail... */
/* Copyright (C) 1987-2002 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 <stdio.h>
#include "bashtypes.h"
#include "posixstat.h"
#ifndef _MINIX
# include <sys/param.h>
#endif
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include "posixtime.h"
#include "bashansi.h"
#include "bashintl.h"
#include "shell.h"
#include "execute_cmd.h"
#include "mailcheck.h"
#include <tilde/tilde.h>
extern int mailstat __P((const char *, struct stat *));
typedef struct {
char *name;
char *msg;
time_t access_time;
time_t mod_time;
off_t file_size;
} FILEINFO;
/* The list of remembered mail files. */
static FILEINFO **mailfiles = (FILEINFO **)NULL;
/* Number of mail files that we have. */
static int mailfiles_count;
/* The last known time that mail was checked. */
static time_t last_time_mail_checked;
/* Non-zero means warn if a mail file has been read since last checked. */
int mail_warning;
static int find_mail_file __P((char *));
static void update_mail_file __P((int));
static int add_mail_file __P((char *, char *));
static int file_mod_date_changed __P((int));
static int file_access_date_changed __P((int));
static int file_has_grown __P((int));
static char *parse_mailpath_spec __P((char *));
/* Returns non-zero if it is time to check mail. */
int
time_to_check_mail ()
{
char *temp;
time_t now;
intmax_t seconds;
temp = get_string_value ("MAILCHECK");
/* Negative number, or non-numbers (such as empty string) cause no
checking to take place. */
if (temp == 0 || legal_number (temp, &seconds) == 0 || seconds < 0)
return (0);
now = NOW;
/* Time to check if MAILCHECK is explicitly set to zero, or if enough
time has passed since the last check. */
return (seconds == 0 || ((now - last_time_mail_checked) >= seconds));
}
/* Okay, we have checked the mail. Perhaps I should make this function
go away. */
void
reset_mail_timer ()
{
last_time_mail_checked = NOW;
}
/* Locate a file in the list. Return index of
entry, or -1 if not found. */
static int
find_mail_file (file)
char *file;
{
register int i;
for (i = 0; i < mailfiles_count; i++)
if (STREQ (mailfiles[i]->name, file))
return i;
return -1;
}
#define RESET_MAIL_FILE(i) \
do \
{ \
mailfiles[i]->access_time = mailfiles[i]->mod_time = 0; \
mailfiles[i]->file_size = 0; \
} \
while (0)
#define UPDATE_MAIL_FILE(i, finfo) \
do \
{ \
mailfiles[i]->access_time = finfo.st_atime; \
mailfiles[i]->mod_time = finfo.st_mtime; \
mailfiles[i]->file_size = finfo.st_size; \
} \
while (0)
static void
update_mail_file (i)
int i;
{
char *file;
struct stat finfo;
file = mailfiles[i]->name;
if (mailstat (file, &finfo) == 0)
UPDATE_MAIL_FILE (i, finfo);
else
RESET_MAIL_FILE (i);
}
/* Add this file to the list of remembered files and return its index
in the list of mail files. */
static int
add_mail_file (file, msg)
char *file, *msg;
{
struct stat finfo;
char *filename;
int i;
filename = full_pathname (file);
i = find_mail_file (filename);
if (i >= 0)
{
if (mailstat (filename, &finfo) == 0)
UPDATE_MAIL_FILE (i, finfo);
free (filename);
return i;
}
i = mailfiles_count++;
mailfiles = (FILEINFO **)xrealloc
(mailfiles, mailfiles_count * sizeof (FILEINFO *));
mailfiles[i] = (FILEINFO *)xmalloc (sizeof (FILEINFO));
mailfiles[i]->name = filename;
mailfiles[i]->msg = msg ? savestring (msg) : (char *)NULL;
update_mail_file (i);
return i;
}
/* Reset the existing mail files access and modification times to zero. */
void
reset_mail_files ()
{
register int i;
for (i = 0; i < mailfiles_count; i++)
{
RESET_MAIL_FILE (i);
}
}
/* Free the information that we have about the remembered mail files. */
void
free_mail_files ()
{
register int i;
for (i = 0; i < mailfiles_count; i++)
{
free (mailfiles[i]->name);
FREE (mailfiles[i]->msg);
free (mailfiles[i]);
}
if (mailfiles)
free (mailfiles);
mailfiles_count = 0;
mailfiles = (FILEINFO **)NULL;
}
/* Return non-zero if FILE's mod date has changed and it has not been
accessed since modified. If the size has dropped to zero, reset
the cached mail file info. */
static int
file_mod_date_changed (i)
int i;
{
time_t mtime;
struct stat finfo;
char *file;
file = mailfiles[i]->name;
mtime = mailfiles[i]->mod_time;
if ((mailstat (file, &finfo) == 0) && (finfo.st_size > 0))
return (mtime != finfo.st_mtime);
if (finfo.st_size == 0 && mailfiles[i]->file_size > 0)
UPDATE_MAIL_FILE (i, finfo);
return (0);
}
/* Return non-zero if FILE's access date has changed. */
static int
file_access_date_changed (i)
int i;
{
time_t atime;
struct stat finfo;
char *file;
file = mailfiles[i]->name;
atime = mailfiles[i]->access_time;
if ((mailstat (file, &finfo) == 0) && (finfo.st_size > 0))
return (atime != finfo.st_atime);
return (0);
}
/* Return non-zero if FILE's size has increased. */
static int
file_has_grown (i)
int i;
{
off_t size;
struct stat finfo;
char *file;
file = mailfiles[i]->name;
size = mailfiles[i]->file_size;
return ((mailstat (file, &finfo) == 0) && (finfo.st_size > size));
}
/* Take an element from $MAILPATH and return the portion from
the first unquoted `?' or `%' to the end of the string. This is the
message to be printed when the file contents change. */
static char *
parse_mailpath_spec (str)
char *str;
{
char *s;
int pass_next;
for (s = str, pass_next = 0; s && *s; s++)
{
if (pass_next)
{
pass_next = 0;
continue;
}
if (*s == '\\')
{
pass_next++;
continue;
}
if (*s == '?' || *s == '%')
return s;
}
return ((char *)NULL);
}
char *
make_default_mailpath ()
{
#if defined (DEFAULT_MAIL_DIRECTORY)
char *mp;
get_current_user_info ();
mp = (char *)xmalloc (2 + sizeof (DEFAULT_MAIL_DIRECTORY) + strlen (current_user.user_name));
strcpy (mp, DEFAULT_MAIL_DIRECTORY);
mp[sizeof(DEFAULT_MAIL_DIRECTORY) - 1] = '/';
strcpy (mp + sizeof (DEFAULT_MAIL_DIRECTORY), current_user.user_name);
return (mp);
#else
return ((char *)NULL);
#endif
}
/* Remember the dates of the files specified by MAILPATH, or if there is
no MAILPATH, by the file specified in MAIL. If neither exists, use a
default value, which we randomly concoct from using Unix. */
void
remember_mail_dates ()
{
char *mailpaths;
char *mailfile, *mp;
int i = 0;
mailpaths = get_string_value ("MAILPATH");
/* If no $MAILPATH, but $MAIL, use that as a single filename to check. */
if (mailpaths == 0 && (mailpaths = get_string_value ("MAIL")))
{
add_mail_file (mailpaths, (char *)NULL);
return;
}
if (mailpaths == 0)
{
mailpaths = make_default_mailpath ();
if (mailpaths)
{
add_mail_file (mailpaths, (char *)NULL);
free (mailpaths);
}
return;
}
while (mailfile = extract_colon_unit (mailpaths, &i))
{
mp = parse_mailpath_spec (mailfile);
if (mp && *mp)
*mp++ = '\0';
add_mail_file (mailfile, mp);
free (mailfile);
}
}
/* check_mail () is useful for more than just checking mail. Since it has
the paranoids dream ability of telling you when someone has read your
mail, it can just as easily be used to tell you when someones .profile
file has been read, thus letting one know when someone else has logged
in. Pretty good, huh? */
/* Check for mail in some files. If the modification date of any
of the files in MAILPATH has changed since we last did a
remember_mail_dates () then mention that the user has mail.
Special hack: If the variable MAIL_WARNING is non-zero and the
mail file has been accessed since the last time we remembered, then
the message "The mail in <mailfile> has been read" is printed. */
void
check_mail ()
{
char *current_mail_file, *message;
int i, use_user_notification;
char *dollar_underscore, *temp;
dollar_underscore = get_string_value ("_");
if (dollar_underscore)
dollar_underscore = savestring (dollar_underscore);
for (i = 0; i < mailfiles_count; i++)
{
current_mail_file = mailfiles[i]->name;
if (*current_mail_file == '\0')
continue;
if (file_mod_date_changed (i))
{
int file_is_bigger;
use_user_notification = mailfiles[i]->msg != (char *)NULL;
message = mailfiles[i]->msg ? mailfiles[i]->msg : _("You have mail in $_");
bind_variable ("_", current_mail_file);
#define atime mailfiles[i]->access_time
#define mtime mailfiles[i]->mod_time
/* Have to compute this before the call to update_mail_file, which
resets all the information. */
file_is_bigger = file_has_grown (i);
update_mail_file (i);
/* If the user has just run a program which manipulates the
mail file, then don't bother explaining that the mail
file has been manipulated. Since some systems don't change
the access time to be equal to the modification time when
the mail in the file is manipulated, check the size also. If
the file has not grown, continue. */
if ((atime >= mtime) && !file_is_bigger)
continue;
/* If the mod time is later than the access time and the file
has grown, note the fact that this is *new* mail. */
if (use_user_notification == 0 && (atime < mtime) && file_is_bigger)
message = _("You have new mail in $_");
#undef atime
#undef mtime
if (temp = expand_string_to_string (message, Q_DOUBLE_QUOTES))
{
puts (temp);
free (temp);
}
else
putchar ('\n');
}
if (mail_warning && file_access_date_changed (i))
{
update_mail_file (i);
printf (_("The mail in %s has been read\n"), current_mail_file);
}
}
if (dollar_underscore)
{
bind_variable ("_", dollar_underscore);
free (dollar_underscore);
}
else
unbind_variable ("_");
}
+2
View File
@@ -3814,6 +3814,8 @@ history_delimiting_chars ()
return " ";
return ";";
}
else if (two_tokens_ago == CASE && token_before_that == WORD && (parser_state & PST_CASESTMT))
return " ";
for (i = 0; no_semi_successors[i]; i++)
{
+1 -1
View File
@@ -3522,7 +3522,7 @@ read_token_word (character)
goto next_character;
}
/* Identify possible compound array variable assignment. */
else if MBTEST(character == '=' && token_index > 0 && token_is_assignment (token, token_index))
else if MBTEST(character == '=' && token_index > 0 && (assignment_acceptable (last_read_token) || (parser_state & PST_ASSIGNOK)) && token_is_assignment (token, token_index))
{
peek_char = shell_getc (1);
if MBTEST(peek_char == '(') /* ) */
+174 -12
View File
@@ -124,7 +124,13 @@ pid_t current_command_subst_pid = NO_PID;
SHELL_VAR *ifs_var;
char *ifs_value;
unsigned char ifs_cmap[UCHAR_MAX + 1];
#if defined (HANDLE_MULTIBYTE)
unsigned char ifs_firstc[MB_LEN_MAX];
size_t ifs_firstc_len;
#else
unsigned char ifs_firstc;
#endif
/* Extern functions and variables from different files. */
extern int last_command_exit_value, last_command_exit_signal;
@@ -785,7 +791,7 @@ skip_double_quoted (string, slen, sind)
{
si = i + 2;
if (string[i + 1] == LPAREN)
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC);
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC); /* ) */
else
ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
@@ -862,8 +868,14 @@ string_extract_verbatim (string, sindex, charlist)
char *charlist;
{
register int i = *sindex;
size_t slen;
#if defined (HANDLE_MULTIBYTE)
size_t clen;
wchar_t *wcharlist;
#endif
int c;
char *temp;
DECLARE_MBSTATE;
if (charlist[0] == '\'' && charlist[1] == '\0')
{
@@ -872,18 +884,62 @@ string_extract_verbatim (string, sindex, charlist)
return temp;
}
for (i = *sindex; c = string[i]; i++)
slen = strlen (string + *sindex) + *sindex;
i = *sindex;
#if defined (HANDLE_MULTIBYTE)
clen = strlen (charlist);
wcharlist = 0;
#endif
while (c = string[i])
{
#if defined (HANDLE_MULTIBYTE)
size_t mblength;
#endif
if (c == CTLESC)
{
i++;
i += 2;
continue;
}
#if defined (HANDLE_MULTIBYTE)
mblength = MBLEN (string + i, slen - 1);
if (mblength > 1)
{
wchar_t wc;
mblength = mbtowc (&wc, string + i, slen - i);
if (MB_INVALIDCH (mblength))
{
if (MEMBER (c, charlist))
break;
}
else
{
if (wcharlist == 0)
{
size_t len;
len = mbstowcs (wcharlist, charlist, 0);
if (len == -1)
len = 0;
wcharlist = xmalloc ((sizeof (wchar_t) * len) + 1);
mbstowcs (wcharlist, charlist, len);
}
if (wcschr (wcharlist, wc))
break;
}
}
else
#endif
if (MEMBER (c, charlist))
break;
ADVANCE_CHAR (string, slen, i);
}
#if defined (HANDLE_MULTIBYTE)
FREE (wcharlist);
#endif
temp = substring (string, *sindex, i);
*sindex = i;
@@ -892,13 +948,13 @@ string_extract_verbatim (string, sindex, charlist)
/* Extract the $( construct in STRING, and return a new string.
Start extracting at (SINDEX) as if we had just seen "$(".
Make (SINDEX) get the position of the matching ")". */
Make (SINDEX) get the position of the matching ")". ) */
char *
extract_command_subst (string, sindex)
char *string;
int *sindex;
{
return (extract_delimited_string (string, sindex, "$(", "(", ")", 0));
return (extract_delimited_string (string, sindex, "$(", "(", ")", 0)); /*)*/
}
/* Extract the $[ construct in STRING, and return a new string. (])
@@ -1456,11 +1512,36 @@ split_at_delims (string, slen, delims, sentinel, nwp, cwp)
d2 = 0;
if (delims)
{
d2 = (char *)xmalloc (strlen (delims) + 1);
for (i = ts = 0; delims[i]; i++)
size_t slength;
#if defined (HANDLE_MULTIBYTE)
size_t mblength = 1;
#endif
DECLARE_MBSTATE;
slength = strlen (delims);
d2 = (char *)xmalloc (slength + 1);
i = ts = 0;
while (delims[i])
{
if (whitespace(delims[i]) == 0)
#if defined (HANDLE_MULTIBYTE)
mbstate_t state_bak = state;
mblength = MBRLEN (delims + i, slength, &state);
if (MB_INVALIDCH (mblength))
state = state_bak;
else if (mblength != 1)
{
memcpy (d2 + ts, delims + i, mblength);
ts += mblength;
i += mblength;
slength -= mblength;
continue;
}
#endif
if (whitespace (delims[i]) == 0)
d2[ts++] = delims[i];
i++;
slength--;
}
d2[ts] = '\0';
}
@@ -1654,10 +1735,25 @@ char *
string_list_dollar_star (list)
WORD_LIST *list;
{
#if defined (HANDLE_MULTIBYTE)
char sep[MB_CUR_MAX + 1];
#else
char sep[2];
#endif
#if defined (HANDLE_MULTIBYTE)
if (ifs_firstc_len == 1)
{
sep[0] = ifs_firstc[0];
sep[1] = '\0';
}
else
memcpy (sep, ifs_firstc, ifs_firstc_len);
#else
sep[0] = ifs_firstc;
sep[1] = '\0';
#endif
return (string_list_internal (list, sep));
}
@@ -1676,14 +1772,42 @@ string_list_dollar_at (list, quoted)
WORD_LIST *list;
int quoted;
{
char *ifs, sep[2];
char *ifs;
#if defined (HANDLE_MULTIBYTE)
char sep[MB_CUR_MAX + 1];
#else
char sep[2];
#endif
WORD_LIST *tlist;
/* XXX this could just be ifs = ifs_value; */
ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
#if defined (HANDLE_MULTIBYTE)
if (ifs && *ifs)
{
size_t mblength;
mblength = MBLEN (ifs, strnlen (ifs, MB_CUR_MAX));
if (MB_INVALIDCH (mblength) || mblength == 1)
{
sep[0] = *ifs;
sep[1] = '\0';
}
else
{
memcpy (sep, ifs, mblength);
sep[mblength] = '\0';
}
}
else
{
sep[0] = ' ';
sep[1] = '\0';
}
#else
sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
sep[1] = '\0';
#endif
tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
? quote_list (list)
@@ -1732,6 +1856,7 @@ list_string (string, separators, quoted)
WORD_DESC *t;
char *current_word, *s;
int sindex, sh_style_split, whitesep;
size_t slen;
if (!string || !*string)
return ((WORD_LIST *)NULL);
@@ -1741,6 +1866,7 @@ list_string (string, separators, quoted)
separators[2] == '\n' &&
separators[3] == '\0';
slen = 0;
/* Remove sequences of whitespace at the beginning of STRING, as
long as those characters appear in IFS. Do not do this if
STRING is quoted or if there are no separator characters. */
@@ -1805,7 +1931,12 @@ list_string (string, separators, quoted)
/* Move past the current separator character. */
if (string[sindex])
sindex++;
{
DECLARE_MBSTATE;
if (slen == 0)
slen = strlen (string);
ADVANCE_CHAR (string, slen, sindex);
}
/* Now skip sequences of space, tab, or newline characters if they are
in the list of separators. */
@@ -1836,6 +1967,7 @@ get_word_from_string (stringp, separators, endptr)
register char *s;
char *current_word;
int sindex, sh_style_split, whitesep;
size_t slen;
if (!stringp || !*stringp || !**stringp)
return ((char *)NULL);
@@ -1847,6 +1979,8 @@ get_word_from_string (stringp, separators, endptr)
separators[2] == '\n' &&
separators[3] == '\0';
slen = 0;
/* Remove sequences of whitespace at the beginning of STRING, as
long as those characters appear in IFS. */
if (sh_style_split || !separators || !*separators)
@@ -1881,7 +2015,12 @@ get_word_from_string (stringp, separators, endptr)
/* Move past the current separator character. */
if (s[sindex])
sindex++;
{
DECLARE_MBSTATE;
if (slen == 0)
slen = strlen (s);
ADVANCE_CHAR (s, slen, sindex);
}
/* Now skip sequences of space, tab, or newline characters if they are
in the list of separators. */
@@ -6809,7 +6948,8 @@ setifs (v)
ifs_var = v;
ifs_value = v ? value_cell (v) : " \t\n";
/* Should really merge ifs_cmap with sh_syntaxtab. */
/* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
handle multibyte chars in IFS */
memset (ifs_cmap, '\0', sizeof (ifs_cmap));
for (t = ifs_value ; t && *t; t++)
{
@@ -6817,7 +6957,29 @@ setifs (v)
ifs_cmap[uc] = 1;
}
#if defined (HANDLE_MULTIBYTE)
if (ifs_value == 0)
{
ifs_firstc[0] = '\0';
ifs_firstc_len = 1;
}
else
{
size_t ifs_len;
ifs_len = strnlen (ifs_value, MB_CUR_MAX);
ifs_firstc_len = MBLEN (ifs_value, ifs_len);
if (ifs_firstc_len == 1 || MB_INVALIDCH (ifs_firstc_len))
{
ifs_firstc[0] = ifs_value[0];
ifs_firstc[1] = '\0';
ifs_firstc_len = 1;
}
else
memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
}
#else
ifs_firstc = ifs_value ? *ifs_value : 0;
#endif
}
char *
+7422
View File
File diff suppressed because it is too large Load Diff
+188 -15
View File
@@ -124,7 +124,13 @@ pid_t current_command_subst_pid = NO_PID;
SHELL_VAR *ifs_var;
char *ifs_value;
unsigned char ifs_cmap[UCHAR_MAX + 1];
#if defined (HANDLE_MULTIBYTE)
unsigned char ifs_firstc[MB_LEN_MAX];
size_t ifs_firstc_len;
#else
unsigned char ifs_firstc;
#endif
/* Extern functions and variables from different files. */
extern int last_command_exit_value, last_command_exit_signal;
@@ -785,7 +791,7 @@ skip_double_quoted (string, slen, sind)
{
si = i + 2;
if (string[i + 1] == LPAREN)
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC);
ret = extract_delimited_string (string, &si, "$(", "(", ")", EX_NOALLOC); /* ) */
else
ret = extract_dollar_brace_string (string, &si, 0, EX_NOALLOC);
@@ -862,8 +868,14 @@ string_extract_verbatim (string, sindex, charlist)
char *charlist;
{
register int i = *sindex;
size_t slen;
#if defined (HANDLE_MULTIBYTE)
size_t clen;
wchar_t *wcharlist;
#endif
int c;
char *temp;
DECLARE_MBSTATE;
if (charlist[0] == '\'' && charlist[1] == '\0')
{
@@ -872,18 +884,62 @@ string_extract_verbatim (string, sindex, charlist)
return temp;
}
for (i = *sindex; c = string[i]; i++)
slen = strlen (string + *sindex) + *sindex;
i = *sindex;
#if defined (HANDLE_MULTIBYTE)
clen = strlen (charlist);
wcharlist = 0;
#endif
while (c = string[i])
{
#if defined (HANDLE_MULTIBYTE)
size_t mblength;
#endif
if (c == CTLESC)
{
i++;
i += 2;
continue;
}
#if defined (HANDLE_MULTIBYTE)
mblength = MBLEN (string + i, slen - 1);
if (mblength > 1)
{
wchar_t wc;
mblength = mbtowc (&wc, string + i, slen - i);
if (MB_INVALIDCH (mblength))
{
if (MEMBER (c, charlist))
break;
}
else
{
if (wcharlist == 0)
{
size_t len;
len = mbstowcs (wcharlist, charlist, 0);
if (len == -1)
len = 0;
wcharlist = xmalloc ((sizeof (wchar_t) * len) + 1);
mbstowcs (wcharlist, charlist, len);
}
if (wcschr (wcharlist, wc))
break;
}
}
else
#endif
if (MEMBER (c, charlist))
break;
ADVANCE_CHAR (string, slen, i);
}
#if defined (HANDLE_MULTIBYTE)
FREE (wcharlist);
#endif
temp = substring (string, *sindex, i);
*sindex = i;
@@ -892,13 +948,13 @@ string_extract_verbatim (string, sindex, charlist)
/* Extract the $( construct in STRING, and return a new string.
Start extracting at (SINDEX) as if we had just seen "$(".
Make (SINDEX) get the position of the matching ")". */
Make (SINDEX) get the position of the matching ")". ) */
char *
extract_command_subst (string, sindex)
char *string;
int *sindex;
{
return (extract_delimited_string (string, sindex, "$(", "(", ")", 0));
return (extract_delimited_string (string, sindex, "$(", "(", ")", 0)); /*)*/
}
/* Extract the $[ construct in STRING, and return a new string. (])
@@ -1456,11 +1512,36 @@ split_at_delims (string, slen, delims, sentinel, nwp, cwp)
d2 = 0;
if (delims)
{
d2 = (char *)xmalloc (strlen (delims) + 1);
for (i = ts = 0; delims[i]; i++)
size_t slength;
#if defined (HANDLE_MULTIBYTE)
size_t mblength = 1;
#endif
DECLARE_MBSTATE;
slength = strlen (delims);
d2 = (char *)xmalloc (slength + 1);
i = ts = 0;
while (delims[i])
{
if (whitespace(delims[i]) == 0)
#if defined (HANDLE_MULTIBYTE)
mbstate_t state_bak = state;
mblength = MBRLEN (delims + i, slength, &state);
if (MB_INVALIDCH (mblength))
state = state_bak;
else if (mblength != 1)
{
memcpy (d2 + ts, delims + i, mblength);
ts += mblength;
i += mblength;
slength -= mblength;
continue;
}
#endif
if (whitespace (delims[i]) == 0)
d2[ts++] = delims[i];
i++;
slength--;
}
d2[ts] = '\0';
}
@@ -1654,10 +1735,25 @@ char *
string_list_dollar_star (list)
WORD_LIST *list;
{
#if defined (HANDLE_MULTIBYTE)
char sep[MB_CUR_MAX + 1];
#else
char sep[2];
#endif
#if defined (HANDLE_MULTIBYTE)
if (ifs_firstc_len == 1)
{
sep[0] = ifs_firstc[0];
sep[1] = '\0';
}
else
memcpy (sep, ifs_firstc, ifs_firstc_len);
#else
sep[0] = ifs_firstc;
sep[1] = '\0';
#endif
return (string_list_internal (list, sep));
}
@@ -1676,14 +1772,42 @@ string_list_dollar_at (list, quoted)
WORD_LIST *list;
int quoted;
{
char *ifs, sep[2];
char *ifs;
#if defined (HANDLE_MULTIBYTE)
char sep[MB_CUR_MAX + 1];
#else
char sep[2];
#endif
WORD_LIST *tlist;
/* XXX this could just be ifs = ifs_value; */
ifs = ifs_var ? value_cell (ifs_var) : (char *)0;
#if defined (HANDLE_MULTIBYTE)
if (ifs && *ifs)
{
size_t mblength;
mblength = MBLEN (ifs, strnlen (ifs, MB_CUR_MAX));
if (MB_INVALIDCH (mblength) || mblength == 1)
{
sep[0] = *ifs;
sep[1] = '\0';
}
else
{
memcpy (sep, ifs, mblength);
sep[mblength] = '\0';
}
}
else
{
sep[0] = ' ';
sep[1] = '\0';
}
#else
sep[0] = (ifs == 0 || *ifs == 0) ? ' ' : *ifs;
sep[1] = '\0';
#endif
tlist = ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) || (ifs && *ifs == 0))
? quote_list (list)
@@ -1732,6 +1856,7 @@ list_string (string, separators, quoted)
WORD_DESC *t;
char *current_word, *s;
int sindex, sh_style_split, whitesep;
size_t slen;
if (!string || !*string)
return ((WORD_LIST *)NULL);
@@ -1741,6 +1866,7 @@ list_string (string, separators, quoted)
separators[2] == '\n' &&
separators[3] == '\0';
slen = 0;
/* Remove sequences of whitespace at the beginning of STRING, as
long as those characters appear in IFS. Do not do this if
STRING is quoted or if there are no separator characters. */
@@ -1805,7 +1931,12 @@ list_string (string, separators, quoted)
/* Move past the current separator character. */
if (string[sindex])
sindex++;
{
DECLARE_MBSTATE;
if (slen == 0)
slen = strlen (string);
ADVANCE_CHAR (string, slen, sindex);
}
/* Now skip sequences of space, tab, or newline characters if they are
in the list of separators. */
@@ -1836,6 +1967,7 @@ get_word_from_string (stringp, separators, endptr)
register char *s;
char *current_word;
int sindex, sh_style_split, whitesep;
size_t slen;
if (!stringp || !*stringp || !**stringp)
return ((char *)NULL);
@@ -1847,6 +1979,8 @@ get_word_from_string (stringp, separators, endptr)
separators[2] == '\n' &&
separators[3] == '\0';
slen = 0;
/* Remove sequences of whitespace at the beginning of STRING, as
long as those characters appear in IFS. */
if (sh_style_split || !separators || !*separators)
@@ -1881,7 +2015,12 @@ get_word_from_string (stringp, separators, endptr)
/* Move past the current separator character. */
if (s[sindex])
sindex++;
{
DECLARE_MBSTATE;
if (slen == 0)
slen = strlen (s);
ADVANCE_CHAR (s, slen, sindex);
}
/* Now skip sequences of space, tab, or newline characters if they are
in the list of separators. */
@@ -4899,8 +5038,9 @@ verify_substring_values (value, substr, vtype, e1p, e2p)
#if defined (ARRAY_VARS)
case VT_ARRAYVAR:
a = (ARRAY *)value;
/* For arrays, the first value deals with array indices. */
len = array_max_index (a); /* arrays index from 0 to n - 1 */
/* For arrays, the first value deals with array indices. Negative
offsets count from one past the array's maximum index. */
len = array_max_index (a) + (*e1p < 0); /* arrays index from 0 to n - 1 */
break;
#endif
}
@@ -6808,7 +6948,8 @@ setifs (v)
ifs_var = v;
ifs_value = v ? value_cell (v) : " \t\n";
/* Should really merge ifs_cmap with sh_syntaxtab. */
/* Should really merge ifs_cmap with sh_syntaxtab. XXX - doesn't yet
handle multibyte chars in IFS */
memset (ifs_cmap, '\0', sizeof (ifs_cmap));
for (t = ifs_value ; t && *t; t++)
{
@@ -6816,7 +6957,28 @@ setifs (v)
ifs_cmap[uc] = 1;
}
#if defined (HANDLE_MULTIBYTE)
if (ifs_value == 0)
{
ifs_firstc[0] = '\0';
ifs_firstc_len = 1;
}
else
{
size_t ifs_len;
ifs_len = strnlen (ifs_value, MB_CUR_MAX);
ifs_firstc_len = MBLEN (ifs_value, ifs_len);
if (ifs_firstc_len == 1 || MB_INVALIDCH (ifs_firstc_len))
{
ifs_firstc[0] = ifs_value[0];
ifs_firstc[1] = '\0';
}
else
memcpy (ifs_firstc, ifs_value, ifs_firstc_len);
}
#else
ifs_firstc = ifs_value ? *ifs_value : 0;
#endif
}
char *
@@ -6854,12 +7016,23 @@ static WORD_LIST *
word_list_split (list)
WORD_LIST *list;
{
WORD_LIST *result, *t, *tresult;
WORD_LIST *result, *t, *tresult, *e;
for (t = list, result = (WORD_LIST *)NULL; t; t = t->next)
{
tresult = word_split (t->word, ifs_value);
#if 0
result = (WORD_LIST *) list_append (result, tresult);
#else
if (result == 0)
result = e = tresult;
else
{
e->next = tresult;
while (e->next)
e = e->next;
}
#endif
}
return (result);
}
+6
View File
@@ -231,7 +231,13 @@ extern WORD_LIST *split_at_delims __P((char *, int, char *, int, int *, int *));
extern SHELL_VAR *ifs_var;
extern char *ifs_value;
extern unsigned char ifs_cmap[];
#if defined (HANDLE_MULTIBYTE)
extern unsigned char ifs_firstc[];
extern size_t ifs_firstc_len;
#else
extern unsigned char ifs_firstc;
#endif
/* Evaluates to 1 if C is a character in $IFS. */
#define isifs(c) (ifs_cmap[(unsigned char)(c)] != 0)
+245
View File
@@ -0,0 +1,245 @@
/* subst.h -- Names of externally visible functions in subst.c. */
/* Copyright (C) 1993-2002 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. */
#if !defined (_SUBST_H_)
#define _SUBST_H_
#include "stdc.h"
/* Constants which specify how to handle backslashes and quoting in
expand_word_internal (). Q_DOUBLE_QUOTES means to use the function
slashify_in_quotes () to decide whether the backslash should be
retained. Q_HERE_DOCUMENT means slashify_in_here_document () to
decide whether to retain the backslash. Q_KEEP_BACKSLASH means
to unconditionally retain the backslash. Q_PATQUOTE means that we're
expanding a pattern ${var%#[#%]pattern} in an expansion surrounded
by double quotes. */
#define Q_DOUBLE_QUOTES 0x1
#define Q_HERE_DOCUMENT 0x2
#define Q_KEEP_BACKSLASH 0x4
#define Q_PATQUOTE 0x8
#define Q_QUOTED 0x10
#define Q_ADDEDQUOTES 0x20
#define Q_QUOTEDNULL 0x40
/* Remove backslashes which are quoting backquotes from STRING. Modifies
STRING, and returns a pointer to it. */
extern char * de_backslash __P((char *));
/* Replace instances of \! in a string with !. */
extern void unquote_bang __P((char *));
/* Extract the $( construct in STRING, and return a new string.
Start extracting at (SINDEX) as if we had just seen "$(".
Make (SINDEX) get the position just after the matching ")". */
extern char *extract_command_subst __P((char *, int *));
/* Extract the $[ construct in STRING, and return a new string.
Start extracting at (SINDEX) as if we had just seen "$[".
Make (SINDEX) get the position just after the matching "]". */
extern char *extract_arithmetic_subst __P((char *, int *));
#if defined (PROCESS_SUBSTITUTION)
/* Extract the <( or >( construct in STRING, and return a new string.
Start extracting at (SINDEX) as if we had just seen "<(".
Make (SINDEX) get the position just after the matching ")". */
extern char *extract_process_subst __P((char *, char *, int *));
#endif /* PROCESS_SUBSTITUTION */
/* Extract the name of the variable to bind to from the assignment string. */
extern char *assignment_name __P((char *));
/* Return a single string of all the words present in LIST, separating
each word with SEP. */
extern char *string_list_internal __P((WORD_LIST *, char *));
/* Return a single string of all the words present in LIST, separating
each word with a space. */
extern char *string_list __P((WORD_LIST *));
/* Turn $* into a single string, obeying POSIX rules. */
extern char *string_list_dollar_star __P((WORD_LIST *));
/* Expand $@ into a single string, obeying POSIX rules. */
extern char *string_list_dollar_at __P((WORD_LIST *, int));
/* Perform quoted null character removal on each element of LIST.
This modifies LIST. */
extern void word_list_remove_quoted_nulls __P((WORD_LIST *));
/* This performs word splitting and quoted null character removal on
STRING. */
extern WORD_LIST *list_string __P((char *, char *, int));
extern char *get_word_from_string __P((char **, char *, char **));
extern char *strip_trailing_ifs_whitespace __P((char *, char *, int));
/* Given STRING, an assignment string, get the value of the right side
of the `=', and bind it to the left side. If EXPAND is true, then
perform parameter expansion, command substitution, and arithmetic
expansion on the right-hand side. Perform tilde expansion in any
case. Do not perform word splitting on the result of expansion. */
extern int do_assignment __P((const char *));
extern int do_assignment_no_expand __P((const char *));
/* Append SOURCE to TARGET at INDEX. SIZE is the current amount
of space allocated to TARGET. SOURCE can be NULL, in which
case nothing happens. Gets rid of SOURCE by free ()ing it.
Returns TARGET in case the location has changed. */
extern char *sub_append_string __P((char *, char *, int *, int *));
/* Append the textual representation of NUMBER to TARGET.
INDEX and SIZE are as in SUB_APPEND_STRING. */
extern char *sub_append_number __P((intmax_t, char *, int *, int *));
/* Return the word list that corresponds to `$*'. */
extern WORD_LIST *list_rest_of_args __P((void));
/* Make a single large string out of the dollar digit variables,
and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
case of "$*" with respect to IFS. */
extern char *string_rest_of_args __P((int));
extern int number_of_args __P((void));
/* Expand STRING by performing parameter expansion, command substitution,
and arithmetic expansion. Dequote the resulting WORD_LIST before
returning it, but do not perform word splitting. The call to
remove_quoted_nulls () is made here because word splitting normally
takes care of quote removal. */
extern WORD_LIST *expand_string_unsplit __P((char *, int));
/* Expand a prompt string. */
extern WORD_LIST *expand_prompt_string __P((char *, int));
/* Expand STRING just as if you were expanding a word. This also returns
a list of words. Note that filename globbing is *NOT* done for word
or string expansion, just when the shell is expanding a command. This
does parameter expansion, command substitution, arithmetic expansion,
and word splitting. Dequote the resultant WORD_LIST before returning. */
extern WORD_LIST *expand_string __P((char *, int));
/* Convenience functions that expand strings to strings, taking care of
converting the WORD_LIST * returned by the expand_string* functions
to a string and deallocating the WORD_LIST *. */
extern char *expand_string_to_string __P((char *, int));
extern char *expand_string_unsplit_to_string __P((char *, int));
/* De-quoted quoted characters in STRING. */
extern char *dequote_string __P((char *));
/* Expand WORD, performing word splitting on the result. This does
parameter expansion, command substitution, arithmetic expansion,
word splitting, and quote removal. */
extern WORD_LIST *expand_word __P((WORD_DESC *, int));
/* Expand WORD, but do not perform word splitting on the result. This
does parameter expansion, command substitution, arithmetic expansion,
and quote removal. */
extern WORD_LIST *expand_word_unsplit __P((WORD_DESC *, int));
extern WORD_LIST *expand_word_leave_quoted __P((WORD_DESC *, int));
/* Return the value of a positional parameter. This handles values > 10. */
extern char *get_dollar_var_value __P((intmax_t));
/* Quote a string to protect it from word splitting. */
extern char *quote_string __P((char *));
/* Quote escape characters (characters special to interals of expansion)
in a string. */
extern char *quote_escapes __P((char *));
/* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
backslash quoting rules for within double quotes. */
extern char *string_quote_removal __P((char *, int));
/* Perform quote removal on word WORD. This allocates and returns a new
WORD_DESC *. */
extern WORD_DESC *word_quote_removal __P((WORD_DESC *, int));
/* Perform quote removal on all words in LIST. If QUOTED is non-zero,
the members of the list are treated as if they are surrounded by
double quotes. Return a new list, or NULL if LIST is NULL. */
extern WORD_LIST *word_list_quote_removal __P((WORD_LIST *, int));
/* Called when IFS is changed to maintain some private variables. */
extern void setifs __P((SHELL_VAR *));
/* Return the value of $IFS, or " \t\n" if IFS is unset. */
extern char *getifs __P((void));
/* This splits a single word into a WORD LIST on $IFS, but only if the word
is not quoted. list_string () performs quote removal for us, even if we
don't do any splitting. */
extern WORD_LIST *word_split __P((WORD_DESC *, char *));
/* Take the list of words in LIST and do the various substitutions. Return
a new list of words which is the expanded list, and without things like
variable assignments. */
extern WORD_LIST *expand_words __P((WORD_LIST *));
/* Same as expand_words (), but doesn't hack variable or environment
variables. */
extern WORD_LIST *expand_words_no_vars __P((WORD_LIST *));
/* Perform the `normal shell expansions' on a WORD_LIST. These are
brace expansion, tilde expansion, parameter and variable substitution,
command substitution, arithmetic expansion, and word splitting. */
extern WORD_LIST *expand_words_shellexp __P((WORD_LIST *));
extern char *command_substitute __P((char *, int));
extern char *pat_subst __P((char *, char *, char *, int));
extern void unlink_fifo_list __P((void));
extern WORD_LIST *list_string_with_quotes __P((char *));
#if defined (ARRAY_VARS)
extern char *extract_array_assignment_list __P((char *, int *));
#endif
#if defined (COND_COMMAND)
extern char *remove_backslashes __P((char *));
extern char *cond_expand_word __P((WORD_DESC *, int));
#endif
#if defined (READLINE)
extern int char_is_quoted __P((char *, int));
extern int unclosed_pair __P((char *, int, char *));
extern int skip_to_delim __P((char *, int, char *));
extern WORD_LIST *split_at_delims __P((char *, int, char *, int, int *, int *));
#endif
/* Variables used to keep track of the characters in IFS. */
extern SHELL_VAR *ifs_var;
extern char *ifs_value;
extern unsigned char ifs_cmap[];
extern unsigned char ifs_firstc;
/* Evaluates to 1 if C is a character in $IFS. */
#define isifs(c) (ifs_cmap[(unsigned char)(c)] != 0)
/* How to determine the quoted state of the character C. */
#define QUOTED_CHAR(c) ((c) == CTLESC)
/* Is the first character of STRING a quoted NULL character? */
#define QUOTED_NULL(string) ((string)[0] == CTLNUL && (string)[1] == '\0')
#endif /* !_SUBST_H_ */
+245
View File
@@ -0,0 +1,245 @@
/* subst.h -- Names of externally visible functions in subst.c. */
/* Copyright (C) 1993-2002 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. */
#if !defined (_SUBST_H_)
#define _SUBST_H_
#include "stdc.h"
/* Constants which specify how to handle backslashes and quoting in
expand_word_internal (). Q_DOUBLE_QUOTES means to use the function
slashify_in_quotes () to decide whether the backslash should be
retained. Q_HERE_DOCUMENT means slashify_in_here_document () to
decide whether to retain the backslash. Q_KEEP_BACKSLASH means
to unconditionally retain the backslash. Q_PATQUOTE means that we're
expanding a pattern ${var%#[#%]pattern} in an expansion surrounded
by double quotes. */
#define Q_DOUBLE_QUOTES 0x1
#define Q_HERE_DOCUMENT 0x2
#define Q_KEEP_BACKSLASH 0x4
#define Q_PATQUOTE 0x8
#define Q_QUOTED 0x10
#define Q_ADDEDQUOTES 0x20
#define Q_QUOTEDNULL 0x40
/* Remove backslashes which are quoting backquotes from STRING. Modifies
STRING, and returns a pointer to it. */
extern char * de_backslash __P((char *));
/* Replace instances of \! in a string with !. */
extern void unquote_bang __P((char *));
/* Extract the $( construct in STRING, and return a new string.
Start extracting at (SINDEX) as if we had just seen "$(".
Make (SINDEX) get the position just after the matching ")". */
extern char *extract_command_subst __P((char *, int *));
/* Extract the $[ construct in STRING, and return a new string.
Start extracting at (SINDEX) as if we had just seen "$[".
Make (SINDEX) get the position just after the matching "]". */
extern char *extract_arithmetic_subst __P((char *, int *));
#if defined (PROCESS_SUBSTITUTION)
/* Extract the <( or >( construct in STRING, and return a new string.
Start extracting at (SINDEX) as if we had just seen "<(".
Make (SINDEX) get the position just after the matching ")". */
extern char *extract_process_subst __P((char *, char *, int *));
#endif /* PROCESS_SUBSTITUTION */
/* Extract the name of the variable to bind to from the assignment string. */
extern char *assignment_name __P((char *));
/* Return a single string of all the words present in LIST, separating
each word with SEP. */
extern char *string_list_internal __P((WORD_LIST *, char *));
/* Return a single string of all the words present in LIST, separating
each word with a space. */
extern char *string_list __P((WORD_LIST *));
/* Turn $* into a single string, obeying POSIX rules. */
extern char *string_list_dollar_star __P((WORD_LIST *));
/* Expand $@ into a single string, obeying POSIX rules. */
extern char *string_list_dollar_at __P((WORD_LIST *, int));
/* Perform quoted null character removal on each element of LIST.
This modifies LIST. */
extern void word_list_remove_quoted_nulls __P((WORD_LIST *));
/* This performs word splitting and quoted null character removal on
STRING. */
extern WORD_LIST *list_string __P((char *, char *, int));
extern char *get_word_from_string __P((char **, char *, char **));
extern char *strip_trailing_ifs_whitespace __P((char *, char *, int));
/* Given STRING, an assignment string, get the value of the right side
of the `=', and bind it to the left side. If EXPAND is true, then
perform parameter expansion, command substitution, and arithmetic
expansion on the right-hand side. Perform tilde expansion in any
case. Do not perform word splitting on the result of expansion. */
extern int do_assignment __P((const char *));
extern int do_assignment_no_expand __P((const char *));
/* Append SOURCE to TARGET at INDEX. SIZE is the current amount
of space allocated to TARGET. SOURCE can be NULL, in which
case nothing happens. Gets rid of SOURCE by free ()ing it.
Returns TARGET in case the location has changed. */
extern char *sub_append_string __P((char *, char *, int *, int *));
/* Append the textual representation of NUMBER to TARGET.
INDEX and SIZE are as in SUB_APPEND_STRING. */
extern char *sub_append_number __P((intmax_t, char *, int *, int *));
/* Return the word list that corresponds to `$*'. */
extern WORD_LIST *list_rest_of_args __P((void));
/* Make a single large string out of the dollar digit variables,
and the rest_of_args. If DOLLAR_STAR is 1, then obey the special
case of "$*" with respect to IFS. */
extern char *string_rest_of_args __P((int));
extern int number_of_args __P((void));
/* Expand STRING by performing parameter expansion, command substitution,
and arithmetic expansion. Dequote the resulting WORD_LIST before
returning it, but do not perform word splitting. The call to
remove_quoted_nulls () is made here because word splitting normally
takes care of quote removal. */
extern WORD_LIST *expand_string_unsplit __P((char *, int));
/* Expand a prompt string. */
extern WORD_LIST *expand_prompt_string __P((char *, int));
/* Expand STRING just as if you were expanding a word. This also returns
a list of words. Note that filename globbing is *NOT* done for word
or string expansion, just when the shell is expanding a command. This
does parameter expansion, command substitution, arithmetic expansion,
and word splitting. Dequote the resultant WORD_LIST before returning. */
extern WORD_LIST *expand_string __P((char *, int));
/* Convenience functions that expand strings to strings, taking care of
converting the WORD_LIST * returned by the expand_string* functions
to a string and deallocating the WORD_LIST *. */
extern char *expand_string_to_string __P((char *, int));
extern char *expand_string_unsplit_to_string __P((char *, int));
/* De-quoted quoted characters in STRING. */
extern char *dequote_string __P((char *));
/* Expand WORD, performing word splitting on the result. This does
parameter expansion, command substitution, arithmetic expansion,
word splitting, and quote removal. */
extern WORD_LIST *expand_word __P((WORD_DESC *, int));
/* Expand WORD, but do not perform word splitting on the result. This
does parameter expansion, command substitution, arithmetic expansion,
and quote removal. */
extern WORD_LIST *expand_word_unsplit __P((WORD_DESC *, int));
extern WORD_LIST *expand_word_leave_quoted __P((WORD_DESC *, int));
/* Return the value of a positional parameter. This handles values > 10. */
extern char *get_dollar_var_value __P((intmax_t));
/* Quote a string to protect it from word splitting. */
extern char *quote_string __P((char *));
/* Quote escape characters (characters special to interals of expansion)
in a string. */
extern char *quote_escapes __P((char *));
/* Perform quote removal on STRING. If QUOTED > 0, assume we are obeying the
backslash quoting rules for within double quotes. */
extern char *string_quote_removal __P((char *, int));
/* Perform quote removal on word WORD. This allocates and returns a new
WORD_DESC *. */
extern WORD_DESC *word_quote_removal __P((WORD_DESC *, int));
/* Perform quote removal on all words in LIST. If QUOTED is non-zero,
the members of the list are treated as if they are surrounded by
double quotes. Return a new list, or NULL if LIST is NULL. */
extern WORD_LIST *word_list_quote_removal __P((WORD_LIST *, int));
/* Called when IFS is changed to maintain some private variables. */
extern void setifs __P((SHELL_VAR *));
/* Return the value of $IFS, or " \t\n" if IFS is unset. */
extern char *getifs __P((void));
/* This splits a single word into a WORD LIST on $IFS, but only if the word
is not quoted. list_string () performs quote removal for us, even if we
don't do any splitting. */
extern WORD_LIST *word_split __P((WORD_DESC *, char *));
/* Take the list of words in LIST and do the various substitutions. Return
a new list of words which is the expanded list, and without things like
variable assignments. */
extern WORD_LIST *expand_words __P((WORD_LIST *));
/* Same as expand_words (), but doesn't hack variable or environment
variables. */
extern WORD_LIST *expand_words_no_vars __P((WORD_LIST *));
/* Perform the `normal shell expansions' on a WORD_LIST. These are
brace expansion, tilde expansion, parameter and variable substitution,
command substitution, arithmetic expansion, and word splitting. */
extern WORD_LIST *expand_words_shellexp __P((WORD_LIST *));
extern char *command_substitute __P((char *, int));
extern char *pat_subst __P((char *, char *, char *, int));
extern void unlink_fifo_list __P((void));
extern WORD_LIST *list_string_with_quotes __P((char *));
#if defined (ARRAY_VARS)
extern char *extract_array_assignment_list __P((char *, int *));
#endif
#if defined (COND_COMMAND)
extern char *remove_backslashes __P((char *));
extern char *cond_expand_word __P((WORD_DESC *, int));
#endif
#if defined (READLINE)
extern int char_is_quoted __P((char *, int));
extern int unclosed_pair __P((char *, int, char *));
extern int skip_to_delim __P((char *, int, char *));
extern WORD_LIST *split_at_delims __P((char *, int, char *, int, int *, int *));
#endif
/* Variables used to keep track of the characters in IFS. */
extern SHELL_VAR *ifs_var;
extern char *ifs_value;
extern unsigned char ifs_cmap[];
extern unsigned char ifs_firstc;
/* Evaluates to 1 if C is a character in $IFS. */
#define isifs(c) (ifs_cmap[(unsigned char)(c)] != 0)
/* How to determine the quoted state of the character C. */
#define QUOTED_CHAR(c) ((c) == CTLESC)
/* Is the first character of STRING a quoted NULL character? */
#define QUOTED_NULL(string) ((string)[0] == CTLNUL && (string)[1] == '\0')
#endif /* !_SUBST_H_ */
+1 -1
View File
@@ -1162,7 +1162,7 @@ EOF
*:QNX:*:4*)
echo i386-pc-qnx
exit 0 ;;
NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
NSR-[DGKLNPTVWXY]:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit 0 ;;
*:NonStop-UX:*:*)
+1403
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1,4 +1,4 @@
BUILD_DIR=/usr/local/build/chet/bash/bash-current
BUILD_DIR=/usr/local/build/bash/bash-current
THIS_SH=$BUILD_DIR/bash
PATH=$PATH:$BUILD_DIR
+5
View File
@@ -17,6 +17,11 @@ abcd{efgh
foo 1 2 bar
foo 1 2 bar
foo 1 2 bar
foobar foobaz.
foobar foobaz
bazx bazy
vx vy
bazx bazy
1 2 3 4 5 6 7 8 9 10
0..10 braces
0 1 2 3 4 5 6 7 8 9 10 braces
+13
View File
@@ -23,6 +23,19 @@ echo foo {1,2} bar
echo `zecho foo {1,2} bar`
echo $(zecho foo {1,2} bar)
var=baz
varx=vx
vary=vy
echo foo{bar,${var}.}
echo foo{bar,${var}}
echo "${var}"{x,y}
echo $var{x,y}
echo ${var}{x,y}
unset var varx vary
# new sequence brace operators
echo {1..10}
+65
View File
@@ -0,0 +1,65 @@
echo ff{c,b,a}
echo f{d,e,f}g
echo {l,n,m}xyz
echo {abc\,def}
echo {abc}
echo \{a,b,c,d,e}
echo {x,y,\{a,b,c}}
echo {x\,y,\{abc\},trie}
echo /usr/{ucb/{ex,edit},lib/{ex,how_ex}}
echo XXXX\{`echo a b c | tr ' ' ','`\}
eval echo XXXX\{`echo a b c | tr ' ' ','`\}
echo {}
echo { }
echo }
echo {
echo abcd{efgh
echo foo {1,2} bar
echo `zecho foo {1,2} bar`
echo $(zecho foo {1,2} bar)
var=baz
echo foo{bar,${var}.}
echo foo{bar,${var}}
echo "${var}"{x,y}
echo $var{x,y}
echo ${var}{x,y}
# new sequence brace operators
echo {1..10}
# this doesn't work yet
echo {0..10,braces}
# but this does
echo {{0..10},braces}
echo x{{0..10},braces}y
echo {3..3}
echo x{3..3}y
echo {10..1}
echo {10..1}y
echo x{10..1}y
echo {a..f}
echo {f..a}
echo {a..A}
echo {A..a}
echo {f..f}
# mixes are incorrectly-formed brace expansions
echo {1..f}
echo {f..1}
echo 0{1..9} {10..20}
# do negative numbers work?
echo {-1..-10}
echo {-20..0}