commit bash-20100225 snapshot

This commit is contained in:
Chet Ramey
2011-12-12 21:55:02 -05:00
parent 4691dc6b2d
commit 644196275f
44 changed files with 8373 additions and 98 deletions
+84
View File
@@ -9495,3 +9495,87 @@ builtins/hash.def
- change add_hashed_command to remove the command being looked up from
the hash table before trying to add it. That way, if it's not found,
there won't be anything remaining in the hash table
2/26
----
trap.[ch]
- move IMPOSSIBLE_TRAP_HANDLER define to trap.h so other parts of the
shell can use it
parse.y
- change yy_readline_get to use IMPOSSIBLE_TRAP_HANDER instead of NULL
as a sentinel value for the SIGINT signal handler
- make sure yy_readline_get resets interrupt_immediately to 0 after
calling readline() using the same criteria it used to set it to 1
before the call -- make the code symmetric. Suggested by Werner
Fink <werner@suse.de>
builtins/read.def
- move assignment to `retval' before decrement of interrupt_immediately
and terminate_immediately and call to discard_unwind_frame
- move assign_vars label before decrement of interrupt_immediately and
terminate_immediately so those variables get reset appropriately
if read -t times out
subst.h
- new define for Q_DOLBRACE, indicates double-quoted ${...}
subst.c
- in parameter_brace_expand, before calling parameter_brace_expand_rhs,
add Q_DOLBRACE to `quoted' if we're within double quotes.
- in expand_word_internal, if the Q_DOLBRACE flag is set, remove a
backslash escaping a { or }. Result of a Posix discussion on the
austin-group list
2/27
----
variables.c
- new functions to save and restore the PIPESTATUS variable's internal
array: save_pipestatus_array and restore_pipestatus_array
variables.h
- new extern declarations for save_pipestatus_array and
restore_pipestatus_array
trap.c
- in run_pending_traps, _run_trap_internal, and run_exit_trap, save
and restore $PIPESTATUS while traps are running. Fixes bug
reported by Florian Bruhin <me@the-compiler.org>
parse.y
- use save_pipestatus_array and restore_pipestatus_array in
save_parser_state and restore_parser_state, respectively, replacing
inline code
lib/readline/histfile.c
- fix callers of history_filename to be prepared to cope with it
returning NULL
- change history_filename to return NULL if $HOME is not set, rather
than trying to write the history file in the current directory.
This is the default directory, used only if the application does
not specify a history filename. Changed due to long-ago (unsent)
bug report from OpenBSD
{Makefile,config.h,configure}.in,externs.h,lib/sh/{dprintf.c,Makefile.in}
- change fdprintf to dprintf, which is the Posix standard interface,
look for it with configure, replace it if not available
2/28
----
command.h
- add new subshell flag, SUBSHELL_RESETTRAP. Indicates to the trap
builtin that the shell is executing a command substitution and
should free the trap strings we left unfreed by reset_signal_handlers()
trap.c
- free_trap_string() and free_trap_strings() are now compiled in
builtins/trap.def
- if changing a signal disposition and the SUBSHELL_RESETTRAP flag is
set in subshell_environment, free the trap strings left unfreed by
reset_signal_handlers
subst.c
- in command_substitute, set the SUBSHELL_RESETTRAP flag. This change
is for Austin Group Posix interpretation 53
(http://austingroupbugs.net/view.php?id=53)
+104 -1
View File
@@ -9475,4 +9475,107 @@ builtins/exec.def
shell.c
- if exec_argv0 is set, set dollar_vars[0] to it and set it to NULL,
assuming it was set by `exec -a'. `exec -a foo' now sets $0 to
foo in an executable shell script without a leading `#!'
foo in an executable shell script without a leading `#!' (fixes
longstanding bug)
2/8
---
variables.c
- in push_func_var, if a variable is in a special builtin's temporary
environment and needs to be propagated because we're in Posix mode,
or we just need to propagate a variable, and we are executing in a
function without any local variables (so the function-local variable
context has no variable hash table), make sure we create a hash
table so we have a place to save the variable to be propagated.
Fixes bug reported by Crestez Dan Leonard <cdleonard@gmail.com>.
2/18
----
builtins/hash.def
- change add_hashed_command to remove the command being looked up from
the hash table before trying to add it. That way, if it's not found,
there won't be anything remaining in the hash table
2/26
----
trap.[ch]
- move IMPOSSIBLE_TRAP_HANDLER define to trap.h so other parts of the
shell can use it
parse.y
- change yy_readline_get to use IMPOSSIBLE_TRAP_HANDER instead of NULL
as a sentinel value for the SIGINT signal handler
- make sure yy_readline_get resets interrupt_immediately to 0 after
calling readline() using the same criteria it used to set it to 1
before the call -- make the code symmetric. Suggested by Werner
Fink <werner@suse.de>
builtins/read.def
- move assignment to `retval' before decrement of interrupt_immediately
and terminate_immediately and call to discard_unwind_frame
- move assign_vars label before decrement of interrupt_immediately and
terminate_immediately so those variables get reset appropriately
if read -t times out
subst.h
- new define for Q_DOLBRACE, indicates double-quoted ${...}
subst.c
- in parameter_brace_expand, before calling parameter_brace_expand_rhs,
add Q_DOLBRACE to `quoted' if we're within double quotes.
- in expand_word_internal, if the Q_DOLBRACE flag is set, remove a
backslash escaping a { or }. Result of a Posix discussion on the
austin-group list
2/27
----
variables.c
- new functions to save and restore the PIPESTATUS variable's internal
array: save_pipestatus_array and restore_pipestatus_array
variables.h
- new extern declarations for save_pipestatus_array and
restore_pipestatus_array
trap.c
- in run_pending_traps, _run_trap_internal, and run_exit_trap, save
and restore $PIPESTATUS while traps are running. Fixes bug
reported by Florian Bruhin <me@the-compiler.org>
parse.y
- use save_pipestatus_array and restore_pipestatus_array in
save_parser_state and restore_parser_state, respectively, replacing
inline code
lib/readline/histfile.c
- fix callers of history_filename to be prepared to cope with it
returning NULL
- change history_filename to return NULL if $HOME is not set, rather
than trying to write the history file in the current directory.
This is the default directory, used only if the application does
not specify a history filename. Changed due to long-ago (unsent)
bug report from OpenBSD
{Makefile,config.h,configure}.in,externs.h,lib/sh/{dprintf.c,Makefile.in}
- change fdprintf to dprintf, which is the Posix standard interface,
look for it with configure, replace it if not available
2/28
----
command.h
- add new subshell flag, SUBSHELL_RESETTRAP. Indicates to the trap
builtin that the shell is executing a command substitution and
should free the trap strings we left unfreed by reset_signal_handlers()
trap.c
- free_trap_string() and free_trap_strings() are now compiled in
builtins/trap.def
- if changing a signal disposition and the SUBSHELL_RESETTRAP flag is
set in subshell_environment, free the trap strings left unfreed by
reset_signal_handlers
subst.c
- in command_substitute, set the SUBSHELL_RESETTRAP flag. This change
is for Austin Group Posix interpretation 53
(http://austingroupbugs.net/view.php?id=53)
+1 -1
View File
@@ -382,8 +382,8 @@ lib/sh/Makefile.in f
lib/sh/casemod.c f
lib/sh/clktck.c f
lib/sh/clock.c f
lib/sh/dprintf.c f
lib/sh/eaccess.c f
lib/sh/fdprintf.c f
lib/sh/fmtullong.c f
lib/sh/fmtulong.c f
lib/sh/fmtumax.c f
+1135
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -212,7 +212,7 @@ SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \
${SH_LIBSRC}/zmapfd.c ${SH_LIBSRC}/fpurge.c \
${SH_LIBSRC}/zgetline.c ${SH_LIBSRC}/mbscmp.c \
${SH_LIBSRC}/casemod.c ${SH_LIBSRC}/uconvert.c \
${SH_LIBSRC}/ufuncs.c ${SH_LIBSRC}/fdprintf.c \
${SH_LIBSRC}/ufuncs.c ${SH_LIBSRC}/dprintf.c \
${SH_LIBSRC}/input_avail.c ${SH_LIBSRC}/mbscasecmp.c \
${SH_LIBSRC}/fnxform.c
+1526
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,5 +1,5 @@
@%:@! /bin/sh
@%:@ From configure.in for Bash 4.1, version 4.020.
@%:@ From configure.in for Bash 4.1, version 4.021.
@%:@ Guess values for system-dependent variables and create Makefiles.
@%:@ Generated by GNU Autoconf 2.63 for bash 4.1-maint.
@%:@
@@ -14334,7 +14334,7 @@ done
for ac_func in fdprintf
for ac_func in dprintf
do
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
+11 -11
View File
@@ -15,25 +15,25 @@
'configure.in'
],
{
'AM_PROG_F77_C_O' => 1,
'_LT_AC_TAGCONFIG' => 1,
'm4_pattern_forbid' => 1,
'AM_PROG_F77_C_O' => 1,
'AC_INIT' => 1,
'AC_CANONICAL_TARGET' => 1,
'm4_pattern_forbid' => 1,
'_AM_COND_IF' => 1,
'AC_CONFIG_LIBOBJ_DIR' => 1,
'AC_CANONICAL_TARGET' => 1,
'AC_SUBST' => 1,
'AC_CANONICAL_HOST' => 1,
'AC_CONFIG_LIBOBJ_DIR' => 1,
'AC_FC_SRCEXT' => 1,
'AC_CANONICAL_HOST' => 1,
'AC_PROG_LIBTOOL' => 1,
'AM_INIT_AUTOMAKE' => 1,
'AC_CONFIG_SUBDIRS' => 1,
'AM_AUTOMAKE_VERSION' => 1,
'LT_CONFIG_LTDL_DIR' => 1,
'AC_CONFIG_LINKS' => 1,
'AC_REQUIRE_AUX_FILE' => 1,
'LT_SUPPORTED_TAG' => 1,
'AC_CONFIG_LINKS' => 1,
'm4_sinclude' => 1,
'LT_SUPPORTED_TAG' => 1,
'AM_MAINTAINER_MODE' => 1,
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
'_m4_warn' => 1,
@@ -49,13 +49,13 @@
'AC_CANONICAL_BUILD' => 1,
'AC_FC_FREEFORM' => 1,
'AH_OUTPUT' => 1,
'AC_CONFIG_AUX_DIR' => 1,
'_AM_SUBST_NOTMAKE' => 1,
'AM_PROG_CC_C_O' => 1,
'm4_pattern_allow' => 1,
'AC_CONFIG_AUX_DIR' => 1,
'sinclude' => 1,
'AM_CONDITIONAL' => 1,
'm4_pattern_allow' => 1,
'AM_PROG_CC_C_O' => 1,
'AC_CANONICAL_SYSTEM' => 1,
'AM_CONDITIONAL' => 1,
'AC_CONFIG_HEADERS' => 1,
'AC_DEFINE_TRACE_LITERAL' => 1,
'm4_include' => 1,
+3 -3
View File
@@ -1481,9 +1481,9 @@ m4trace:configure.in:741: -1- AH_OUTPUT([HAVE_STRTOUMAX], [/* Define to 1 if you
m4trace:configure.in:741: -1- AC_SUBST([LIB@&t@OBJS], ["$LIB@&t@OBJS $ac_func.$ac_objext"])
m4trace:configure.in:741: -1- AC_SUBST_TRACE([LIB@&t@OBJS])
m4trace:configure.in:741: -1- m4_pattern_allow([^LIB@&t@OBJS$])
m4trace:configure.in:742: -1- AC_LIBSOURCE([fdprintf.c])
m4trace:configure.in:742: -1- AH_OUTPUT([HAVE_FDPRINTF], [/* Define to 1 if you have the `fdprintf\' function. */
#undef HAVE_FDPRINTF])
m4trace:configure.in:742: -1- AC_LIBSOURCE([dprintf.c])
m4trace:configure.in:742: -1- AH_OUTPUT([HAVE_DPRINTF], [/* Define to 1 if you have the `dprintf\' function. */
#undef HAVE_DPRINTF])
m4trace:configure.in:742: -1- AC_SUBST([LIB@&t@OBJS], ["$LIB@&t@OBJS $ac_func.$ac_objext"])
m4trace:configure.in:742: -1- AC_SUBST_TRACE([LIB@&t@OBJS])
m4trace:configure.in:742: -1- m4_pattern_allow([^LIB@&t@OBJS$])
+4 -4
View File
@@ -615,14 +615,14 @@ add_char:
if (unbuffered_read == 0)
zsyncfd (fd);
interrupt_immediately--;
terminate_immediately--;
discard_unwind_frame ("read_builtin");
retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
assign_vars:
interrupt_immediately--;
terminate_immediately--;
discard_unwind_frame ("read_builtin");
#if defined (ARRAY_VARS)
/* If -a was given, take the string read, break it into a list of words,
an assign them to `arrayname' in turn. */
+985
View File
@@ -0,0 +1,985 @@
This file is read.def, from which is created read.c.
It implements the builtin "read" in Bash.
Copyright (C) 1987-2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
$PRODUCES read.c
$BUILTIN read
$FUNCTION read_builtin
$SHORT_DOC read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
Read a line from the standard input and split it into fields.
Reads a single line from the standard input, or from file descriptor FD
if the -u option is supplied. The line is split into fields as with word
splitting, and the first word is assigned to the first NAME, the second
word to the second NAME, and so on, with any leftover words assigned to
the last NAME. Only the characters found in $IFS are recognized as word
delimiters.
If no NAMEs are supplied, the line read is stored in the REPLY variable.
Options:
-a array assign the words read to sequential indices of the array
variable ARRAY, starting at zero
-d delim continue until the first character of DELIM is read, rather
than newline
-e use Readline to obtain the line in an interactive shell
-i text Use TEXT as the initial text for Readline
-n nchars return after reading NCHARS characters rather than waiting
for a newline, but honor a delimiter if fewer than NCHARS
characters are read before the delimiter
-N nchars return only after reading exactly NCHARS characters, unless
EOF is encountered or read times out, ignoring any delimiter
-p prompt output the string PROMPT without a trailing newline before
attempting to read
-r do not allow backslashes to escape any characters
-s do not echo input coming from a terminal
-t timeout time out and return failure if a complete line of input is
not read withint TIMEOUT seconds. The value of the TMOUT
variable is the default timeout. TIMEOUT may be a
fractional number. If TIMEOUT is 0, read returns success only
if input is available on the specified file descriptor. The
exit status is greater than 128 if the timeout is exceeded
-u fd read from file descriptor FD instead of the standard input
Exit Status:
The return code is zero, unless end-of-file is encountered, read times out,
or an invalid file descriptor is supplied as the argument to -u.
$END
#include <config.h>
#include "bashtypes.h"
#include "posixstat.h"
#include <stdio.h>
#include "bashansi.h"
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <signal.h>
#include <errno.h>
#ifdef __CYGWIN__
# include <fcntl.h>
# include <io.h>
#endif
#include "../bashintl.h"
#include "../shell.h"
#include "common.h"
#include "bashgetopt.h"
#include <shtty.h>
#if defined (READLINE)
#include "../bashline.h"
#include <readline/readline.h>
#endif
#if defined (BUFFERED_INPUT)
# include "input.h"
#endif
#if !defined(errno)
extern int errno;
#endif
struct ttsave
{
int fd;
TTYSTRUCT *attrs;
};
#if defined (READLINE)
static void reset_attempted_completion_function __P((char *));
static int set_itext __P((void));
static char *edit_line __P((char *, char *));
static void set_eol_delim __P((int));
static void reset_eol_delim __P((char *));
#endif
static SHELL_VAR *bind_read_variable __P((char *, char *));
#if defined (HANDLE_MULTIBYTE)
static int read_mbchar __P((int, char *, int, int, int));
#endif
static void ttyrestore __P((struct ttsave *));
static sighandler sigalrm __P((int));
static void reset_alarm __P((void));
static procenv_t alrmbuf;
static SigHandler *old_alrm;
static unsigned char delim;
static sighandler
sigalrm (s)
int s;
{
longjmp (alrmbuf, 1);
}
static void
reset_alarm ()
{
set_signal_handler (SIGALRM, old_alrm);
falarm (0, 0);
}
/* Read the value of the shell variables whose names follow.
The reading is done from the current input stream, whatever
that may be. Successive words of the input line are assigned
to the variables mentioned in LIST. The last variable in LIST
gets the remainder of the words on the line. If no variables
are mentioned in LIST, then the default variable is $REPLY. */
int
read_builtin (list)
WORD_LIST *list;
{
register char *varname;
int size, i, nr, pass_next, saw_escape, eof, opt, retval, code, print_ps2;
int input_is_tty, input_is_pipe, unbuffered_read, skip_ctlesc, skip_ctlnul;
int raw, edit, nchars, silent, have_timeout, ignore_delim, fd;
unsigned int tmsec, tmusec;
long ival, uval;
intmax_t intval;
char c;
char *input_string, *orig_input_string, *ifs_chars, *prompt, *arrayname;
char *e, *t, *t1, *ps2, *tofree;
struct stat tsb;
SHELL_VAR *var;
TTYSTRUCT ttattrs, ttset;
struct ttsave termsave;
#if defined (ARRAY_VARS)
WORD_LIST *alist;
#endif
#if defined (READLINE)
char *rlbuf, *itext;
int rlind;
#endif
USE_VAR(size);
USE_VAR(i);
USE_VAR(pass_next);
USE_VAR(print_ps2);
USE_VAR(saw_escape);
USE_VAR(input_is_pipe);
/* USE_VAR(raw); */
USE_VAR(edit);
USE_VAR(tmsec);
USE_VAR(tmusec);
USE_VAR(nchars);
USE_VAR(silent);
USE_VAR(ifs_chars);
USE_VAR(prompt);
USE_VAR(arrayname);
#if defined (READLINE)
USE_VAR(rlbuf);
USE_VAR(rlind);
USE_VAR(itext);
#endif
USE_VAR(list);
USE_VAR(ps2);
i = 0; /* Index into the string that we are reading. */
raw = edit = 0; /* Not reading raw input by default. */
silent = 0;
arrayname = prompt = (char *)NULL;
fd = 0; /* file descriptor to read from */
#if defined (READLINE)
rlbuf = itext = (char *)0;
rlind = 0;
#endif
tmsec = tmusec = 0; /* no timeout */
nr = nchars = input_is_tty = input_is_pipe = unbuffered_read = have_timeout = 0;
delim = '\n'; /* read until newline */
ignore_delim = 0;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "ersa:d:i:n:p:t:u:N:")) != -1)
{
switch (opt)
{
case 'r':
raw = 1;
break;
case 'p':
prompt = list_optarg;
break;
case 's':
silent = 1;
break;
case 'e':
#if defined (READLINE)
edit = 1;
#endif
break;
case 'i':
#if defined (READLINE)
itext = list_optarg;
#endif
break;
#if defined (ARRAY_VARS)
case 'a':
arrayname = list_optarg;
break;
#endif
case 't':
code = uconvert (list_optarg, &ival, &uval);
if (code == 0 || ival < 0 || uval < 0)
{
builtin_error (_("%s: invalid timeout specification"), list_optarg);
return (EXECUTION_FAILURE);
}
else
{
have_timeout = 1;
tmsec = ival;
tmusec = uval;
}
break;
case 'N':
ignore_delim = 1;
delim = -1;
case 'n':
code = legal_number (list_optarg, &intval);
if (code == 0 || intval < 0 || intval != (int)intval)
{
sh_invalidnum (list_optarg);
return (EXECUTION_FAILURE);
}
else
nchars = intval;
break;
case 'u':
code = legal_number (list_optarg, &intval);
if (code == 0 || intval < 0 || intval != (int)intval)
{
builtin_error (_("%s: invalid file descriptor specification"), list_optarg);
return (EXECUTION_FAILURE);
}
else
fd = intval;
if (sh_validfd (fd) == 0)
{
builtin_error (_("%d: invalid file descriptor: %s"), fd, strerror (errno));
return (EXECUTION_FAILURE);
}
break;
case 'd':
delim = *list_optarg;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
/* `read -t 0 var' tests whether input is available with select/FIONREAD,
and fails if those are unavailable */
if (have_timeout && tmsec == 0 && tmusec == 0)
#if 0
return (EXECUTION_FAILURE);
#else
return (input_avail (fd) ? EXECUTION_SUCCESS : EXECUTION_FAILURE);
#endif
/* If we're asked to ignore the delimiter, make sure we do. */
if (ignore_delim)
delim = -1;
/* IF IFS is unset, we use the default of " \t\n". */
ifs_chars = getifs ();
if (ifs_chars == 0) /* XXX - shouldn't happen */
ifs_chars = "";
/* If we want to read exactly NCHARS chars, don't split on IFS */
if (ignore_delim)
ifs_chars = "";
for (skip_ctlesc = skip_ctlnul = 0, e = ifs_chars; *e; e++)
skip_ctlesc |= *e == CTLESC, skip_ctlnul |= *e == CTLNUL;
input_string = (char *)xmalloc (size = 112); /* XXX was 128 */
input_string[0] = '\0';
/* $TMOUT, if set, is the default timeout for read. */
if (have_timeout == 0 && (e = get_string_value ("TMOUT")))
{
code = uconvert (e, &ival, &uval);
if (code == 0 || ival < 0 || uval < 0)
tmsec = tmusec = 0;
else
{
tmsec = ival;
tmusec = uval;
}
}
begin_unwind_frame ("read_builtin");
#if defined (BUFFERED_INPUT)
if (interactive == 0 && default_buffered_input >= 0 && fd_is_bash_input (fd))
sync_buffered_stream (default_buffered_input);
#endif
input_is_tty = isatty (fd);
if (input_is_tty == 0)
#ifndef __CYGWIN__
input_is_pipe = (lseek (fd, 0L, SEEK_CUR) < 0) && (errno == ESPIPE);
#else
input_is_pipe = 1;
#endif
/* If the -p, -e or -s flags were given, but input is not coming from the
terminal, turn them off. */
if ((prompt || edit || silent) && input_is_tty == 0)
{
prompt = (char *)NULL;
#if defined (READLINE)
itext = (char *)NULL;
#endif
edit = silent = 0;
}
#if defined (READLINE)
if (edit)
add_unwind_protect (xfree, rlbuf);
#endif
pass_next = 0; /* Non-zero signifies last char was backslash. */
saw_escape = 0; /* Non-zero signifies that we saw an escape char */
if (tmsec > 0 || tmusec > 0)
{
/* Turn off the timeout if stdin is a regular file (e.g. from
input redirection). */
if ((fstat (fd, &tsb) < 0) || S_ISREG (tsb.st_mode))
tmsec = tmusec = 0;
}
if (tmsec > 0 || tmusec > 0)
{
code = setjmp (alrmbuf);
if (code)
{
/* Tricky. The top of the unwind-protect stack is the free of
input_string. We want to run all the rest and use input_string,
so we have to remove it from the stack. */
remove_unwind_protect ();
run_unwind_frame ("read_builtin");
input_string[i] = '\0'; /* make sure it's terminated */
retval = 128+SIGALRM;
itrace("read_builtin: before goto assign_vars: interrupt_immediately = %d", interrupt_immediately);
goto assign_vars;
}
old_alrm = set_signal_handler (SIGALRM, sigalrm);
add_unwind_protect (reset_alarm, (char *)NULL);
#if defined (READLINE)
if (edit)
add_unwind_protect (reset_attempted_completion_function, (char *)NULL);
#endif
falarm (tmsec, tmusec);
}
/* If we've been asked to read only NCHARS chars, or we're using some
character other than newline to terminate the line, do the right
thing to readline or the tty. */
if (nchars > 0 || delim != '\n')
{
#if defined (READLINE)
if (edit)
{
if (nchars > 0)
{
unwind_protect_int (rl_num_chars_to_read);
rl_num_chars_to_read = nchars;
}
if (delim != '\n')
{
set_eol_delim (delim);
add_unwind_protect (reset_eol_delim, (char *)NULL);
}
}
else
#endif
if (input_is_tty)
{
/* ttsave() */
termsave.fd = fd;
ttgetattr (fd, &ttattrs);
termsave.attrs = &ttattrs;
ttset = ttattrs;
i = silent ? ttfd_cbreak (fd, &ttset) : ttfd_onechar (fd, &ttset);
if (i < 0)
sh_ttyerror (1);
add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
}
}
else if (silent) /* turn off echo but leave term in canonical mode */
{
/* ttsave (); */
termsave.fd = fd;
ttgetattr (fd, &ttattrs);
termsave.attrs = &ttattrs;
ttset = ttattrs;
i = ttfd_noecho (fd, &ttset); /* ttnoecho (); */
if (i < 0)
sh_ttyerror (1);
add_unwind_protect ((Function *)ttyrestore, (char *)&termsave);
}
/* This *must* be the top unwind-protect on the stack, so the manipulation
of the unwind-protect stack after the realloc() works right. */
add_unwind_protect (xfree, input_string);
interrupt_immediately++;
terminate_immediately++;
unbuffered_read = (nchars > 0) || (delim != '\n') || input_is_pipe;
if (prompt && edit == 0)
{
fprintf (stderr, "%s", prompt);
fflush (stderr);
}
#if defined (__CYGWIN__) && defined (O_TEXT)
setmode (0, O_TEXT);
#endif
ps2 = 0;
for (print_ps2 = eof = retval = 0;;)
{
#if defined (READLINE)
if (edit)
{
if (rlbuf && rlbuf[rlind] == '\0')
{
xfree (rlbuf);
rlbuf = (char *)0;
}
if (rlbuf == 0)
{
rlbuf = edit_line (prompt ? prompt : "", itext);
rlind = 0;
}
if (rlbuf == 0)
{
eof = 1;
break;
}
c = rlbuf[rlind++];
}
else
{
#endif
if (print_ps2)
{
if (ps2 == 0)
ps2 = get_string_value ("PS2");
fprintf (stderr, "%s", ps2 ? ps2 : "");
fflush (stderr);
print_ps2 = 0;
}
if (unbuffered_read)
retval = zread (fd, &c, 1);
else
retval = zreadc (fd, &c);
if (retval <= 0)
{
eof = 1;
break;
}
#if defined (READLINE)
}
#endif
if (i + 4 >= size) /* XXX was i + 2; use i + 4 for multibyte/read_mbchar */
{
input_string = (char *)xrealloc (input_string, size += 128);
remove_unwind_protect ();
add_unwind_protect (xfree, input_string);
}
/* If the next character is to be accepted verbatim, a backslash
newline pair still disappears from the input. */
if (pass_next)
{
pass_next = 0;
if (c == '\n')
{
i--; /* back up over the CTLESC */
if (interactive && input_is_tty && raw == 0)
print_ps2 = 1;
}
else
goto add_char;
continue;
}
/* This may cause problems if IFS contains CTLESC */
if (c == '\\' && raw == 0)
{
pass_next++;
if (skip_ctlesc == 0)
{
saw_escape++;
input_string[i++] = CTLESC;
}
continue;
}
if ((unsigned char)c == delim)
break;
if ((skip_ctlesc == 0 && c == CTLESC) || (skip_ctlnul == 0 && c == CTLNUL))
{
saw_escape++;
input_string[i++] = CTLESC;
}
add_char:
input_string[i++] = c;
#if defined (HANDLE_MULTIBYTE)
if (nchars > 0 && MB_CUR_MAX > 1)
{
input_string[i] = '\0'; /* for simplicity and debugging */
i += read_mbchar (fd, input_string, i, c, unbuffered_read);
}
#endif
nr++;
if (nchars > 0 && nr >= nchars)
break;
}
input_string[i] = '\0';
#if 1
if (retval < 0)
{
builtin_error (_("read error: %d: %s"), fd, strerror (errno));
run_unwind_frame ("read_builtin");
return (EXECUTION_FAILURE);
}
#endif
if (tmsec > 0 || tmusec > 0)
reset_alarm ();
if (nchars > 0 || delim != '\n')
{
#if defined (READLINE)
if (edit)
{
if (nchars > 0)
rl_num_chars_to_read = 0;
if (delim != '\n')
reset_eol_delim ((char *)NULL);
}
else
#endif
if (input_is_tty)
ttyrestore (&termsave);
}
else if (silent)
ttyrestore (&termsave);
if (unbuffered_read == 0)
zsyncfd (fd);
retval = eof ? EXECUTION_FAILURE : EXECUTION_SUCCESS;
assign_vars:
interrupt_immediately--;
terminate_immediately--;
discard_unwind_frame ("read_builtin");
#if defined (ARRAY_VARS)
/* If -a was given, take the string read, break it into a list of words,
an assign them to `arrayname' in turn. */
if (arrayname)
{
if (legal_identifier (arrayname) == 0)
{
sh_invalidid (arrayname);
xfree (input_string);
return (EXECUTION_FAILURE);
}
var = find_or_make_array_variable (arrayname, 1);
if (var == 0)
{
xfree (input_string);
return EXECUTION_FAILURE; /* readonly or noassign */
}
array_flush (array_cell (var));
alist = list_string (input_string, ifs_chars, 0);
if (alist)
{
if (saw_escape)
dequote_list (alist);
else
word_list_remove_quoted_nulls (alist);
assign_array_var_from_word_list (var, alist, 0);
dispose_words (alist);
}
xfree (input_string);
return (retval);
}
#endif /* ARRAY_VARS */
/* If there are no variables, save the text of the line read to the
variable $REPLY. ksh93 strips leading and trailing IFS whitespace,
so that `read x ; echo "$x"' and `read ; echo "$REPLY"' behave the
same way, but I believe that the difference in behaviors is useful
enough to not do it. Without the bash behavior, there is no way
to read a line completely without interpretation or modification
unless you mess with $IFS (e.g., setting it to the empty string).
If you disagree, change the occurrences of `#if 0' to `#if 1' below. */
if (list == 0)
{
#if 0
orig_input_string = input_string;
for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
;
input_string = t;
input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
#endif
if (saw_escape)
{
t = dequote_string (input_string);
var = bind_variable ("REPLY", t, 0);
free (t);
}
else
var = bind_variable ("REPLY", input_string, 0);
VUNSETATTR (var, att_invisible);
free (input_string);
return (retval);
}
/* This code implements the Posix.2 spec for splitting the words
read and assigning them to variables. */
orig_input_string = input_string;
/* Remove IFS white space at the beginning of the input string. If
$IFS is null, no field splitting is performed. */
for (t = input_string; ifs_chars && *ifs_chars && spctabnl(*t) && isifs(*t); t++)
;
input_string = t;
for (; list->next; list = list->next)
{
varname = list->word->word;
#if defined (ARRAY_VARS)
if (legal_identifier (varname) == 0 && valid_array_reference (varname) == 0)
#else
if (legal_identifier (varname) == 0)
#endif
{
sh_invalidid (varname);
xfree (orig_input_string);
return (EXECUTION_FAILURE);
}
/* If there are more variables than words read from the input,
the remaining variables are set to the empty string. */
if (*input_string)
{
/* This call updates INPUT_STRING. */
t = get_word_from_string (&input_string, ifs_chars, &e);
if (t)
*e = '\0';
/* Don't bother to remove the CTLESC unless we added one
somewhere while reading the string. */
if (t && saw_escape)
{
t1 = dequote_string (t);
var = bind_read_variable (varname, t1);
xfree (t1);
}
else
var = bind_read_variable (varname, t);
}
else
{
t = (char *)0;
var = bind_read_variable (varname, "");
}
FREE (t);
if (var == 0)
{
xfree (orig_input_string);
return (EXECUTION_FAILURE);
}
stupidly_hack_special_variables (varname);
VUNSETATTR (var, att_invisible);
}
/* Now assign the rest of the line to the last variable argument. */
#if defined (ARRAY_VARS)
if (legal_identifier (list->word->word) == 0 && valid_array_reference (list->word->word) == 0)
#else
if (legal_identifier (list->word->word) == 0)
#endif
{
sh_invalidid (list->word->word);
xfree (orig_input_string);
return (EXECUTION_FAILURE);
}
#if 0
/* This has to be done this way rather than using string_list
and list_string because Posix.2 says that the last variable gets the
remaining words and their intervening separators. */
input_string = strip_trailing_ifs_whitespace (input_string, ifs_chars, saw_escape);
#else
/* Check whether or not the number of fields is exactly the same as the
number of variables. */
tofree = NULL;
if (*input_string)
{
t1 = input_string;
t = get_word_from_string (&input_string, ifs_chars, &e);
if (*input_string == 0)
tofree = input_string = t;
else
{
input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
tofree = t;
}
}
#endif
if (saw_escape)
{
t = dequote_string (input_string);
var = bind_read_variable (list->word->word, t);
xfree (t);
}
else
var = bind_read_variable (list->word->word, input_string);
stupidly_hack_special_variables (list->word->word);
FREE (tofree);
if (var)
VUNSETATTR (var, att_invisible);
xfree (orig_input_string);
return (retval);
}
static SHELL_VAR *
bind_read_variable (name, value)
char *name, *value;
{
#if defined (ARRAY_VARS)
if (valid_array_reference (name) == 0)
return (bind_variable (name, value, 0));
else
return (assign_array_element (name, value, 0));
#else /* !ARRAY_VARS */
return bind_variable (name, value, 0);
#endif /* !ARRAY_VARS */
}
#if defined (HANDLE_MULTIBYTE)
static int
read_mbchar (fd, string, ind, ch, unbuffered)
int fd;
char *string;
int ind, ch, unbuffered;
{
char mbchar[MB_LEN_MAX + 1];
int i, n, r;
char c;
size_t ret;
mbstate_t ps, ps_back;
wchar_t wc;
memset (&ps, '\0', sizeof (mbstate_t));
memset (&ps_back, '\0', sizeof (mbstate_t));
mbchar[0] = ch;
i = 1;
for (n = 0; n <= MB_LEN_MAX; n++)
{
ps_back = ps;
ret = mbrtowc (&wc, mbchar, i, &ps);
if (ret == (size_t)-2)
{
ps = ps_back;
if (unbuffered)
r = zread (fd, &c, 1);
else
r = zreadc (fd, &c);
if (r < 0)
goto mbchar_return;
mbchar[i++] = c;
continue;
}
else if (ret == (size_t)-1 || ret == (size_t)0 || ret > (size_t)0)
break;
}
mbchar_return:
if (i > 1) /* read a multibyte char */
/* mbchar[0] is already string[ind-1] */
for (r = 1; r < i; r++)
string[ind+r-1] = mbchar[r];
return i - 1;
}
#endif
static void
ttyrestore (ttp)
struct ttsave *ttp;
{
ttsetattr (ttp->fd, ttp->attrs);
}
#if defined (READLINE)
static rl_completion_func_t *old_attempted_completion_function = 0;
static rl_hook_func_t *old_startup_hook;
static char *deftext;
static void
reset_attempted_completion_function (cp)
char *cp;
{
if (rl_attempted_completion_function == 0 && old_attempted_completion_function)
rl_attempted_completion_function = old_attempted_completion_function;
}
static int
set_itext ()
{
int r1, r2;
r1 = r2 = 0;
if (old_startup_hook)
r1 = (*old_startup_hook) ();
if (deftext)
{
r2 = rl_insert_text (deftext);
deftext = (char *)NULL;
rl_startup_hook = old_startup_hook;
old_startup_hook = (rl_hook_func_t *)NULL;
}
return (r1 || r2);
}
static char *
edit_line (p, itext)
char *p;
char *itext;
{
char *ret;
int len;
if (bash_readline_initialized == 0)
initialize_readline ();
old_attempted_completion_function = rl_attempted_completion_function;
rl_attempted_completion_function = (rl_completion_func_t *)NULL;
if (itext)
{
old_startup_hook = rl_startup_hook;
rl_startup_hook = set_itext;
deftext = itext;
}
ret = readline (p);
rl_attempted_completion_function = old_attempted_completion_function;
old_attempted_completion_function = (rl_completion_func_t *)NULL;
if (ret == 0)
return ret;
len = strlen (ret);
ret = (char *)xrealloc (ret, len + 2);
ret[len++] = delim;
ret[len] = '\0';
return ret;
}
static int old_delim_ctype;
static rl_command_func_t *old_delim_func;
static int old_newline_ctype;
static rl_command_func_t *old_newline_func;
static unsigned char delim_char;
static void
set_eol_delim (c)
int c;
{
Keymap cmap;
if (bash_readline_initialized == 0)
initialize_readline ();
cmap = rl_get_keymap ();
/* Change newline to self-insert */
old_newline_ctype = cmap[RETURN].type;
old_newline_func = cmap[RETURN].function;
cmap[RETURN].type = ISFUNC;
cmap[RETURN].function = rl_insert;
/* Bind the delimiter character to accept-line. */
old_delim_ctype = cmap[c].type;
old_delim_func = cmap[c].function;
cmap[c].type = ISFUNC;
cmap[c].function = rl_newline;
delim_char = c;
}
static void
reset_eol_delim (cp)
char *cp;
{
Keymap cmap;
cmap = rl_get_keymap ();
cmap[RETURN].type = old_newline_ctype;
cmap[RETURN].function = old_newline_func;
cmap[delim_char].type = old_delim_ctype;
cmap[delim_char].function = old_delim_func;
}
#endif
+12 -1
View File
@@ -93,7 +93,7 @@ static int display_traps __P((WORD_LIST *));
#define REVERT 1 /* Revert to this signals original value. */
#define IGNORE 2 /* Ignore this signal. */
extern int posixly_correct;
extern int posixly_correct, subshell_environment;
int
trap_builtin (list)
@@ -103,6 +103,7 @@ trap_builtin (list)
list_signal_names = display = 0;
result = EXECUTION_SUCCESS;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "lp")) != -1)
{
@@ -163,6 +164,16 @@ trap_builtin (list)
operation = REVERT;
}
/* If we're in a command substitution, we haven't freed the trap strings
(though we reset the signal handlers). If we're setting a trap to
handle a signal here, free the rest of the trap strings since they
don't apply any more. */
if (subshell_environment & SUBSHELL_RESETTRAP)
{
free_trap_strings ();
subshell_environment &= ~SUBSHELL_RESETTRAP;
}
while (list)
{
sig = decode_signal (list->word->word, opt);
+280
View File
@@ -0,0 +1,280 @@
This file is trap.def, from which is created trap.c.
It implements the builtin "trap" in Bash.
Copyright (C) 1987-2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
$PRODUCES trap.c
$BUILTIN trap
$FUNCTION trap_builtin
$SHORT_DOC trap [-lp] [[arg] signal_spec ...]
Trap signals and other events.
Defines and activates handlers to be run when the shell receives signals
or other conditions.
ARG is a command to be read and executed when the shell receives the
signal(s) SIGNAL_SPEC. If ARG is absent (and a single SIGNAL_SPEC
is supplied) or `-', each specified signal is reset to its original
value. If ARG is the null string each SIGNAL_SPEC is ignored by the
shell and by the commands it invokes.
If a SIGNAL_SPEC is EXIT (0) ARG is executed on exit from the shell. If
a SIGNAL_SPEC is DEBUG, ARG is executed before every simple command.
If no arguments are supplied, trap prints the list of commands associated
with each signal.
Options:
-l print a list of signal names and their corresponding numbers
-p display the trap commands associated with each SIGNAL_SPEC
Each SIGNAL_SPEC is either a signal name in <signal.h> or a signal number.
Signal names are case insensitive and the SIG prefix is optional. A
signal may be sent to the shell with "kill -signal $$".
Exit Status:
Returns success unless a SIGSPEC is invalid or an invalid option is given.
$END
#include <config.h>
#if defined (HAVE_UNISTD_H)
# ifdef _MINIX
# include <sys/types.h>
# endif
# include <unistd.h>
#endif
#include "../bashtypes.h"
#include <signal.h>
#include <stdio.h>
#include "../bashansi.h"
#include "../shell.h"
#include "../trap.h"
#include "common.h"
#include "bashgetopt.h"
static void showtrap __P((int));
static int display_traps __P((WORD_LIST *));
/* The trap command:
trap <arg> <signal ...>
trap <signal ...>
trap -l
trap -p [sigspec ...]
trap [--]
Set things up so that ARG is executed when SIGNAL(s) N is recieved.
If ARG is the empty string, then ignore the SIGNAL(s). If there is
no ARG, then set the trap for SIGNAL(s) to its original value. Just
plain "trap" means to print out the list of commands associated with
each signal number. Single arg of "-l" means list the signal names. */
/* Possible operations to perform on the list of signals.*/
#define SET 0 /* Set this signal to first_arg. */
#define REVERT 1 /* Revert to this signals original value. */
#define IGNORE 2 /* Ignore this signal. */
extern int posixly_correct;
int
trap_builtin (list)
WORD_LIST *list;
{
int list_signal_names, display, result, opt;
list_signal_names = display = 0;
result = EXECUTION_SUCCESS;
reset_internal_getopt ();
while ((opt = internal_getopt (list, "lp")) != -1)
{
switch (opt)
{
case 'l':
list_signal_names++;
break;
case 'p':
display++;
break;
default:
builtin_usage ();
return (EX_USAGE);
}
}
list = loptend;
opt = DSIG_NOCASE|DSIG_SIGPREFIX; /* flags for decode_signal */
if (list_signal_names)
return (sh_chkwrite (display_signal_list ((WORD_LIST *)NULL, 1)));
else if (display || list == 0)
return (sh_chkwrite (display_traps (list)));
else
{
char *first_arg;
int operation, sig, first_signal;
operation = SET;
first_arg = list->word->word;
first_signal = first_arg && *first_arg && all_digits (first_arg) && signal_object_p (first_arg, opt);
/* Backwards compatibility. XXX - question about whether or not we
should throw an error if an all-digit argument doesn't correspond
to a valid signal number (e.g., if it's `50' on a system with only
32 signals). */
if (first_signal)
operation = REVERT;
/* When in posix mode, the historical behavior of looking for a
missing first argument is disabled. To revert to the original
signal handling disposition, use `-' as the first argument. */
else if (posixly_correct == 0 && first_arg && *first_arg &&
(*first_arg != '-' || first_arg[1]) &&
signal_object_p (first_arg, opt) && list->next == 0)
operation = REVERT;
else
{
list = list->next;
if (list == 0)
{
builtin_usage ();
return (EX_USAGE);
}
else if (*first_arg == '\0')
operation = IGNORE;
else if (first_arg[0] == '-' && !first_arg[1])
operation = REVERT;
}
while (list)
{
sig = decode_signal (list->word->word, opt);
if (sig == NO_SIG)
{
sh_invalidsig (list->word->word);
result = EXECUTION_FAILURE;
}
else
{
switch (operation)
{
case SET:
set_signal (sig, first_arg);
break;
case REVERT:
restore_default_signal (sig);
/* Signals that the shell treats specially need special
handling. */
switch (sig)
{
case SIGINT:
if (interactive)
set_signal_handler (SIGINT, sigint_sighandler);
else
set_signal_handler (SIGINT, termsig_sighandler);
break;
case SIGQUIT:
/* Always ignore SIGQUIT. */
set_signal_handler (SIGQUIT, SIG_IGN);
break;
case SIGTERM:
#if defined (JOB_CONTROL)
case SIGTTIN:
case SIGTTOU:
case SIGTSTP:
#endif /* JOB_CONTROL */
if (interactive)
set_signal_handler (sig, SIG_IGN);
break;
}
break;
case IGNORE:
ignore_signal (sig);
break;
}
}
list = list->next;
}
}
return (result);
}
static void
showtrap (i)
int i;
{
char *t, *p, *sn;
p = trap_list[i];
if (p == (char *)DEFAULT_SIG)
return;
t = (p == (char *)IGNORE_SIG) ? (char *)NULL : sh_single_quote (p);
sn = signal_name (i);
/* Make sure that signals whose names are unknown (for whatever reason)
are printed as signal numbers. */
if (STREQN (sn, "SIGJUNK", 7) || STREQN (sn, "unknown", 7))
printf ("trap -- %s %d\n", t ? t : "''", i);
else if (posixly_correct)
{
if (STREQN (sn, "SIG", 3))
printf ("trap -- %s %s\n", t ? t : "''", sn+3);
else
printf ("trap -- %s %s\n", t ? t : "''", sn);
}
else
printf ("trap -- %s %s\n", t ? t : "''", sn);
FREE (t);
}
static int
display_traps (list)
WORD_LIST *list;
{
int result, i;
if (list == 0)
{
for (i = 0; i < BASH_NSIG; i++)
showtrap (i);
return (EXECUTION_SUCCESS);
}
for (result = EXECUTION_SUCCESS; list; list = list->next)
{
i = decode_signal (list->word->word, DSIG_NOCASE|DSIG_SIGPREFIX);
if (i == NO_SIG)
{
sh_invalidsig (list->word->word);
result = EXECUTION_FAILURE;
}
else
showtrap (i);
}
return (result);
}
+1
View File
@@ -105,6 +105,7 @@ enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
#define SUBSHELL_PIPE 0x10 /* subshell from a pipeline element */
#define SUBSHELL_PROCSUB 0x20 /* subshell caused by <(command) or >(command) */
#define SUBSHELL_COPROC 0x40 /* subshell from a coproc pipeline */
#define SUBSHELL_RESETTRAP 0x80 /* subshell needs to reset trap strings on first call to trap */
/* A structure which represents a word. */
typedef struct word_desc {
+384
View File
@@ -0,0 +1,384 @@
/* command.h -- The structures used internally to represent commands, and
the extern declarations of the functions used to create them. */
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (_COMMAND_H_)
#define _COMMAND_H_
#include "stdc.h"
/* Instructions describing what kind of thing to do for a redirection. */
enum r_instruction {
r_output_direction, r_input_direction, r_inputa_direction,
r_appending_to, r_reading_until, r_reading_string,
r_duplicating_input, r_duplicating_output, r_deblank_reading_until,
r_close_this, r_err_and_out, r_input_output, r_output_force,
r_duplicating_input_word, r_duplicating_output_word,
r_move_input, r_move_output, r_move_input_word, r_move_output_word,
r_append_err_and_out
};
/* Redirection flags; values for rflags */
#define REDIR_VARASSIGN 0x01
/* Redirection errors. */
#define AMBIGUOUS_REDIRECT -1
#define NOCLOBBER_REDIRECT -2
#define RESTRICTED_REDIRECT -3 /* can only happen in restricted shells. */
#define HEREDOC_REDIRECT -4 /* here-doc temp file can't be created */
#define BADVAR_REDIRECT -5 /* something wrong with {varname}redir */
#define CLOBBERING_REDIRECT(ri) \
(ri == r_output_direction || ri == r_err_and_out)
#define OUTPUT_REDIRECT(ri) \
(ri == r_output_direction || ri == r_input_output || ri == r_err_and_out || ri == r_append_err_and_out)
#define INPUT_REDIRECT(ri) \
(ri == r_input_direction || ri == r_inputa_direction || ri == r_input_output)
#define WRITE_REDIRECT(ri) \
(ri == r_output_direction || \
ri == r_input_output || \
ri == r_err_and_out || \
ri == r_appending_to || \
ri == r_append_err_and_out || \
ri == r_output_force)
/* redirection needs translation */
#define TRANSLATE_REDIRECT(ri) \
(ri == r_duplicating_input_word || ri == r_duplicating_output_word || \
ri == r_move_input_word || ri == r_move_output_word)
/* Command Types: */
enum command_type { cm_for, cm_case, cm_while, cm_if, cm_simple, cm_select,
cm_connection, cm_function_def, cm_until, cm_group,
cm_arith, cm_cond, cm_arith_for, cm_subshell, cm_coproc };
/* Possible values for the `flags' field of a WORD_DESC. */
#define W_HASDOLLAR 0x000001 /* Dollar sign present. */
#define W_QUOTED 0x000002 /* Some form of quote character is present. */
#define W_ASSIGNMENT 0x000004 /* This word is a variable assignment. */
#define W_GLOBEXP 0x000008 /* This word is the result of a glob expansion. */
#define W_NOSPLIT 0x000010 /* Do not perform word splitting on this word because ifs is empty string. */
#define W_NOGLOB 0x000020 /* Do not perform globbing on this word. */
#define W_NOSPLIT2 0x000040 /* Don't split word except for $@ expansion (using spaces) because context does not allow it. */
#define W_TILDEEXP 0x000080 /* Tilde expand this assignment word */
#define W_DOLLARAT 0x000100 /* $@ and its special handling */
#define W_DOLLARSTAR 0x000200 /* $* and its special handling */
#define W_NOCOMSUB 0x000400 /* Don't perform command substitution on this word */
#define W_ASSIGNRHS 0x000800 /* Word is rhs of an assignment statement */
#define W_NOTILDE 0x001000 /* Don't perform tilde expansion on this word */
#define W_ITILDE 0x002000 /* Internal flag for word expansion */
#define W_NOEXPAND 0x004000 /* Don't expand at all -- do quote removal */
#define W_COMPASSIGN 0x008000 /* Compound assignment */
#define W_ASSNBLTIN 0x010000 /* word is a builtin command that takes assignments */
#define W_ASSIGNARG 0x020000 /* word is assignment argument to command */
#define W_HASQUOTEDNULL 0x040000 /* word contains a quoted null character */
#define W_DQUOTE 0x080000 /* word should be treated as if double-quoted */
#define W_NOPROCSUB 0x100000 /* don't perform process substitution */
#define W_HASCTLESC 0x200000 /* word contains literal CTLESC characters */
#define W_ASSIGNASSOC 0x400000 /* word looks like associative array assignment */
/* Possible values for subshell_environment */
#define SUBSHELL_ASYNC 0x01 /* subshell caused by `command &' */
#define SUBSHELL_PAREN 0x02 /* subshell caused by ( ... ) */
#define SUBSHELL_COMSUB 0x04 /* subshell caused by `command` or $(command) */
#define SUBSHELL_FORK 0x08 /* subshell caused by executing a disk command */
#define SUBSHELL_PIPE 0x10 /* subshell from a pipeline element */
#define SUBSHELL_PROCSUB 0x20 /* subshell caused by <(command) or >(command) */
#define SUBSHELL_COPROC 0x40 /* subshell from a coproc pipeline */
/* A structure which represents a word. */
typedef struct word_desc {
char *word; /* Zero terminated string. */
int flags; /* Flags associated with this word. */
} WORD_DESC;
/* A linked list of words. */
typedef struct word_list {
struct word_list *next;
WORD_DESC *word;
} WORD_LIST;
/* **************************************************************** */
/* */
/* Shell Command Structs */
/* */
/* **************************************************************** */
/* What a redirection descriptor looks like. If the redirection instruction
is ri_duplicating_input or ri_duplicating_output, use DEST, otherwise
use the file in FILENAME. Out-of-range descriptors are identified by a
negative DEST. */
typedef union {
int dest; /* Place to redirect REDIRECTOR to, or ... */
WORD_DESC *filename; /* filename to redirect to. */
} REDIRECTEE;
/* Structure describing a redirection. If REDIRECTOR is negative, the parser
(or translator in redir.c) encountered an out-of-range file descriptor. */
typedef struct redirect {
struct redirect *next; /* Next element, or NULL. */
REDIRECTEE redirector; /* Descriptor or varname to be redirected. */
int rflags; /* Private flags for this redirection */
int flags; /* Flag value for `open'. */
enum r_instruction instruction; /* What to do with the information. */
REDIRECTEE redirectee; /* File descriptor or filename */
char *here_doc_eof; /* The word that appeared in <<foo. */
} REDIRECT;
/* An element used in parsing. A single word or a single redirection.
This is an ephemeral construct. */
typedef struct element {
WORD_DESC *word;
REDIRECT *redirect;
} ELEMENT;
/* Possible values for command->flags. */
#define CMD_WANT_SUBSHELL 0x01 /* User wants a subshell: ( command ) */
#define CMD_FORCE_SUBSHELL 0x02 /* Shell needs to force a subshell. */
#define CMD_INVERT_RETURN 0x04 /* Invert the exit value. */
#define CMD_IGNORE_RETURN 0x08 /* Ignore the exit value. For set -e. */
#define CMD_NO_FUNCTIONS 0x10 /* Ignore functions during command lookup. */
#define CMD_INHIBIT_EXPANSION 0x20 /* Do not expand the command words. */
#define CMD_NO_FORK 0x40 /* Don't fork; just call execve */
#define CMD_TIME_PIPELINE 0x80 /* Time a pipeline */
#define CMD_TIME_POSIX 0x100 /* time -p; use POSIX.2 time output spec. */
#define CMD_AMPERSAND 0x200 /* command & */
#define CMD_STDIN_REDIR 0x400 /* async command needs implicit </dev/null */
#define CMD_COMMAND_BUILTIN 0x0800 /* command executed by `command' builtin */
#define CMD_COPROC_SUBSHELL 0x1000
/* What a command looks like. */
typedef struct command {
enum command_type type; /* FOR CASE WHILE IF CONNECTION or SIMPLE. */
int flags; /* Flags controlling execution environment. */
int line; /* line number the command starts on */
REDIRECT *redirects; /* Special redirects for FOR CASE, etc. */
union {
struct for_com *For;
struct case_com *Case;
struct while_com *While;
struct if_com *If;
struct connection *Connection;
struct simple_com *Simple;
struct function_def *Function_def;
struct group_com *Group;
#if defined (SELECT_COMMAND)
struct select_com *Select;
#endif
#if defined (DPAREN_ARITHMETIC)
struct arith_com *Arith;
#endif
#if defined (COND_COMMAND)
struct cond_com *Cond;
#endif
#if defined (ARITH_FOR_COMMAND)
struct arith_for_com *ArithFor;
#endif
struct subshell_com *Subshell;
struct coproc_com *Coproc;
} value;
} COMMAND;
/* Structure used to represent the CONNECTION type. */
typedef struct connection {
int ignore; /* Unused; simplifies make_command (). */
COMMAND *first; /* Pointer to the first command. */
COMMAND *second; /* Pointer to the second command. */
int connector; /* What separates this command from others. */
} CONNECTION;
/* Structures used to represent the CASE command. */
/* Values for FLAGS word in a PATTERN_LIST */
#define CASEPAT_FALLTHROUGH 0x01
#define CASEPAT_TESTNEXT 0x02
/* Pattern/action structure for CASE_COM. */
typedef struct pattern_list {
struct pattern_list *next; /* Clause to try in case this one failed. */
WORD_LIST *patterns; /* Linked list of patterns to test. */
COMMAND *action; /* Thing to execute if a pattern matches. */
int flags;
} PATTERN_LIST;
/* The CASE command. */
typedef struct case_com {
int flags; /* See description of CMD flags. */
int line; /* line number the `case' keyword appears on */
WORD_DESC *word; /* The thing to test. */
PATTERN_LIST *clauses; /* The clauses to test against, or NULL. */
} CASE_COM;
/* FOR command. */
typedef struct for_com {
int flags; /* See description of CMD flags. */
int line; /* line number the `for' keyword appears on */
WORD_DESC *name; /* The variable name to get mapped over. */
WORD_LIST *map_list; /* The things to map over. This is never NULL. */
COMMAND *action; /* The action to execute.
During execution, NAME is bound to successive
members of MAP_LIST. */
} FOR_COM;
#if defined (ARITH_FOR_COMMAND)
typedef struct arith_for_com {
int flags;
int line; /* generally used for error messages */
WORD_LIST *init;
WORD_LIST *test;
WORD_LIST *step;
COMMAND *action;
} ARITH_FOR_COM;
#endif
#if defined (SELECT_COMMAND)
/* KSH SELECT command. */
typedef struct select_com {
int flags; /* See description of CMD flags. */
int line; /* line number the `select' keyword appears on */
WORD_DESC *name; /* The variable name to get mapped over. */
WORD_LIST *map_list; /* The things to map over. This is never NULL. */
COMMAND *action; /* The action to execute.
During execution, NAME is bound to the member of
MAP_LIST chosen by the user. */
} SELECT_COM;
#endif /* SELECT_COMMAND */
/* IF command. */
typedef struct if_com {
int flags; /* See description of CMD flags. */
COMMAND *test; /* Thing to test. */
COMMAND *true_case; /* What to do if the test returned non-zero. */
COMMAND *false_case; /* What to do if the test returned zero. */
} IF_COM;
/* WHILE command. */
typedef struct while_com {
int flags; /* See description of CMD flags. */
COMMAND *test; /* Thing to test. */
COMMAND *action; /* Thing to do while test is non-zero. */
} WHILE_COM;
#if defined (DPAREN_ARITHMETIC)
/* The arithmetic evaluation command, ((...)). Just a set of flags and
a WORD_LIST, of which the first element is the only one used, for the
time being. */
typedef struct arith_com {
int flags;
int line;
WORD_LIST *exp;
} ARITH_COM;
#endif /* DPAREN_ARITHMETIC */
/* The conditional command, [[...]]. This is a binary tree -- we slippped
a recursive-descent parser into the YACC grammar to parse it. */
#define COND_AND 1
#define COND_OR 2
#define COND_UNARY 3
#define COND_BINARY 4
#define COND_TERM 5
#define COND_EXPR 6
typedef struct cond_com {
int flags;
int line;
int type;
WORD_DESC *op;
struct cond_com *left, *right;
} COND_COM;
/* The "simple" command. Just a collection of words and redirects. */
typedef struct simple_com {
int flags; /* See description of CMD flags. */
int line; /* line number the command starts on */
WORD_LIST *words; /* The program name, the arguments,
variable assignments, etc. */
REDIRECT *redirects; /* Redirections to perform. */
} SIMPLE_COM;
/* The "function definition" command. */
typedef struct function_def {
int flags; /* See description of CMD flags. */
int line; /* Line number the function def starts on. */
WORD_DESC *name; /* The name of the function. */
COMMAND *command; /* The parsed execution tree. */
char *source_file; /* file in which function was defined, if any */
} FUNCTION_DEF;
/* A command that is `grouped' allows pipes and redirections to affect all
commands in the group. */
typedef struct group_com {
int ignore; /* See description of CMD flags. */
COMMAND *command;
} GROUP_COM;
typedef struct subshell_com {
int flags;
COMMAND *command;
} SUBSHELL_COM;
#define COPROC_RUNNING 0x01
#define COPROC_DEAD 0x02
typedef struct coproc {
char *c_name;
pid_t c_pid;
int c_rfd;
int c_wfd;
int c_rsave;
int c_wsave;
int c_flags;
int c_status;
} Coproc;
typedef struct coproc_com {
int flags;
char *name;
COMMAND *command;
} COPROC_COM;
extern COMMAND *global_command;
extern Coproc sh_coproc;
/* Possible command errors */
#define CMDERR_DEFAULT 0
#define CMDERR_BADTYPE 1
#define CMDERR_BADCONN 2
#define CMDERR_BADJUMP 3
#define CMDERR_LAST 3
/* Forward declarations of functions declared in copy_cmd.c. */
extern FUNCTION_DEF *copy_function_def_contents __P((FUNCTION_DEF *, FUNCTION_DEF *));
extern FUNCTION_DEF *copy_function_def __P((FUNCTION_DEF *));
extern WORD_DESC *copy_word __P((WORD_DESC *));
extern WORD_LIST *copy_word_list __P((WORD_LIST *));
extern REDIRECT *copy_redirect __P((REDIRECT *));
extern REDIRECT *copy_redirects __P((REDIRECT *));
extern COMMAND *copy_command __P((COMMAND *));
#endif /* _COMMAND_H_ */
+3
View File
@@ -546,6 +546,9 @@
/* Define if you don't have vprintf but do have _doprnt. */
#undef HAVE_DOPRNT
/* Define if you have the dprintf function. */
#undef HAVE_DPRINTF
/* Define if you have the dup2 function. */
#undef HAVE_DUP2
+3
View File
@@ -994,6 +994,9 @@
/* Define if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
/* Define if you have the <ulimit.h> header file. */
#undef HAVE_ULIMIT_H
/* Define if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
Vendored
+2 -2
View File
@@ -1,5 +1,5 @@
#! /bin/sh
# From configure.in for Bash 4.1, version 4.020.
# From configure.in for Bash 4.1, version 4.021.
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.63 for bash 4.1-maint.
#
@@ -14334,7 +14334,7 @@ done
for ac_func in fdprintf
for ac_func in dprintf
do
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
+2 -2
View File
@@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_REVISION([for Bash 4.1, version 4.020])dnl
AC_REVISION([for Bash 4.1, version 4.021])dnl
define(bashvers, 4.1)
define(relstatus, maint)
@@ -739,7 +739,7 @@ AC_CHECK_FUNCS(getpwent getpwnam getpwuid)
AC_REPLACE_FUNCS(getcwd memset)
AC_REPLACE_FUNCS(strcasecmp strcasestr strerror strftime strnlen strpbrk strstr)
AC_REPLACE_FUNCS(strtod strtol strtoul strtoll strtoull strtoimax strtoumax)
AC_REPLACE_FUNCS(fdprintf)
AC_REPLACE_FUNCS(dprintf)
AC_CHECK_DECLS([confstr])
AC_CHECK_DECLS([printf])
+1 -1
View File
@@ -21,7 +21,7 @@ dnl Process this file with autoconf to produce a configure script.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
AC_REVISION([for Bash 4.1, version 4.019])dnl
AC_REVISION([for Bash 4.1, version 4.020])dnl
define(bashvers, 4.1)
define(relstatus, maint)
+26 -3
View File
@@ -112,6 +112,7 @@ extern pid_t last_command_subst_pid;
extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
extern char **subshell_argv, **subshell_envp;
extern int subshell_argc;
extern time_t shell_start_time;
#if 0
extern char *glob_argv_flags;
#endif
@@ -1182,7 +1183,7 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
int asynchronous, pipe_in, pipe_out;
struct fd_bitmap *fds_to_close;
{
int rv, posix_time, old_flags;
int rv, posix_time, old_flags, nullcmd;
time_t rs, us, ss;
int rsf, usf, ssf;
int cpu;
@@ -1218,6 +1219,22 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
posix_time = (command->flags & CMD_TIME_POSIX);
#if 0 /* XXX - bash-4.2 */
nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
if (posixly_correct && nullcmd)
{
#if defined (HAVE_GETRUSAGE)
selfb.ru_utime.tv_sec = kidsb.ru_utime.tv_sec = selfb.ru_stime.tv_sec = kidsb.ru_stime.tv_sec = 0;
selfb.ru_utime.tv_usec = kidsb.ru_utime.tv_usec = selfb.ru_stime.tv_usec = kidsb.ru_stime.tv_usec = 0;
before.tv_sec = shell_start_time;
before.tv_usec = 0;
#else
before.tms_utime = before.tms_stime = before.tms_cutime = before.tms_cstime = 0;
tbefore = shell_start_time;
#endif
}
#endif
old_flags = command->flags;
command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX);
rv = execute_command_internal (command, asynchronous, pipe_in, pipe_out, fds_to_close);
@@ -1271,8 +1288,14 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
if (posix_time)
time_format = POSIX_TIMEFORMAT;
else if ((time_format = get_string_value ("TIMEFORMAT")) == 0)
time_format = BASH_TIMEFORMAT;
{
#if 0 /* XXX - bash-4.2 */
if (posixly_correct && nullcmd)
time_format = "user\t%2lU\nsys\t%2lS";
else
#endif
time_format = BASH_TIMEFORMAT;
}
if (time_format && *time_format)
print_formatted_time (stderr, time_format, rs, rsf, us, usf, ss, ssf, cpu);
+23 -6
View File
@@ -112,7 +112,7 @@ extern pid_t last_command_subst_pid;
extern sh_builtin_func_t *last_shell_builtin, *this_shell_builtin;
extern char **subshell_argv, **subshell_envp;
extern int subshell_argc;
extern char *exec_argv0;
extern time_t shell_start_time;
#if 0
extern char *glob_argv_flags;
#endif
@@ -1183,7 +1183,7 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
int asynchronous, pipe_in, pipe_out;
struct fd_bitmap *fds_to_close;
{
int rv, posix_time, old_flags;
int rv, posix_time, old_flags, nullcmd;
time_t rs, us, ss;
int rsf, usf, ssf;
int cpu;
@@ -1219,6 +1219,20 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
posix_time = (command->flags & CMD_TIME_POSIX);
nullcmd = (command == 0) || (command->type == cm_simple && command->value.Simple->words == 0 && command->value.Simple->redirects == 0);
if (posixly_correct && nullcmd)
{
#if defined (HAVE_GETRUSAGE)
selfb.ru_utime.tv_sec = kidsb.ru_utime.tv_sec = selfb.ru_stime.tv_sec = kidsb.ru_stime.tv_sec = 0;
selfb.ru_utime.tv_usec = kidsb.ru_utime.tv_usec = selfb.ru_stime.tv_usec = kidsb.ru_stime.tv_usec = 0;
before.tv_sec = shell_start_time;
before.tv_usec = 0;
#else
before.tms_utime = before.tms_stime = before.tms_cutime = before.tms_cstime = 0;
tbefore = shell_start_time;
#endif
}
old_flags = command->flags;
command->flags &= ~(CMD_TIME_PIPELINE|CMD_TIME_POSIX);
rv = execute_command_internal (command, asynchronous, pipe_in, pipe_out, fds_to_close);
@@ -1272,8 +1286,12 @@ time_command (command, asynchronous, pipe_in, pipe_out, fds_to_close)
if (posix_time)
time_format = POSIX_TIMEFORMAT;
else if ((time_format = get_string_value ("TIMEFORMAT")) == 0)
time_format = BASH_TIMEFORMAT;
{
if (posixly_correct && nullcmd)
time_format = "user\t%2lU\nsys\t%2lS";
else
time_format = BASH_TIMEFORMAT;
}
if (time_format && *time_format)
print_formatted_time (stderr, time_format, rs, rsf, us, usf, ss, ssf, cpu);
@@ -4880,8 +4898,7 @@ shell_execve (command, args, env)
for (i = larray - 1; i; i--)
args[i] = args[i - 1];
args[0] = exec_argv0 ? shell_name : exec_argv0;
exec_argv0 = (char *)NULL;
args[0] = shell_name;
args[1] = command;
args[larray] = (char *)NULL;
+4 -2
View File
@@ -178,8 +178,10 @@ extern long get_clk_tck __P((void));
extern void clock_t_to_secs ();
extern void print_clock_t ();
/* Declarations for functions defined in lib/sh/fdprintf.c */
extern void fdprintf __P((int, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
/* Declarations for functions defined in lib/sh/dprintf.c */
#if !defined (HAVE_DPRINTF)
extern void dprintf __P((int, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
#endif
/* Declarations for functions defined in lib/sh/fmtulong.c */
#define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
+475
View File
@@ -0,0 +1,475 @@
/* externs.h -- extern function declarations which do not appear in their
own header file. */
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
/* 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. */
#define FUNC_MULTILINE 0x01
#define FUNC_EXTERNAL 0x02
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 void xtrace_init __P((void));
#ifdef NEED_XTRACE_SET_DECL
extern void xtrace_set __P((int, FILE *));
#endif
extern void xtrace_fdchk __P((int));
extern void xtrace_reset __P((void));
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 char *xparse_dolparen __P((char *, char *, int *, int));
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 void set_default_lang __P((void));
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((const 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/casemod.c */
extern char *sh_modcase __P((const char *, char *, int));
/* Defines for flags argument to sh_modcase. These need to agree with what's
in lib/sh/casemode.c */
#define CASE_LOWER 0x0001
#define CASE_UPPER 0x0002
#define CASE_CAPITALIZE 0x0004
#define CASE_UNCAP 0x0008
#define CASE_TOGGLE 0x0010
#define CASE_TOGGLEALL 0x0020
#define CASE_UPFIRST 0x0040
#define CASE_LOWFIRST 0x0080
#define CASE_USEWORDS 0x1000
/* 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/dprintf.c */
extern void dprintf __P((int, const char *, ...)) __attribute__((__format__ (printf, 2, 3)));
/* 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/fnxform.c */
extern char *fnx_fromfs __P((char *, size_t));
extern char *fnx_tofs __P((char *, size_t));
/* Declarations for functions defined in lib/sh/fpurge.c */
#if defined NEED_FPURGE_DECL
#if !HAVE_DECL_FPURGE
#if HAVE_FPURGE
# define fpurge _bash_fpurge
#endif
extern int fpurge __P((FILE *stream));
#endif /* HAVE_DECL_FPURGE */
#endif /* NEED_FPURGE_DECL */
/* 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/input_avail.c */
extern int input_avail __P((int));
/* 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
#define MP_IGNDOT 0x08
extern char *sh_makepath __P((const char *, const char *, int));
/* declarations for functions defined in lib/sh/mbscasecmp.c */
#if !defined (HAVE_MBSCASECMP)
extern char *mbscasecmp __P((const char *, const char *));
#endif
/* declarations for functions defined in lib/sh/mbschr.c */
#if !defined (HAVE_MBSCHR)
extern char *mbschr __P((const char *, int));
#endif
/* declarations for functions defined in lib/sh/mbscmp.c */
#if !defined (HAVE_MBSCMP)
extern char *mbscmp __P((const char *, const char *));
#endif
/* 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/shaccess.c */
extern int sh_eaccess __P((char *, int));
/* 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_mkdoublequoted __P((const char *, int, int));
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 *));
extern char *dirspell __P((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/strcasestr.c */
#if ! HAVE_STRCASESTR
extern char *strcasestr __P((const char *, const char *));
#endif
/* declarations for functions defined in lib/sh/strerror.c */
#if !defined (HAVE_STRERROR) && !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 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/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 **));
#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/uconvert.c */
extern int uconvert __P((char *, long *, long *));
/* declarations for functions defined in lib/sh/ufuncs.c */
extern unsigned int falarm __P((unsigned int, unsigned int));
extern unsigned int fsleep __P((unsigned int, unsigned int));
/* declarations for functions defined in lib/sh/winsize.c */
extern void get_new_window_size __P((int, int *, int *));
/* declarations for functions defined in lib/sh/zcatfd.c */
extern int zcatfd __P((int, int, char *));
/* declarations for functions defined in lib/sh/zgetline.c */
extern ssize_t zgetline __P((int, char **, size_t *, int));
/* declarations for functions defined in lib/sh/zmapfd.c */
extern int zmapfd __P((int, char **, char *));
/* declarations for functions defined in lib/sh/zread.c */
extern ssize_t zread __P((int, char *, size_t));
extern ssize_t zreadretry __P((int, char *, size_t));
extern ssize_t zreadintr __P((int, char *, size_t));
extern ssize_t zreadc __P((int, char *));
extern ssize_t zreadcintr __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_ */
+8 -3
View File
@@ -126,8 +126,12 @@ history_filename (filename)
if (home == 0)
{
#if 0
home = ".";
home_len = 1;
#else
return (NULL);
#endif
}
else
home_len = strlen (home);
@@ -179,7 +183,7 @@ read_history_range (filename, from, to)
buffer = last_ts = (char *)NULL;
input = history_filename (filename);
file = open (input, O_RDONLY|O_BINARY, 0666);
file = input ? open (input, O_RDONLY|O_BINARY, 0666) : -1;
if ((file < 0) || (fstat (file, &finfo) == -1))
goto error_and_exit;
@@ -314,7 +318,7 @@ history_truncate_file (fname, lines)
buffer = (char *)NULL;
filename = history_filename (fname);
file = open (filename, O_RDONLY|O_BINARY, 0666);
file = filename ? open (filename, O_RDONLY|O_BINARY, 0666) : -1;
rv = 0;
/* Don't try to truncate non-regular files. */
@@ -436,9 +440,10 @@ history_do_write (filename, nelements, overwrite)
mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
#endif
output = history_filename (filename);
file = output ? open (output, mode, 0600) : -1;
rv = 0;
if ((file = open (output, mode, 0600)) == -1)
if (file == -1)
{
FREE (output);
return (errno);
+547
View File
@@ -0,0 +1,547 @@
/* histfile.c - functions to manipulate the history file. */
/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
This file contains the GNU History Library (History), a set of
routines for managing the text of previously typed lines.
History is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
History 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 History. If not, see <http://www.gnu.org/licenses/>.
*/
/* The goal is to make the implementation transparent, so that you
don't have to know what data types are used, just what functions
you can call. I think I have done that. */
#define READLINE_LIBRARY
#if defined (__TANDEM)
# include <floss.h>
#endif
#if defined (HAVE_CONFIG_H)
# include <config.h>
#endif
#include <stdio.h>
#include <sys/types.h>
#if ! defined (_MINIX) && defined (HAVE_SYS_FILE_H)
# include <sys/file.h>
#endif
#include "posixstat.h"
#include <fcntl.h>
#if defined (HAVE_STDLIB_H)
# include <stdlib.h>
#else
# include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#include <ctype.h>
#if defined (__EMX__)
# undef HAVE_MMAP
#endif
#ifdef HISTORY_USE_MMAP
# include <sys/mman.h>
# ifdef MAP_FILE
# define MAP_RFLAGS (MAP_FILE|MAP_PRIVATE)
# define MAP_WFLAGS (MAP_FILE|MAP_SHARED)
# else
# define MAP_RFLAGS MAP_PRIVATE
# define MAP_WFLAGS MAP_SHARED
# endif
# ifndef MAP_FAILED
# define MAP_FAILED ((void *)-1)
# endif
#endif /* HISTORY_USE_MMAP */
/* If we're compiling for __EMX__ (OS/2) or __CYGWIN__ (cygwin32 environment
on win 95/98/nt), we want to open files with O_BINARY mode so that there
is no \n -> \r\n conversion performed. On other systems, we don't want to
mess around with O_BINARY at all, so we ensure that it's defined to 0. */
#if defined (__EMX__) || defined (__CYGWIN__)
# ifndef O_BINARY
# define O_BINARY 0
# endif
#else /* !__EMX__ && !__CYGWIN__ */
# undef O_BINARY
# define O_BINARY 0
#endif /* !__EMX__ && !__CYGWIN__ */
#include <errno.h>
#if !defined (errno)
extern int errno;
#endif /* !errno */
#include "history.h"
#include "histlib.h"
#include "rlshell.h"
#include "xmalloc.h"
/* If non-zero, we write timestamps to the history file in history_do_write() */
int history_write_timestamps = 0;
/* Does S look like the beginning of a history timestamp entry? Placeholder
for more extensive tests. */
#define HIST_TIMESTAMP_START(s) (*(s) == history_comment_char && isdigit ((s)[1]) )
/* Return the string that should be used in the place of this
filename. This only matters when you don't specify the
filename to read_history (), or write_history (). */
static char *
history_filename (filename)
const char *filename;
{
char *return_val;
const char *home;
int home_len;
return_val = filename ? savestring (filename) : (char *)NULL;
if (return_val)
return (return_val);
home = sh_get_env_value ("HOME");
if (home == 0)
{
home = ".";
home_len = 1;
}
else
home_len = strlen (home);
return_val = (char *)xmalloc (2 + home_len + 8); /* strlen(".history") == 8 */
strcpy (return_val, home);
return_val[home_len] = '/';
#if defined (__MSDOS__)
strcpy (return_val + home_len + 1, "_history");
#else
strcpy (return_val + home_len + 1, ".history");
#endif
return (return_val);
}
/* Add the contents of FILENAME to the history list, a line at a time.
If FILENAME is NULL, then read from ~/.history. Returns 0 if
successful, or errno if not. */
int
read_history (filename)
const char *filename;
{
return (read_history_range (filename, 0, -1));
}
/* Read a range of lines from FILENAME, adding them to the history list.
Start reading at the FROM'th line and end at the TO'th. If FROM
is zero, start at the beginning. If TO is less than FROM, read
until the end of the file. If FILENAME is NULL, then read from
~/.history. Returns 0 if successful, or errno if not. */
int
read_history_range (filename, from, to)
const char *filename;
int from, to;
{
register char *line_start, *line_end, *p;
char *input, *buffer, *bufend, *last_ts;
int file, current_line, chars_read;
struct stat finfo;
size_t file_size;
#if defined (EFBIG)
int overflow_errno = EFBIG;
#elif defined (EOVERFLOW)
int overflow_errno = EOVERFLOW;
#else
int overflow_errno = EIO;
#endif
buffer = last_ts = (char *)NULL;
input = history_filename (filename);
file = open (input, O_RDONLY|O_BINARY, 0666);
if ((file < 0) || (fstat (file, &finfo) == -1))
goto error_and_exit;
file_size = (size_t)finfo.st_size;
/* check for overflow on very large files */
if (file_size != finfo.st_size || file_size + 1 < file_size)
{
errno = overflow_errno;
goto error_and_exit;
}
#ifdef HISTORY_USE_MMAP
/* We map read/write and private so we can change newlines to NULs without
affecting the underlying object. */
buffer = (char *)mmap (0, file_size, PROT_READ|PROT_WRITE, MAP_RFLAGS, file, 0);
if ((void *)buffer == MAP_FAILED)
{
errno = overflow_errno;
goto error_and_exit;
}
chars_read = file_size;
#else
buffer = (char *)malloc (file_size + 1);
if (buffer == 0)
{
errno = overflow_errno;
goto error_and_exit;
}
chars_read = read (file, buffer, file_size);
#endif
if (chars_read < 0)
{
error_and_exit:
if (errno != 0)
chars_read = errno;
else
chars_read = EIO;
if (file >= 0)
close (file);
FREE (input);
#ifndef HISTORY_USE_MMAP
FREE (buffer);
#endif
return (chars_read);
}
close (file);
/* Set TO to larger than end of file if negative. */
if (to < 0)
to = chars_read;
/* Start at beginning of file, work to end. */
bufend = buffer + chars_read;
current_line = 0;
/* Skip lines until we are at FROM. */
for (line_start = line_end = buffer; line_end < bufend && current_line < from; line_end++)
if (*line_end == '\n')
{
p = line_end + 1;
/* If we see something we think is a timestamp, continue with this
line. We should check more extensively here... */
if (HIST_TIMESTAMP_START(p) == 0)
current_line++;
line_start = p;
}
/* If there are lines left to gobble, then gobble them now. */
for (line_end = line_start; line_end < bufend; line_end++)
if (*line_end == '\n')
{
/* Change to allow Windows-like \r\n end of line delimiter. */
if (line_end > line_start && line_end[-1] == '\r')
line_end[-1] = '\0';
else
*line_end = '\0';
if (*line_start)
{
if (HIST_TIMESTAMP_START(line_start) == 0)
{
add_history (line_start);
if (last_ts)
{
add_history_time (last_ts);
last_ts = NULL;
}
}
else
{
last_ts = line_start;
current_line--;
}
}
current_line++;
if (current_line >= to)
break;
line_start = line_end + 1;
}
FREE (input);
#ifndef HISTORY_USE_MMAP
FREE (buffer);
#else
munmap (buffer, file_size);
#endif
return (0);
}
/* Truncate the history file FNAME, leaving only LINES trailing lines.
If FNAME is NULL, then use ~/.history. Returns 0 on success, errno
on failure. */
int
history_truncate_file (fname, lines)
const char *fname;
int lines;
{
char *buffer, *filename, *bp, *bp1; /* bp1 == bp+1 */
int file, chars_read, rv;
struct stat finfo;
size_t file_size;
buffer = (char *)NULL;
filename = history_filename (fname);
file = open (filename, O_RDONLY|O_BINARY, 0666);
rv = 0;
/* Don't try to truncate non-regular files. */
if (file == -1 || fstat (file, &finfo) == -1)
{
rv = errno;
if (file != -1)
close (file);
goto truncate_exit;
}
if (S_ISREG (finfo.st_mode) == 0)
{
close (file);
#ifdef EFTYPE
rv = EFTYPE;
#else
rv = EINVAL;
#endif
goto truncate_exit;
}
file_size = (size_t)finfo.st_size;
/* check for overflow on very large files */
if (file_size != finfo.st_size || file_size + 1 < file_size)
{
close (file);
#if defined (EFBIG)
rv = errno = EFBIG;
#elif defined (EOVERFLOW)
rv = errno = EOVERFLOW;
#else
rv = errno = EINVAL;
#endif
goto truncate_exit;
}
buffer = (char *)malloc (file_size + 1);
if (buffer == 0)
{
close (file);
goto truncate_exit;
}
chars_read = read (file, buffer, file_size);
close (file);
if (chars_read <= 0)
{
rv = (chars_read < 0) ? errno : 0;
goto truncate_exit;
}
/* Count backwards from the end of buffer until we have passed
LINES lines. bp1 is set funny initially. But since bp[1] can't
be a comment character (since it's off the end) and *bp can't be
both a newline and the history comment character, it should be OK. */
for (bp1 = bp = buffer + chars_read - 1; lines && bp > buffer; bp--)
{
if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
lines--;
bp1 = bp;
}
/* If this is the first line, then the file contains exactly the
number of lines we want to truncate to, so we don't need to do
anything. It's the first line if we don't find a newline between
the current value of i and 0. Otherwise, write from the start of
this line until the end of the buffer. */
for ( ; bp > buffer; bp--)
{
if (*bp == '\n' && HIST_TIMESTAMP_START(bp1) == 0)
{
bp++;
break;
}
bp1 = bp;
}
/* Write only if there are more lines in the file than we want to
truncate to. */
if (bp > buffer && ((file = open (filename, O_WRONLY|O_TRUNC|O_BINARY, 0600)) != -1))
{
write (file, bp, chars_read - (bp - buffer));
#if defined (__BEOS__)
/* BeOS ignores O_TRUNC. */
ftruncate (file, chars_read - (bp - buffer));
#endif
close (file);
}
truncate_exit:
FREE (buffer);
free (filename);
return rv;
}
/* Workhorse function for writing history. Writes NELEMENT entries
from the history list to FILENAME. OVERWRITE is non-zero if you
wish to replace FILENAME with the entries. */
static int
history_do_write (filename, nelements, overwrite)
const char *filename;
int nelements, overwrite;
{
register int i;
char *output;
int file, mode, rv;
#ifdef HISTORY_USE_MMAP
size_t cursize;
mode = overwrite ? O_RDWR|O_CREAT|O_TRUNC|O_BINARY : O_RDWR|O_APPEND|O_BINARY;
#else
mode = overwrite ? O_WRONLY|O_CREAT|O_TRUNC|O_BINARY : O_WRONLY|O_APPEND|O_BINARY;
#endif
output = history_filename (filename);
rv = 0;
if ((file = open (output, mode, 0600)) == -1)
{
FREE (output);
return (errno);
}
#ifdef HISTORY_USE_MMAP
cursize = overwrite ? 0 : lseek (file, 0, SEEK_END);
#endif
if (nelements > history_length)
nelements = history_length;
/* Build a buffer of all the lines to write, and write them in one syscall.
Suggested by Peter Ho (peter@robosts.oxford.ac.uk). */
{
HIST_ENTRY **the_history; /* local */
register int j;
int buffer_size;
char *buffer;
the_history = history_list ();
/* Calculate the total number of bytes to write. */
for (buffer_size = 0, i = history_length - nelements; i < history_length; i++)
#if 0
buffer_size += 2 + HISTENT_BYTES (the_history[i]);
#else
{
if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
buffer_size += strlen (the_history[i]->timestamp) + 1;
buffer_size += strlen (the_history[i]->line) + 1;
}
#endif
/* Allocate the buffer, and fill it. */
#ifdef HISTORY_USE_MMAP
if (ftruncate (file, buffer_size+cursize) == -1)
goto mmap_error;
buffer = (char *)mmap (0, buffer_size, PROT_READ|PROT_WRITE, MAP_WFLAGS, file, cursize);
if ((void *)buffer == MAP_FAILED)
{
mmap_error:
rv = errno;
FREE (output);
close (file);
return rv;
}
#else
buffer = (char *)malloc (buffer_size);
if (buffer == 0)
{
rv = errno;
FREE (output);
close (file);
return rv;
}
#endif
for (j = 0, i = history_length - nelements; i < history_length; i++)
{
if (history_write_timestamps && the_history[i]->timestamp && the_history[i]->timestamp[0])
{
strcpy (buffer + j, the_history[i]->timestamp);
j += strlen (the_history[i]->timestamp);
buffer[j++] = '\n';
}
strcpy (buffer + j, the_history[i]->line);
j += strlen (the_history[i]->line);
buffer[j++] = '\n';
}
#ifdef HISTORY_USE_MMAP
if (msync (buffer, buffer_size, 0) != 0 || munmap (buffer, buffer_size) != 0)
rv = errno;
#else
if (write (file, buffer, buffer_size) < 0)
rv = errno;
free (buffer);
#endif
}
close (file);
FREE (output);
return (rv);
}
/* Append NELEMENT entries to FILENAME. The entries appended are from
the end of the list minus NELEMENTs up to the end of the list. */
int
append_history (nelements, filename)
int nelements;
const char *filename;
{
return (history_do_write (filename, nelements, HISTORY_APPEND));
}
/* Overwrite FILENAME with the current history. If FILENAME is NULL,
then write the history list to ~/.history. Values returned
are as in read_history ().*/
int
write_history (filename)
const char *filename;
{
return (history_do_write (filename, history_length, HISTORY_OVERWRITE));
}
+5 -5
View File
@@ -91,7 +91,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
strtoll.c strtoull.c strtoimax.c strtoumax.c memset.c strstr.c \
mktime.c strftime.c mbschr.c zcatfd.c zmapfd.c winsize.c eaccess.c \
wcsdup.c fpurge.c zgetline.c mbscmp.c uconvert.c ufuncs.c \
casemod.c fdprintf.c input_avail.c mbscasecmp.c fnxform.c
casemod.c dprintf.c input_avail.c mbscasecmp.c fnxform.c
# The header files for this library.
HSOURCES =
@@ -105,7 +105,7 @@ OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
strtrans.o snprintf.o mailstat.o fmtulong.o \
fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \
fpurge.o zgetline.o mbscmp.o uconvert.o ufuncs.o casemod.o \
fdprintf.o input_avail.o mbscasecmp.o fnxform.o ${LIBOBJS}
input_avail.o mbscasecmp.o fnxform.o ${LIBOBJS}
SUPPORT = Makefile
@@ -144,7 +144,7 @@ casemod.o: casemod.c
clktck.o: clktck.c
clock.o: clock.c
eaccess.o: eaccess.c
fdprintf.o: fdprintf.c
dprintf.o: dprintf.c
fmtullong.o: fmtullong.c
fmtulong.o: fmtulong.c
fmtumax.o: fmtumax.c
@@ -214,7 +214,7 @@ casemod.o: ${BUILD_DIR}/config.h
clktck.o: ${BUILD_DIR}/config.h
clock.o: ${BUILD_DIR}/config.h
eaccess.o: ${BUILD_DIR}/config.h
fdprintf.o: ${BUILD_DIR}/config.h
dprintf.o: ${BUILD_DIR}/config.h
fmtullong.o: ${BUILD_DIR}/config.h
fmtulong.o: ${BUILD_DIR}/config.h
fmtumax.o: ${BUILD_DIR}/config.h
@@ -529,7 +529,7 @@ casemod.o: ${topdir}/bashtypes.h
casemod.o: ${BASHINCDIR}/shmbutil.h
casemod.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
fdprintf.o: ${BASHINCDIR}/stdc.h
dprintf.o: ${BASHINCDIR}/stdc.h
input_avail.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
input_avail.o: ${BASHINCDIR}/stdc.h
+544
View File
@@ -0,0 +1,544 @@
#
# Makefile for the Bash library
#
#
# Copyright (C) 1998-2009 Free Software Foundation, Inc.
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
PACKAGE = @PACKAGE_NAME@
VERSION = @PACKAGE_VERSION@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_VERSION = @PACKAGE_VERSION@
srcdir = @srcdir@
VPATH = .:@srcdir@
topdir = @top_srcdir@
BUILD_DIR = @BUILD_DIR@
LIBBUILD = ${BUILD_DIR}/lib
BASHINCDIR = ${topdir}/include
INTL_LIBSRC = ${topdir}/lib/intl
INTL_BUILDDIR = ${LIBBUILD}/intl
INTL_INC = @INTL_INC@
LIBINTL_H = @LIBINTL_H@
datarootdir = @datarootdir@
INSTALL = @INSTALL@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_DATA = @INSTALL_DATA@
CC = @CC@
RANLIB = @RANLIB@
AR = @AR@
ARFLAGS = @ARFLAGS@
RM = rm -f
CP = cp
MV = mv
SHELL = @MAKE_SHELL@
CFLAGS = @CFLAGS@
LOCAL_CFLAGS = @LOCAL_CFLAGS@ ${DEBUG}
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@ @LOCAL_LDFLAGS@
PROFILE_FLAGS = @PROFILE_FLAGS@
DEFS = @DEFS@
LOCAL_DEFS = @LOCAL_DEFS@
INCLUDES = -I. -I../.. -I$(topdir) -I$(topdir)/lib -I$(BASHINCDIR) -I$(srcdir) $(INTL_INC)
CCFLAGS = ${PROFILE_FLAGS} ${INCLUDES} $(DEFS) $(LOCAL_DEFS) $(LOCAL_CFLAGS) \
$(CFLAGS) $(CPPFLAGS)
GCC_LINT_FLAGS = -Wall -Wshadow -Wpointer-arith -Wcast-qual \
-Wcast-align -Wstrict-prototypes -Wconversion \
-Wmissing-prototypes -Wtraditional -Wredundant-decls -pedantic
.c.o:
$(CC) -c $(CCFLAGS) $<
# The name of the library target.
LIBRARY_NAME = libsh.a
# The C code source files for this library.
CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \
strcasecmp.c strerror.c strtod.c strtol.c strtoul.c \
vprint.c itos.c rename.c zread.c zwrite.c shtty.c \
inet_aton.c netconn.c netopen.c strpbrk.c timeval.c makepath.c \
pathcanon.c pathphys.c tmpfile.c stringlist.c stringvec.c spell.c \
shquote.c strtrans.c strcasestr.c snprintf.c mailstat.c \
fmtulong.c fmtullong.c fmtumax.c shmatch.c strnlen.c \
strtoll.c strtoull.c strtoimax.c strtoumax.c memset.c strstr.c \
mktime.c strftime.c mbschr.c zcatfd.c zmapfd.c winsize.c eaccess.c \
wcsdup.c fpurge.c zgetline.c mbscmp.c uconvert.c ufuncs.c \
casemod.c dprintf.c input_avail.c mbscasecmp.c fnxform.c
# The header files for this library.
HSOURCES =
# The object files contained in $(LIBRARY_NAME)
LIBOBJS = @LIBOBJS@
OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.o \
itos.o zread.o zwrite.o shtty.o shmatch.o eaccess.o \
netconn.o netopen.o timeval.o makepath.o pathcanon.o \
pathphys.o tmpfile.o stringlist.o stringvec.o spell.o shquote.o \
strtrans.o snprintf.o mailstat.o fmtulong.o \
fmtullong.o fmtumax.o zcatfd.o zmapfd.o winsize.o wcsdup.o \
fpurge.o zgetline.o mbscmp.o uconvert.o ufuncs.o casemod.o \
input_avail.o mbscasecmp.o fnxform.o ${LIBOBJS}
SUPPORT = Makefile
all: $(LIBRARY_NAME)
$(LIBRARY_NAME): $(OBJECTS)
$(RM) $@
$(AR) $(ARFLAGS) $@ $(OBJECTS)
-test -n "$(RANLIB)" && $(RANLIB) $@
force:
# The rule for 'includes' is written funny so that the if statement
# always returns TRUE unless there really was an error installing the
# include files.
install:
clean:
$(RM) $(OBJECTS) $(LIBRARY_NAME)
realclean distclean maintainer-clean: clean
$(RM) Makefile
mostlyclean: clean
# Dependencies
${BUILD_DIR}/version.h: ${BUILD_DIR}/config.h ${BUILD_DIR}/Makefile Makefile
-( cd ${BUILD_DIR} && ${MAKE} ${MFLAGS} version.h )
${BUILD_DIR}/pathnames.h: ${BUILD_DIR}/config.h ${BUILD_DIR}/Makefile Makefile
-( cd ${BUILD_DIR} && ${MAKE} ${MFLAGS} pathnames.h )
# rules for losing makes, like SunOS
casemod.o: casemod.c
clktck.o: clktck.c
clock.o: clock.c
eaccess.o: eaccess.c
fdprintf.o: fdprintf.c
fmtullong.o: fmtullong.c
fmtulong.o: fmtulong.c
fmtumax.o: fmtumax.c
fnxform.o: fnxform.c
fpurge.o: fpurge.c
getcwd.o: getcwd.c
getenv.o: getenv.c
inet_aton.o: inet_aton.c
input_avail.o: input_avail.c
itos.o: itos.c
mailstat.o: mailstat.c
makepath.o: makepath.c
mbscasecmp.o: mbscasecmp.c
mbscmp.o: mbscmp.c
memset.o: memset.c
mktime.o: mktime.c
netconn.o: netconn.c
netopen.o: netopen.c
oslib.o: oslib.c
pathcanon.o: pathcanon.c
pathphys.o: pathphys.c
rename.o: rename.c
setlinebuf.o: setlinebuf.c
shquote.o: shquote.c
shtty.o: shtty.c
snprintf.o: snprintf.c
spell.o: spell.c
strcasecmp.o: strcasecmp.c
strerror.o: strerror.c
strftime.o: strftime.c
strcasestr.o: strcasestr.c
stringlist.o: stringlist.c
stringvec.o: stringvec.c
strnlen.o: strnlen.c
strpbrk.o: strpbrk.c
strtod.o: strtod.c
strtoimax.o: strtoimax.c
strtol.o: strtol.c
strtoll.o: strtoll.c
strtoul.o: strtoul.c
strtoull.o: strtoull.c
strtoumax.o: strtoumax.c
strtrans.o: strtrans.c
times.o: times.c
timeval.o: timeval.c
tmpfile.o: tmpfile.c
uconvert.o: uconvert.c
ufuncs.o: ufuncs.c
vprint.o: vprint.c
wcsdup.o: wcsdup.c
mbschr.o: mbschr.c
zcatfd.o: zcatfd.c
zmapfd.o: zmapfd.c
zgetline.o: zgetline.c
zread.o: zread.c
zwrite.o: zwrite.c
# dependencies for c files that include other c files
fmtullong.o: fmtulong.c
fmtumax.o: fmtulong.c
strtoll.o: strtol.c
strtoul.o: strtol.c
strtoull.o: strtol.c
# all files in the library depend on config.h
casemod.o: ${BUILD_DIR}/config.h
clktck.o: ${BUILD_DIR}/config.h
clock.o: ${BUILD_DIR}/config.h
eaccess.o: ${BUILD_DIR}/config.h
fdprintf.o: ${BUILD_DIR}/config.h
fmtullong.o: ${BUILD_DIR}/config.h
fmtulong.o: ${BUILD_DIR}/config.h
fmtumax.o: ${BUILD_DIR}/config.h
fnxform.o: ${BUILD_DIR}/config.h
fpurge.o: ${BUILD_DIR}/config.h
getcwd.o: ${BUILD_DIR}/config.h
getenv.o: ${BUILD_DIR}/config.h
inet_aton.o: ${BUILD_DIR}/config.h
input_avail.o: ${BUILD_DIR}/config.h
itos.o: ${BUILD_DIR}/config.h
mailstat.o: ${BUILD_DIR}/config.h
makepath.o: ${BUILD_DIR}/config.h
mbscasecmp.o: ${BUILD_DIR}/config.h
mbscmp.o: ${BUILD_DIR}/config.h
memset.o: ${BUILD_DIR}/config.h
mktime.o: ${BUILD_DIR}/config.h
netconn.o: ${BUILD_DIR}/config.h
netopen.o: ${BUILD_DIR}/config.h
oslib.o: ${BUILD_DIR}/config.h
pathcanon.o: ${BUILD_DIR}/config.h
pathphys.o: ${BUILD_DIR}/config.h
rename.o: ${BUILD_DIR}/config.h
setlinebuf.o: ${BUILD_DIR}/config.h
shquote.o: ${BUILD_DIR}/config.h
shtty.o: ${BUILD_DIR}/config.h
snprintf.o: ${BUILD_DIR}/config.h
spell.o: ${BUILD_DIR}/config.h
strcasecmp.o: ${BUILD_DIR}/config.h
strerror.o: ${BUILD_DIR}/config.h
strftime.o: ${BUILD_DIR}/config.h
strcasestr.o: ${BUILD_DIR}/config.h
stringlist.o: ${BUILD_DIR}/config.h
stringvec.o: ${BUILD_DIR}/config.h
strnlen.o: ${BUILD_DIR}/config.h
strpbrk.o: ${BUILD_DIR}/config.h
strtod.o: ${BUILD_DIR}/config.h
strtoimax.o: ${BUILD_DIR}/config.h
strtol.o: ${BUILD_DIR}/config.h
strtoll.o: ${BUILD_DIR}/config.h
strtoul.o: ${BUILD_DIR}/config.h
strtoull.o: ${BUILD_DIR}/config.h
strtoumax.o: ${BUILD_DIR}/config.h
strtrans.o: ${BUILD_DIR}/config.h
times.o: ${BUILD_DIR}/config.h
timeval.o: ${BUILD_DIR}/config.h
tmpfile.o: ${BUILD_DIR}/config.h
uconvert.o: ${BUILD_DIR}/config.h
ufuncs.o: ${BUILD_DIR}/config.h
vprint.o: ${BUILD_DIR}/config.h
wcsdup.o: ${BUILD_DIR}/config.h
mbschr.o: ${BUILD_DIR}/config.h
zcatfd.o: ${BUILD_DIR}/config.h
zgetline.o: ${BUILD_DIR}/config.h
zmapfd.o: ${BUILD_DIR}/config.h
zread.o: ${BUILD_DIR}/config.h
zwrite.o: ${BUILD_DIR}/config.h
clktck.o: ${topdir}/bashtypes.h
getcwd.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
getcwd.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/posixdir.h
getcwd.o: ${BASHINCDIR}/memalloc.h ${BASHINCDIR}/ansi_stdlib.h
getenv.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
getenv.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
getenv.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
getenv.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
getenv.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
getenv.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
getenv.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
getenv.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h
getenv.o: ${BUILD_DIR}/version.h
inet_aton.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
inet_aton.o: ${BASHINCDIR}/stdc.h
itos.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
itos.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
itos.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
itos.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
itos.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
itos.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
itos.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
itos.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
makepath.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
makepath.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
makepath.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
makepath.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
makepath.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
makepath.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
makepath.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
makepath.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
netconn.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
netconn.o: ${topdir}/bashtypes.h
netopen.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
netopen.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
netopen.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
netopen.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
netopen.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
netopen.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
netopen.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
netopen.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
netopen.o: ${topdir}/bashintl.h ${LIBINTL_H} $(BASHINCDIR)/gettext.h
oslib.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
oslib.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
oslib.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
oslib.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
oslib.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
oslib.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
oslib.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
oslib.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
oslib.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
oslib.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
pathcanon.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
pathcanon.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
pathcanon.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
pathcanon.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
pathcanon.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
pathcanon.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
pathcanon.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
pathcanon.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
pathcanon.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
pathcanon.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
pathphys.o: ${topdir}/bashtypes.h ${topdir}/bashansi.h ${BASHINCDIR}/maxpath.h
pathphys.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
pathphys.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
pathphys.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
pathphys.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
pathphys.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
pathphys.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
pathphys.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
pathphys.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/filecntl.h
pathphys.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
rename.o: ${topdir}/bashtypes.h ${BASHINCDIR}/stdc.h
rename.o: ${BASHINCDIR}/posixstat.h
setlinebuf.o: ${topdir}/xmalloc.h ${topdir}/bashansi.h
setlinebuf.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/stdc.h
eaccess.o: ${topdir}/bashtypes.h
eaccess.o: ${BASHINCDIR}/posixstat.h
eaccess.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
eaccess.o: ${BASHINCDIR}/filecntl.h
eaccess.o: ${BASHINCDIR}/stdc.h
eaccess.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
eaccess.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
eaccess.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
eaccess.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
eaccess.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
eaccess.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
eaccess.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
shquote.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
shquote.o: ${BASHINCDIR}/ansi_stdlib.h ${topdir}/xmalloc.h
shtty.o: ${BASHINCDIR}/shtty.h
shtty.o: ${BASHINCDIR}/stdc.h
snprintf.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h ${topdir}/xmalloc.h
snprintf.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
snprintf.o: ${BASHINCDIR}/typemax.h
spell.o: ${topdir}/bashtypes.h
spell.o: ${BASHINCDIR}/posixstat.h ${BASHINCDIR}/posixdir.h
spell.o: ${BASHINCDIR}/ansi_stdlib.h
strcasecmp.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
strcasecmp.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strerror.o: ${topdir}/bashtypes.h
strerror.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
strerror.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
strerror.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
strerror.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
strerror.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
strerror.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
strerror.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
strcasestr.o: ${BASHINCDIR}/stdc.h ${topdir}/bashansi.h
strcasestr.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
stringlist.o: ${topdir}/bashansi.h
stringlist.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
stringlist.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
stringlist.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
stringlist.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
stringlist.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
stringlist.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
stringlist.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
stringvec.o: ${topdir}/bashansi.h ${BASHINCDIR}/chartypes.h
stringvec.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
stringvec.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
stringvec.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
stringvec.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
stringvec.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
stringvec.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
stringvec.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
strnlen.o: ${BASHINCDIR}/stdc.h
strpbrk.o: ${BASHINCDIR}/stdc.h
strtod.o: ${topdir}/bashansi.h
strtod.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtoimax.o: ${BASHINCDIR}/stdc.h
strtol.o: ${topdir}/bashansi.h
strtol.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtol.o: ${BASHINCDIR}/typemax.h
strtoll.o: ${topdir}/bashansi.h
strtoll.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtoll.o: ${BASHINCDIR}/typemax.h
strtoul.o: ${topdir}/bashansi.h
strtoul.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtoul.o: ${BASHINCDIR}/typemax.h
strtoull.o: ${topdir}/bashansi.h
strtoull.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtoull.o: ${BASHINCDIR}/typemax.h
strtoumax.o: ${BASHINCDIR}/stdc.h
strtrans.o: ${topdir}/bashansi.h
strtrans.o: ${BASHINCDIR}/ansi_stdlib.h ${BASHINCDIR}/chartypes.h
strtrans.o: ${topdir}/shell.h ${topdir}/syntax.h ${topdir}/bashjmp.h ${BASHINCDIR}/posixjmp.h
strtrans.o: ${topdir}/command.h ${BASHINCDIR}/stdc.h ${topdir}/error.h
strtrans.o: ${topdir}/general.h ${topdir}/bashtypes.h ${topdir}/variables.h ${topdir}/conftypes.h
strtrans.o: ${topdir}/array.h ${topdir}/hashlib.h ${topdir}/quit.h
strtrans.o: ${topdir}/unwind_prot.h ${topdir}/dispose_cmd.h
strtrans.o: ${topdir}/make_cmd.h ${topdir}/subst.h ${topdir}/sig.h
strtrans.o: ${BUILD_DIR}/pathnames.h ${topdir}/externs.h ${BUILD_DIR}/version.h
times.o: ${BASHINCDIR}/systimes.h
times.o: ${BASHINCDIR}/posixtime.h
timeval.o: ${BASHINCDIR}/posixtime.h
tmpfile.o: ${topdir}/bashtypes.h
tmpfile.o: ${BASHINCDIR}/posixstat.h
tmpfile.o: ${BASHINCDIR}/filecntl.h
uconvert.o: ${topdir}/bashtypes.h
ufuncs.o: ${topdir}/bashtypes.h
clock.o: ${BASHINCDIR}/posixtime.h
mailstat.o: ${topdir}/bashansi.h
mailstat.o: ${topdir}/bashtypes.h
mailstat.o: ${BASHINCDIR}/ansi_stdlib.h
mailstat.o: ${BASHINCDIR}/posixstat.h
mailstat.o: ${BASHINCDIR}/posixdir.h
mailstat.o: ${BASHINCDIR}/maxpath.h
fmtulong.o: ${topdir}/bashansi.h
fmtulong.o: ${BASHINCDIR}/ansi_stdlib.h
fmtulong.o: ${BASHINCDIR}/chartypes.h
fmtulong.o: ${BASHINCDIR}/stdc.h
fmtulong.o: ${BASHINCDIR}/typemax.h
fmtulong.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
fmtullong.o: ${topdir}/bashansi.h
fmtullong.o: ${BASHINCDIR}/ansi_stdlib.h
fmtullong.o: ${BASHINCDIR}/chartypes.h
fmtullong.o: ${BASHINCDIR}/stdc.h
fmtullong.o: ${BASHINCDIR}/typemax.h
fmtullong.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
fmtumax.o: ${topdir}/bashansi.h
fmtumax.o: ${BASHINCDIR}/ansi_stdlib.h
fmtumax.o: ${BASHINCDIR}/chartypes.h
fmtumax.o: ${BASHINCDIR}/stdc.h
fmtumax.o: ${BASHINCDIR}/typemax.h
fmtumax.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
wcsdup.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
wcsdup.o: ${BASHINCDIR}/stdc.h
wcsdup.o: ${topdir}/xmalloc.h
mbschr.o: ${topdir}/bashansi.h
mbschr.o: ${BASHINCDIR}/ansi_stdlib.h
mbschr.o: ${BASHINCDIR}/shmbutil.h
zgetline.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
zgetline.o: ${BASHINCDIR}/stdc.h
zgetline.o: ${topdir}/xmalloc.h
zgetline.o: ${topdir}/bashtypes.h
mbscasecmp.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
mbscasecmp.o: ${BASHINCDIR}/stdc.h
mbscasecmp.o: ${topdir}/xmalloc.h
mbscmp.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
mbscmp.o: ${BASHINCDIR}/stdc.h
mbscmp.o: ${topdir}/xmalloc.h
casemod.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
casemod.o: ${BASHINCDIR}/stdc.h
casemod.o: ${topdir}/xmalloc.h
casemod.o: ${topdir}/bashtypes.h
casemod.o: ${BASHINCDIR}/shmbutil.h
casemod.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
fdprintf.o: ${BASHINCDIR}/stdc.h
input_avail.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
input_avail.o: ${BASHINCDIR}/stdc.h
input_avail.o: ${topdir}/xmalloc.h ${BASHINCDIR}/posixselect.h
mktime.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
mktime.o: ${BASHINCDIR}/stdc.h
fnxform.o: ${topdir}/bashansi.h ${BASHINCDIR}/ansi_stdlib.h
fnxform.o: ${BASHINCDIR}/stdc.h
fnxform.o: ${topdir}/bashtypes.h
fnxform.o: ${topdir}/bashintl.h ${LIBINTL_H} ${BASHINCDIR}/gettext.h
+70
View File
@@ -0,0 +1,70 @@
/* dprintf -- printf to a file descriptor */
/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdc.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (PREFER_STDARG)
# include <stdarg.h>
#else
# include <varargs.h>
#endif
#include <stdio.h>
int
#if defined (PREFER_STDARG)
dprintf(int fd, const char *format, ...)
#else
dprintf(fd, format, va_alist)
int fd;
const char *format;
va_dcl
#endif
{
FILE *fp;
int fd2, rc, r2;
va_list args;
if ((fd2 = dup(fd)) < 0)
return -1;
fp = fdopen (fd2, "w");
if (fp == 0)
{
close (fd2);
return -1;
}
SH_VA_START (args, format);
rc = vfprintf (fp, format, args);
fflush (fp);
va_end (args);
r2 = fclose (fp); /* check here */
return rc;
}
+70
View File
@@ -0,0 +1,70 @@
/* fdprintf -- printf to a file descriptor */
/* Copyright (C) 2008,2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdc.h>
#if defined (HAVE_UNISTD_H)
# include <unistd.h>
#endif
#if defined (PREFER_STDARG)
# include <stdarg.h>
#else
# include <varargs.h>
#endif
#include <stdio.h>
int
#if defined (PREFER_STDARG)
fdprintf(int fd, const char *format, ...)
#else
fdprintf(fd, format, va_alist)
int fd;
const char *format;
va_dcl
#endif
{
FILE *fp;
int fd2, rc, r2;
va_list args;
if ((fd2 = dup(fd)) < 0)
return -1;
fp = fdopen (fd2, "w");
if (fp == 0)
{
close (fd2);
return -1;
}
SH_VA_START (args, format);
rc = vfprintf (fp, format, args);
fflush (fp);
va_end (args);
r2 = fclose (fp); /* check here */
return rc;
}
+7 -23
View File
@@ -1422,11 +1422,11 @@ yy_readline_get ()
give_terminal_to (shell_pgrp, 0);
#endif /* JOB_CONTROL */
old_sigint = (SigHandler *)NULL;
old_sigint = (SigHandler *)IMPOSSIBLE_TRAP_HANDLER;
if (signal_is_ignored (SIGINT) == 0)
{
old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
interrupt_immediately++;
old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
}
terminate_immediately = 1;
@@ -1434,10 +1434,11 @@ yy_readline_get ()
current_readline_prompt : "");
terminate_immediately = 0;
if (signal_is_ignored (SIGINT) == 0 && old_sigint)
if (signal_is_ignored (SIGINT) == 0)
{
interrupt_immediately--;
set_signal_handler (SIGINT, old_sigint);
if (old_sigint != IMPOSSIBLE_TRAP_HANDLER)
set_signal_handler (SIGINT, old_sigint);
}
#if 0
@@ -5779,10 +5780,6 @@ sh_parser_state_t *
save_parser_state (ps)
sh_parser_state_t *ps;
{
#if defined (ARRAY_VARS)
SHELL_VAR *v;
#endif
if (ps == 0)
ps = (sh_parser_state_t *)xmalloc (sizeof (sh_parser_state_t));
if (ps == 0)
@@ -5805,11 +5802,7 @@ save_parser_state (ps)
ps->last_command_exit_value = last_command_exit_value;
#if defined (ARRAY_VARS)
v = find_variable ("PIPESTATUS");
if (v && array_p (v) && array_cell (v))
ps->pipestatus = array_copy (array_cell (v));
else
ps->pipestatus = (ARRAY *)NULL;
ps->pipestatus = save_pipestatus_array ();
#endif
ps->last_shell_builtin = last_shell_builtin;
@@ -5825,10 +5818,6 @@ void
restore_parser_state (ps)
sh_parser_state_t *ps;
{
#if defined (ARRAY_VARS)
SHELL_VAR *v;
#endif
if (ps == 0)
return;
@@ -5853,12 +5842,7 @@ restore_parser_state (ps)
last_command_exit_value = ps->last_command_exit_value;
#if defined (ARRAY_VARS)
v = find_variable ("PIPESTATUS");
if (v && array_p (v) && array_cell (v))
{
array_dispose (array_cell (v));
var_setarray (v, ps->pipestatus);
}
restore_pipestatus_array (ps->pipestatus);
#endif
last_shell_builtin = ps->last_shell_builtin;
+16 -6
View File
@@ -1,6 +1,6 @@
/* parse.y - Yacc grammar for bash. */
/* Copyright (C) 1989-2009 Free Software Foundation, Inc.
/* Copyright (C) 1989-2010 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
@@ -1422,11 +1422,11 @@ yy_readline_get ()
give_terminal_to (shell_pgrp, 0);
#endif /* JOB_CONTROL */
old_sigint = (SigHandler *)NULL;
old_sigint = (SigHandler *)IMPOSSIBLE_TRAP_HANDLER;
if (signal_is_ignored (SIGINT) == 0)
{
old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
interrupt_immediately++;
old_sigint = (SigHandler *)set_signal_handler (SIGINT, sigint_sighandler);
}
terminate_immediately = 1;
@@ -1434,10 +1434,11 @@ yy_readline_get ()
current_readline_prompt : "");
terminate_immediately = 0;
if (signal_is_ignored (SIGINT) == 0 && old_sigint)
if (signal_is_ignored (SIGINT) == 0)
{
interrupt_immediately--;
set_signal_handler (SIGINT, old_sigint);
if (old_sigint != IMPOSSIBLE_TRAP_HANDLER)
set_signal_handler (SIGINT, old_sigint);
}
#if 0
@@ -1957,6 +1958,7 @@ read_a_line (remove_quoted_newline)
}
else if (c == '\\' && remove_quoted_newline)
{
QUIT;
peekc = yy_getc ();
if (peekc == '\n')
{
@@ -2600,7 +2602,7 @@ mk_alexpansion (s)
strcpy (r, s);
/* If the last character in the alias is a newline, don't add a trailing
space to the expansion. Works with shell_getc above. */
if (r[l -1] != ' ' && r[l -1] != '\n')
if (r[l - 1] != ' ' && r[l - 1] != '\n')
r[l++] = ' ';
r[l] = '\0';
return r;
@@ -3340,6 +3342,14 @@ parse_comsub (qc, open, close, lenp, flags)
char *ret, *nestret, *ttrans, *heredelim;
int retind, retsize, rflags, hdlen;
#if 0 /* XXX - bash-4.2 -- jwm@horde.net */
/* Assume $(( introduces arithmetic command and parse accordingly. */
peekc = shell_getc (0);
shell_ungetc (peekc);
if (peekc == '(')
return (parse_matched_pair (qc, open, close, lenp, 0));
#endif
/*itrace("parse_comsub: qc = `%c' open = %c close = %c", qc, open, close);*/
count = 1;
tflags = LEX_RESWDOK;
+27 -5
View File
@@ -858,7 +858,7 @@ add_one_character:
if (string[i + 1] == LPAREN)
ret = extract_command_subst (string, &si, 0);
else
ret = extract_dollar_brace_string (string, &si, 1, 0);
ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, 0);
temp[j++] = '$';
temp[j++] = string[i + 1];
@@ -5075,9 +5075,13 @@ command_substitute (string, quoted)
last_asynchronous_pid = old_async_pid;
if (pid == 0)
/* Reset the signal handlers in the child, but don't free the
trap strings. */
reset_signal_handlers ();
{
/* Reset the signal handlers in the child, but don't free the
trap strings. Set a flag noting that we have to free the
trap strings if we run trap to change a signal disposition. */
reset_signal_handlers ();
subshell_environment |= SUBSHELL_RESETTRAP;
}
#if defined (JOB_CONTROL)
/* XXX DO THIS ONLY IN PARENT ? XXX */
@@ -5587,9 +5591,15 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
else
#endif /* ARRAY_VARS */
bind_variable (name, t1, 0);
#if 1
free (t1);
w->word = temp;
#else /* XXX - bash-4.2 -- depends on Posix group interpretation */
free (temp);
w->word = t1;
#endif
return w;
}
@@ -7018,6 +7028,10 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
FREE (temp);
if (value)
{
/* XXX - bash-4.2 */
/* From Posix discussion on austin-group list */
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
quoted |= Q_DOLBRACE;
ret = parameter_brace_expand_rhs (name, value, c,
quoted,
quoted_dollar_atp,
@@ -7061,6 +7075,8 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
if (contains_dollar_at)
*contains_dollar_at = 0;
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
quoted |= Q_DOLBRACE;
ret = parameter_brace_expand_rhs (name, value, c, quoted,
quoted_dollar_atp,
contains_dollar_at);
@@ -7877,7 +7893,13 @@ add_string:
else
tflag = 0;
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
/* From Posix discussion on austin-group list: Backslash escaping
{ or } in ${...} is removed. */
if ((quoted & Q_DOLBRACE) && (c == '{' || c == '}'))
{
SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
}
else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
{
SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
}
+23 -8
View File
@@ -858,7 +858,7 @@ add_one_character:
if (string[i + 1] == LPAREN)
ret = extract_command_subst (string, &si, 0);
else
ret = extract_dollar_brace_string (string, &si, 1, 0);
ret = extract_dollar_brace_string (string, &si, Q_DOUBLE_QUOTES, 0);
temp[j++] = '$';
temp[j++] = string[i + 1];
@@ -1270,7 +1270,7 @@ extract_delimited_string (string, sindex, opener, alt_opener, closer, flags)
if ((flags & SX_COMMAND) && string[i] == '$' && string[i+1] == LPAREN)
{
si = i + 2;
t = extract_command_subst (string, &si, flags);
t = extract_command_subst (string, &si, flags|SX_NOALLOC);
i = si + 1;
continue;
}
@@ -2661,8 +2661,8 @@ do_assignment_internal (word, expand)
const WORD_DESC *word;
int expand;
{
int offset, tlen, appendop, assign_list, aflags, retval;
char *name, *value;
int offset, appendop, assign_list, aflags, retval;
char *name, *value, *temp;
SHELL_VAR *entry;
#if defined (ARRAY_VARS)
char *t;
@@ -2681,8 +2681,6 @@ do_assignment_internal (word, expand)
if (name[offset] == '=')
{
char *temp;
if (name[offset - 1] == '+')
{
appendop = 1;
@@ -2691,7 +2689,6 @@ do_assignment_internal (word, expand)
name[offset] = 0; /* might need this set later */
temp = name + offset + 1;
tlen = STRLEN (temp);
#if defined (ARRAY_VARS)
if (expand && (word->flags & W_COMPASSIGN))
@@ -5590,9 +5587,15 @@ parameter_brace_expand_rhs (name, value, c, quoted, qdollaratp, hasdollarat)
else
#endif /* ARRAY_VARS */
bind_variable (name, t1, 0);
#if 1
free (t1);
w->word = temp;
#else /* XXX - bash-4.2 -- depends on Posix group interpretation */
free (temp);
w->word = t1;
#endif
return w;
}
@@ -7021,6 +7024,10 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
FREE (temp);
if (value)
{
/* XXX - bash-4.2 */
/* From Posix discussion on austin-group list */
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
quoted |= Q_DOLBRACE;
ret = parameter_brace_expand_rhs (name, value, c,
quoted,
quoted_dollar_atp,
@@ -7064,6 +7071,8 @@ parameter_brace_expand (string, indexp, quoted, pflags, quoted_dollar_atp, conta
if (contains_dollar_at)
*contains_dollar_at = 0;
if (quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES))
quoted |= Q_DOLBRACE;
ret = parameter_brace_expand_rhs (name, value, c, quoted,
quoted_dollar_atp,
contains_dollar_at);
@@ -7880,7 +7889,13 @@ add_string:
else
tflag = 0;
if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
/* From Posix discussion on austin-group list: Backslash escaping
{ or } in ${...} is removed. */
if ((quoted & Q_DOLBRACE) && (c == '{' || c == '}'))
{
SCOPY_CHAR_I (twochars, CTLESC, c, string, sindex, string_size);
}
else if ((quoted & (Q_HERE_DOCUMENT|Q_DOUBLE_QUOTES)) && ((sh_syntaxtab[c] & tflag) == 0))
{
SCOPY_CHAR_I (twochars, '\\', c, string, sindex, string_size);
}
+3 -1
View File
@@ -30,7 +30,8 @@
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. */
by double quotes. Q_DOLBRACE means we are expanding a ${...} word, so
backslashes should also escape { and } and be removed. */
#define Q_DOUBLE_QUOTES 0x01
#define Q_HERE_DOCUMENT 0x02
#define Q_KEEP_BACKSLASH 0x04
@@ -38,6 +39,7 @@
#define Q_QUOTED 0x10
#define Q_ADDEDQUOTES 0x20
#define Q_QUOTEDNULL 0x40
#define Q_DOLBRACE 0x80
/* Flag values controlling how assignment statements are treated. */
#define ASS_APPEND 0x01
+302
View File
@@ -0,0 +1,302 @@
/* subst.h -- Names of externally visible functions in subst.c. */
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#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 0x01
#define Q_HERE_DOCUMENT 0x02
#define Q_KEEP_BACKSLASH 0x04
#define Q_PATQUOTE 0x08
#define Q_QUOTED 0x10
#define Q_ADDEDQUOTES 0x20
#define Q_QUOTEDNULL 0x40
/* Flag values controlling how assignment statements are treated. */
#define ASS_APPEND 0x01
#define ASS_MKLOCAL 0x02
#define ASS_MKASSOC 0x04
/* Flags for the string extraction functions. */
#define SX_NOALLOC 0x01 /* just skip; don't return substring */
#define SX_VARNAME 0x02 /* variable name; for string_extract () */
#define SX_REQMATCH 0x04 /* closing/matching delimiter required */
#define SX_COMMAND 0x08 /* extracting a shell script/command */
#define SX_NOCTLESC 0x10 /* don't honor CTLESC quoting */
#define SX_NOESCCTLNUL 0x20 /* don't let CTLESC quote CTLNUL */
#define SX_NOLONGJMP 0x40 /* don't longjmp on fatal error */
#define SX_ARITHSUB 0x80 /* extracting $(( ... )) (currently unused) */
/* 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 ")".
XFLAGS is additional flags to pass to other extraction functions, */
extern char *extract_command_subst __P((char *, int *, 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));
/* Turn the positional paramters into a string, understanding quoting and
the various subtleties of using the first character of $IFS as the
separator. Calls string_list_dollar_at, string_list_dollar_star, and
string_list as appropriate. */
extern char *string_list_pos_params __P((int, 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 *ifs_firstchar __P((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 tilde expansion, parameter expansion, command substitution,
and arithmetic expansion on the right-hand side. Do not perform word
splitting on the result of expansion. */
extern int do_assignment __P((char *));
extern int do_assignment_no_expand __P((char *));
extern int do_word_assignment __P((WORD_DESC *));
/* 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 the rhs of an assignment statement. */
extern WORD_LIST *expand_string_assignment __P((char *, int));
/* Expand a prompt string. */
extern WORD_LIST *expand_prompt_string __P((char *, int, 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));
extern char *expand_assignment_string_to_string __P((char *, int));
/* Expand an arithmetic expression string */
extern char *expand_arith_string __P((char *, int));
/* De-quote quoted characters in STRING. */
extern char *dequote_string __P((char *));
/* De-quote CTLESC-escaped CTLESC or CTLNUL characters in STRING. */
extern char *dequote_escapes __P((char *));
/* De-quote quoted characters in each word in LIST. */
extern WORD_LIST *dequote_list __P((WORD_LIST *));
/* 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 *));
/* And remove such quoted special characters. */
extern char *remove_quoted_escapes __P((char *));
/* Remove CTLNUL characters from STRING unless they are quoted with CTLESC. */
extern char *remove_quoted_nulls __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 WORD_DESC *command_substitute __P((char *, int));
extern char *pat_subst __P((char *, char *, char *, int));
extern int fifos_pending __P((void));
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
/* Flags for skip_to_delim */
#define SD_NOJMP 0x01 /* don't longjmp on fatal error. */
#define SD_INVERT 0x02 /* look for chars NOT in passed set */
#define SD_NOQUOTEDELIM 0x04 /* don't let single or double quotes act as delimiters */
#define SD_NOSKIPCMD 0x08 /* don't skip over $(, <(, or >( command/process substitution */
extern int skip_to_delim __P((char *, int, char *, int));
#if defined (READLINE)
extern int char_is_quoted __P((char *, int));
extern int unclosed_pair __P((char *, int, char *));
extern WORD_LIST *split_at_delims __P((char *, int, char *, int, 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[];
#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)
/* 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_ */
+27 -5
View File
@@ -113,9 +113,6 @@ int trap_saved_exit_value;
/* The (trapped) signal received while executing in the `wait' builtin */
int wait_signal_received;
/* A value which can never be the target of a trap handler. */
#define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
#define GETORIGSIG(sig) \
do { \
original_signals[sig] = (SigHandler *)set_signal_handler (sig, SIG_DFL); \
@@ -265,6 +262,9 @@ run_pending_traps ()
register int sig;
int old_exit_value, *token_state;
WORD_LIST *save_subst_varlist;
#if defined (ARRAY_VARS)
ARRAY *ps;
#endif
if (catch_flag == 0) /* simple optimization */
return;
@@ -273,6 +273,9 @@ run_pending_traps ()
/* Preserve $? when running trap. */
old_exit_value = last_command_exit_value;
#if defined (ARRAY_VARS)
ps = save_pipestatus_array ();
#endif
for (sig = 1; sig < NSIG; sig++)
{
@@ -357,6 +360,9 @@ run_pending_traps ()
}
}
#if defined (ARRAY_VARS)
restore_pipestatus_array (ps);
#endif
last_command_exit_value = old_exit_value;
}
@@ -674,8 +680,14 @@ run_exit_trap ()
{
char *trap_command;
int code, function_code, retval;
#if defined (ARRAY_VARS)
ARRAY *ps;
#endif
trap_saved_exit_value = last_command_exit_value;
#if defined (ARRAY_VARS)
ps = save_pipestatus_array ();
#endif
function_code = 0;
/* Run the trap only if signal 0 is trapped and not ignored, and we are not
@@ -715,6 +727,9 @@ run_exit_trap ()
return retval;
}
#if defined (ARRAY_VARS)
restore_pipestatus_array (ps);
#endif
return (trap_saved_exit_value);
}
@@ -737,6 +752,9 @@ _run_trap_internal (sig, tag)
int save_return_catch_flag, function_code, flags;
procenv_t save_return_catch;
WORD_LIST *save_subst_varlist;
#if defined (ARRAY_VARS)
ARRAY *ps;
#endif
trap_exit_value = function_code = 0;
/* Run the trap only if SIG is trapped and not ignored, and we are not
@@ -752,6 +770,9 @@ _run_trap_internal (sig, tag)
running_trap = sig + 1;
trap_saved_exit_value = last_command_exit_value;
#if defined (ARRAY_VARS)
ps = save_pipestatus_array ();
#endif
token_state = save_token_state ();
save_subst_varlist = subst_assign_varlist;
@@ -778,6 +799,9 @@ _run_trap_internal (sig, tag)
trap_exit_value = last_command_exit_value;
last_command_exit_value = trap_saved_exit_value;
#if defined (ARRAY_VARS)
restore_pipestatus_array (ps);
#endif
running_trap = 0;
sigmodes[sig] &= ~SIG_INPROGRESS;
@@ -888,7 +912,6 @@ run_interrupt_trap ()
_run_trap_internal (SIGINT, "interrupt trap");
}
#ifdef INCLUDE_UNUSED
/* Free all the allocated strings in the list of traps and reset the trap
values to the default. Intended to be called from subshells that want
to complete work done by reset_signal_handlers upon execution of a
@@ -912,7 +935,6 @@ free_trap_string (sig)
change_signal (sig, (char *)DEFAULT_SIG);
sigmodes[sig] &= ~SIG_TRAPPED;
}
#endif
/* Reset the handler for SIG to the original value. */
static void
+1089
View File
File diff suppressed because it is too large Load Diff
+3
View File
@@ -49,6 +49,9 @@
#define DSIG_SIGPREFIX 0x01 /* don't alllow `SIG' PREFIX */
#define DSIG_NOCASE 0x02 /* case-insensitive comparison */
/* A value which can never be the target of a trap handler. */
#define IMPOSSIBLE_TRAP_HANDLER (SigHandler *)initialize_traps
#define signal_object_p(x,f) (decode_signal (x,f) != NO_SIG)
#define TRAP_STRING(s) \
+99
View File
@@ -0,0 +1,99 @@
/* trap.h -- data structures used in the trap mechanism. */
/* Copyright (C) 1993-2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (_TRAP_H_)
#define _TRAP_H_
#include "stdc.h"
#if !defined (SIG_DFL)
#include "bashtypes.h"
#include <signal.h>
#endif /* SIG_DFL */
#if !defined (NSIG)
#define NSIG 64
#endif /* !NSIG */
#define NO_SIG -1
#define DEFAULT_SIG SIG_DFL
#define IGNORE_SIG SIG_IGN
/* Special shell trap names. */
#define DEBUG_TRAP NSIG
#define ERROR_TRAP NSIG+1
#define RETURN_TRAP NSIG+2
#define EXIT_TRAP 0
/* system signals plus special bash traps */
#define BASH_NSIG NSIG+3
/* Flags values for decode_signal() */
#define DSIG_SIGPREFIX 0x01 /* don't alllow `SIG' PREFIX */
#define DSIG_NOCASE 0x02 /* case-insensitive comparison */
#define signal_object_p(x,f) (decode_signal (x,f) != NO_SIG)
#define TRAP_STRING(s) \
(signal_is_trapped (s) && signal_is_ignored (s) == 0) ? trap_list[s] \
: (char *)NULL
extern char *trap_list[];
/* Externally-visible functions declared in trap.c. */
extern void initialize_traps __P((void));
extern void run_pending_traps __P((void));
extern void maybe_set_sigchld_trap __P((char *));
extern void set_impossible_sigchld_trap __P((void));
extern void set_sigchld_trap __P((char *));
extern void set_debug_trap __P((char *));
extern void set_error_trap __P((char *));
extern void set_return_trap __P((char *));
extern void set_sigint_trap __P((char *));
extern void set_signal __P((int, char *));
extern void restore_default_signal __P((int));
extern void ignore_signal __P((int));
extern int run_exit_trap __P((void));
extern void run_trap_cleanup __P((int));
extern int run_debug_trap __P((void));
extern void run_error_trap __P((void));
extern void run_return_trap __P((void));
extern void free_trap_strings __P((void));
extern void reset_signal_handlers __P((void));
extern void restore_original_signals __P((void));
extern char *signal_name __P((int));
extern int decode_signal __P((char *, int));
extern void run_interrupt_trap __P((void));
extern int maybe_call_trap_handler __P((int));
extern int signal_is_trapped __P((int));
extern int signal_is_ignored __P((int));
extern int signal_is_special __P((int));
extern void set_signal_ignored __P((int));
extern int signal_in_progress __P((int));
#endif /* _TRAP_H_ */
+34
View File
@@ -4639,6 +4639,40 @@ set_pipestatus_array (ps, nproc)
}
}
}
ARRAY *
save_pipestatus_array ()
{
SHELL_VAR *v;
ARRAY *a, *a2;
v = find_variable ("PIPESTATUS");
if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
return ((ARRAY *)NULL);
a = array_cell (v);
a2 = array_copy (array_cell (v));
return a2;
}
void
restore_pipestatus_array (a)
ARRAY *a;
{
SHELL_VAR *v;
ARRAY *a2;
v = find_variable ("PIPESTATUS");
/* XXX - should we still assign even if existing value is NULL? */
if (v == 0 || array_p (v) == 0 || array_cell (v) == 0)
return;
a2 = array_cell (v);
var_setarray (v, a);
array_dispose (a2);
}
#endif
void
+39 -2
View File
@@ -158,7 +158,6 @@ static int export_env_size;
#if defined (READLINE)
static int winsize_assignment; /* currently assigning to LINES or COLUMNS */
static int winsize_assigned; /* assigned to LINES or COLUMNS */
#endif
/* Some forward declarations. */
@@ -3808,6 +3807,11 @@ push_func_var (data)
if (tempvar_p (var) && (posixly_correct || (var->attributes & att_propagate)))
{
/* Make sure we have a hash table to store the variable in while it is
being propagated down to the global variables table. Create one if
we have to */
if ((vc_isfuncenv (shell_variables) || vc_istempenv (shell_variables)) && shell_variables->table == 0)
shell_variables->table = hash_create (0);
/* XXX - should we set v->context here? */
v = bind_variable_internal (var->name, value_cell (var), shell_variables->table, 0, 0);
if (shell_variables == global_variables)
@@ -4342,7 +4346,7 @@ sv_winsize (name)
{
if (legal_number (value_cell (v), &xd) == 0)
return;
winsize_assignment = winsize_assigned = 1;
winsize_assignment = 1;
d = xd; /* truncate */
if (name[0] == 'L') /* LINES */
rl_set_screen_size (d, -1);
@@ -4635,6 +4639,39 @@ set_pipestatus_array (ps, nproc)
}
}
}
ARRAY *
save_pipestatus_array ()
{
SHELL_VAR *v;
ARRAY *a, *a2;
v = find_variable ("PIPESTATUS");
if (v == 0 || array_p (v) == 0)
return ((ARRAY *)NULL);
a = array_cell (v);
a2 = a ? array_copy (a) : a;
itrace("save_pipestatus_array: returning 0x%x", a2);
return a2;
}
void
restore_pipestatus_array (a)
ARRAY *a;
{
SHELL_VAR *v;
ARRAY *a2;
v = find_variable ("PIPESTATUS");
if (v == 0 || array_p (v) == 0)
return ((ARRAY *)NULL);
a2 = array_cell (v);
var_setarray (v, a);
itrace("restore_pipestatus_array: restored 0x%x", a);
array_dispose (a2);
}
#endif
void
+2
View File
@@ -331,6 +331,8 @@ extern SHELL_VAR *make_new_assoc_variable __P((char *));
extern SHELL_VAR *make_local_assoc_variable __P((char *));
extern void set_pipestatus_array __P((int *, int));
extern ARRAY *save_pipestatus_array __P((void));
extern void restore_pipestatus_array __P((ARRAY *));
#endif
extern void set_pipestatus_from_exit __P((int));
+386
View File
@@ -0,0 +1,386 @@
/* variables.h -- data structures for shell variables. */
/* Copyright (C) 1987-2009 Free Software Foundation, Inc.
This file is part of GNU Bash, the Bourne Again SHell.
Bash is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bash is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bash. If not, see <http://www.gnu.org/licenses/>.
*/
#if !defined (_VARIABLES_H_)
#define _VARIABLES_H_
#include "stdc.h"
#include "array.h"
#include "assoc.h"
/* Shell variables and functions are stored in hash tables. */
#include "hashlib.h"
#include "conftypes.h"
/* A variable context. */
typedef struct var_context {
char *name; /* empty or NULL means global context */
int scope; /* 0 means global context */
int flags;
struct var_context *up; /* previous function calls */
struct var_context *down; /* down towards global context */
HASH_TABLE *table; /* variables at this scope */
} VAR_CONTEXT;
/* Flags for var_context->flags */
#define VC_HASLOCAL 0x01
#define VC_HASTMPVAR 0x02
#define VC_FUNCENV 0x04 /* also function if name != NULL */
#define VC_BLTNENV 0x08 /* builtin_env */
#define VC_TEMPENV 0x10 /* temporary_env */
#define VC_TEMPFLAGS (VC_FUNCENV|VC_BLTNENV|VC_TEMPENV)
/* Accessing macros */
#define vc_isfuncenv(vc) (((vc)->flags & VC_FUNCENV) != 0)
#define vc_isbltnenv(vc) (((vc)->flags & VC_BLTNENV) != 0)
#define vc_istempenv(vc) (((vc)->flags & (VC_TEMPFLAGS)) == VC_TEMPENV)
#define vc_istempscope(vc) (((vc)->flags & (VC_TEMPENV|VC_BLTNENV)) != 0)
#define vc_haslocals(vc) (((vc)->flags & VC_HASLOCAL) != 0)
#define vc_hastmpvars(vc) (((vc)->flags & VC_HASTMPVAR) != 0)
/* What a shell variable looks like. */
typedef struct variable *sh_var_value_func_t __P((struct variable *));
typedef struct variable *sh_var_assign_func_t __P((struct variable *, char *, arrayind_t, char *));
/* For the future */
union _value {
char *s; /* string value */
intmax_t i; /* int value */
COMMAND *f; /* function */
ARRAY *a; /* array */
HASH_TABLE *h; /* associative array */
double d; /* floating point number */
#if defined (HAVE_LONG_DOUBLE)
long double ld; /* long double */
#endif
struct variable *v; /* possible indirect variable use */
void *opaque; /* opaque data for future use */
};
typedef struct variable {
char *name; /* Symbol that the user types. */
char *value; /* Value that is returned. */
char *exportstr; /* String for the environment. */
sh_var_value_func_t *dynamic_value; /* Function called to return a `dynamic'
value for a variable, like $SECONDS
or $RANDOM. */
sh_var_assign_func_t *assign_func; /* Function called when this `special
variable' is assigned a value in
bind_variable. */
int attributes; /* export, readonly, array, invisible... */
int context; /* Which context this variable belongs to. */
} SHELL_VAR;
typedef struct _vlist {
SHELL_VAR **list;
int list_size; /* allocated size */
int list_len; /* current number of entries */
} VARLIST;
/* The various attributes that a given variable can have. */
/* First, the user-visible attributes */
#define att_exported 0x0000001 /* export to environment */
#define att_readonly 0x0000002 /* cannot change */
#define att_array 0x0000004 /* value is an array */
#define att_function 0x0000008 /* value is a function */
#define att_integer 0x0000010 /* internal representation is int */
#define att_local 0x0000020 /* variable is local to a function */
#define att_assoc 0x0000040 /* variable is an associative array */
#define att_trace 0x0000080 /* function is traced with DEBUG trap */
#define att_uppercase 0x0000100 /* word converted to uppercase on assignment */
#define att_lowercase 0x0000200 /* word converted to lowercase on assignment */
#define att_capcase 0x0000400 /* word capitalized on assignment */
#define user_attrs (att_exported|att_readonly|att_integer|att_local|att_trace|att_uppercase|att_lowercase|att_capcase)
#define attmask_user 0x0000fff
/* Internal attributes used for bookkeeping */
#define att_invisible 0x0001000 /* cannot see */
#define att_nounset 0x0002000 /* cannot unset */
#define att_noassign 0x0004000 /* assignment not allowed */
#define att_imported 0x0008000 /* came from environment */
#define att_special 0x0010000 /* requires special handling */
#define att_nofree 0x0020000 /* do not free value on unset */
#define attmask_int 0x00ff000
/* Internal attributes used for variable scoping. */
#define att_tempvar 0x0100000 /* variable came from the temp environment */
#define att_propagate 0x0200000 /* propagate to previous scope */
#define attmask_scope 0x0f00000
#define exported_p(var) ((((var)->attributes) & (att_exported)))
#define readonly_p(var) ((((var)->attributes) & (att_readonly)))
#define array_p(var) ((((var)->attributes) & (att_array)))
#define function_p(var) ((((var)->attributes) & (att_function)))
#define integer_p(var) ((((var)->attributes) & (att_integer)))
#define local_p(var) ((((var)->attributes) & (att_local)))
#define assoc_p(var) ((((var)->attributes) & (att_assoc)))
#define trace_p(var) ((((var)->attributes) & (att_trace)))
#define uppercase_p(var) ((((var)->attributes) & (att_uppercase)))
#define lowercase_p(var) ((((var)->attributes) & (att_lowercase)))
#define capcase_p(var) ((((var)->attributes) & (att_capcase)))
#define invisible_p(var) ((((var)->attributes) & (att_invisible)))
#define non_unsettable_p(var) ((((var)->attributes) & (att_nounset)))
#define noassign_p(var) ((((var)->attributes) & (att_noassign)))
#define imported_p(var) ((((var)->attributes) & (att_imported)))
#define specialvar_p(var) ((((var)->attributes) & (att_special)))
#define nofree_p(var) ((((var)->attributes) & (att_nofree)))
#define tempvar_p(var) ((((var)->attributes) & (att_tempvar)))
/* Acessing variable values: rvalues */
#define value_cell(var) ((var)->value)
#define function_cell(var) (COMMAND *)((var)->value)
#define array_cell(var) (ARRAY *)((var)->value)
#define assoc_cell(var) (HASH_TABLE *)((var)->value)
#define var_isnull(var) ((var)->value == 0)
#define var_isset(var) ((var)->value != 0)
/* Assigning variable values: lvalues */
#define var_setvalue(var, str) ((var)->value = (str))
#define var_setfunc(var, func) ((var)->value = (char *)(func))
#define var_setarray(var, arr) ((var)->value = (char *)(arr))
#define var_setassoc(var, arr) ((var)->value = (char *)(arr))
/* Make VAR be auto-exported. */
#define set_auto_export(var) \
do { (var)->attributes |= att_exported; array_needs_making = 1; } while (0)
#define SETVARATTR(var, attr, undo) \
((undo == 0) ? ((var)->attributes |= (attr)) \
: ((var)->attributes &= ~(attr)))
#define VSETATTR(var, attr) ((var)->attributes |= (attr))
#define VUNSETATTR(var, attr) ((var)->attributes &= ~(attr))
#define VGETFLAGS(var) ((var)->attributes)
#define VSETFLAGS(var, flags) ((var)->attributes = (flags))
#define VCLRFLAGS(var) ((var)->attributes = 0)
/* Macros to perform various operations on `exportstr' member of a SHELL_VAR. */
#define CLEAR_EXPORTSTR(var) (var)->exportstr = (char *)NULL
#define COPY_EXPORTSTR(var) ((var)->exportstr) ? savestring ((var)->exportstr) : (char *)NULL
#define SET_EXPORTSTR(var, value) (var)->exportstr = (value)
#define SAVE_EXPORTSTR(var, value) (var)->exportstr = (value) ? savestring (value) : (char *)NULL
#define FREE_EXPORTSTR(var) \
do { if ((var)->exportstr) free ((var)->exportstr); } while (0)
#define CACHE_IMPORTSTR(var, value) \
(var)->exportstr = savestring (value)
#define INVALIDATE_EXPORTSTR(var) \
do { \
if ((var)->exportstr) \
{ \
free ((var)->exportstr); \
(var)->exportstr = (char *)NULL; \
} \
} while (0)
/* Stuff for hacking variables. */
typedef int sh_var_map_func_t __P((SHELL_VAR *));
/* Where we keep the variables and functions */
extern VAR_CONTEXT *global_variables;
extern VAR_CONTEXT *shell_variables;
extern HASH_TABLE *shell_functions;
extern HASH_TABLE *temporary_env;
extern int variable_context;
extern char *dollar_vars[];
extern char **export_env;
extern void initialize_shell_variables __P((char **, int));
extern SHELL_VAR *set_if_not __P((char *, char *));
extern void sh_set_lines_and_columns __P((int, int));
extern void set_pwd __P((void));
extern void set_ppid __P((void));
extern void make_funcname_visible __P((int));
extern SHELL_VAR *var_lookup __P((const char *, VAR_CONTEXT *));
extern SHELL_VAR *find_function __P((const char *));
extern FUNCTION_DEF *find_function_def __P((const char *));
extern SHELL_VAR *find_variable __P((const char *));
extern SHELL_VAR *find_variable_internal __P((const char *, int));
extern SHELL_VAR *find_tempenv_variable __P((const char *));
extern SHELL_VAR *copy_variable __P((SHELL_VAR *));
extern SHELL_VAR *make_local_variable __P((const char *));
extern SHELL_VAR *bind_variable __P((const char *, char *, int));
extern SHELL_VAR *bind_function __P((const char *, COMMAND *));
extern void bind_function_def __P((const char *, FUNCTION_DEF *));
extern SHELL_VAR **map_over __P((sh_var_map_func_t *, VAR_CONTEXT *));
SHELL_VAR **map_over_funcs __P((sh_var_map_func_t *));
extern SHELL_VAR **all_shell_variables __P((void));
extern SHELL_VAR **all_shell_functions __P((void));
extern SHELL_VAR **all_visible_variables __P((void));
extern SHELL_VAR **all_visible_functions __P((void));
extern SHELL_VAR **all_exported_variables __P((void));
extern SHELL_VAR **local_exported_variables __P((void));
extern SHELL_VAR **all_local_variables __P((void));
#if defined (ARRAY_VARS)
extern SHELL_VAR **all_array_variables __P((void));
#endif
extern char **all_variables_matching_prefix __P((const char *));
extern char **make_var_array __P((HASH_TABLE *));
extern char **add_or_supercede_exported_var __P((char *, int));
extern char *get_variable_value __P((SHELL_VAR *));
extern char *get_string_value __P((const char *));
extern char *sh_get_env_value __P((const char *));
extern char *make_variable_value __P((SHELL_VAR *, char *, int));
extern SHELL_VAR *bind_variable_value __P((SHELL_VAR *, char *, int));
extern SHELL_VAR *bind_int_variable __P((char *, char *));
extern SHELL_VAR *bind_var_to_int __P((char *, intmax_t));
extern int assign_in_env __P((WORD_DESC *));
extern int unbind_variable __P((const char *));
extern int unbind_func __P((const char *));
extern int unbind_function_def __P((const char *));
extern int makunbound __P((const char *, VAR_CONTEXT *));
extern int kill_local_variable __P((const char *));
extern void delete_all_variables __P((HASH_TABLE *));
extern void delete_all_contexts __P((VAR_CONTEXT *));
extern VAR_CONTEXT *new_var_context __P((char *, int));
extern void dispose_var_context __P((VAR_CONTEXT *));
extern VAR_CONTEXT *push_var_context __P((char *, int, HASH_TABLE *));
extern void pop_var_context __P((void));
extern VAR_CONTEXT *push_scope __P((int, HASH_TABLE *));
extern void pop_scope __P((int));
extern void push_context __P((char *, int, HASH_TABLE *));
extern void pop_context __P((void));
extern void push_dollar_vars __P((void));
extern void pop_dollar_vars __P((void));
extern void dispose_saved_dollar_vars __P((void));
extern void push_args __P((WORD_LIST *));
extern void pop_args __P((void));
extern void adjust_shell_level __P((int));
extern void non_unsettable __P((char *));
extern void dispose_variable __P((SHELL_VAR *));
extern void dispose_used_env_vars __P((void));
extern void dispose_function_env __P((void));
extern void dispose_builtin_env __P((void));
extern void merge_temporary_env __P((void));
extern void merge_builtin_env __P((void));
extern void kill_all_local_variables __P((void));
extern void set_var_read_only __P((char *));
extern void set_func_read_only __P((const char *));
extern void set_var_auto_export __P((char *));
extern void set_func_auto_export __P((const char *));
extern void sort_variables __P((SHELL_VAR **));
extern void maybe_make_export_env __P((void));
extern void update_export_env_inplace __P((char *, int, char *));
extern void put_command_name_into_env __P((char *));
extern void put_gnu_argv_flags_into_env __P((intmax_t, char *));
extern void print_var_list __P((SHELL_VAR **));
extern void print_func_list __P((SHELL_VAR **));
extern void print_assignment __P((SHELL_VAR *));
extern void print_var_value __P((SHELL_VAR *, int));
extern void print_var_function __P((SHELL_VAR *));
#if defined (ARRAY_VARS)
extern SHELL_VAR *make_new_array_variable __P((char *));
extern SHELL_VAR *make_local_array_variable __P((char *));
extern SHELL_VAR *make_new_assoc_variable __P((char *));
extern SHELL_VAR *make_local_assoc_variable __P((char *));
extern void set_pipestatus_array __P((int *, int));
#endif
extern void set_pipestatus_from_exit __P((int));
/* The variable in NAME has just had its state changed. Check to see if it
is one of the special ones where something special happens. */
extern void stupidly_hack_special_variables __P((char *));
/* Reinitialize some special variables that have external effects upon unset
when the shell reinitializes itself. */
extern void reinit_special_variables __P((void));
extern int get_random_number __P((void));
/* The `special variable' functions that get called when a particular
variable is set. */
extern void sv_ifs __P((char *));
extern void sv_path __P((char *));
extern void sv_mail __P((char *));
extern void sv_globignore __P((char *));
extern void sv_ignoreeof __P((char *));
extern void sv_strict_posix __P((char *));
extern void sv_optind __P((char *));
extern void sv_opterr __P((char *));
extern void sv_locale __P((char *));
extern void sv_xtracefd __P((char *));
#if defined (READLINE)
extern void sv_comp_wordbreaks __P((char *));
extern void sv_terminal __P((char *));
extern void sv_hostfile __P((char *));
extern void sv_winsize __P((char *));
#endif
#if defined (__CYGWIN__)
extern void sv_home __P((char *));
#endif
#if defined (HISTORY)
extern void sv_histsize __P((char *));
extern void sv_histignore __P((char *));
extern void sv_history_control __P((char *));
# if defined (BANG_HISTORY)
extern void sv_histchars __P((char *));
# endif
extern void sv_histtimefmt __P((char *));
#endif /* HISTORY */
#if defined (HAVE_TZSET) && defined (PROMPT_STRING_DECODE)
extern void sv_tz __P((char *));
#endif
#endif /* !_VARIABLES_H_ */