mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-06-27 07:43:07 +02:00
commit bash-20100225 snapshot
This commit is contained in:
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
@@ -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,
|
||||
|
||||
@@ -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
@@ -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. */
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
@@ -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_ */
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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_ */
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_ */
|
||||
@@ -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
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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_ */
|
||||
Reference in New Issue
Block a user