Bash-4.0 patchlevel 38

This commit is contained in:
Chet Ramey 2011-11-21 20:49:12 -05:00
commit 89a92869e5
27 changed files with 490 additions and 164 deletions

View file

@ -98,7 +98,7 @@ convert_var_to_assoc (var)
oldval = value_cell (var);
hash = assoc_create (0);
if (oldval)
assoc_insert (hash, "0", oldval);
assoc_insert (hash, savestring ("0"), oldval);
FREE (value_cell (var));
var_setassoc (var, hash);
@ -604,64 +604,7 @@ quote_array_assignment_chars (list)
}
}
/* This function assumes s[i] == '['; returns with s[ret] == ']' if
an array subscript is correctly parsed. */
int
skipsubscript (s, i)
const char *s;
int i;
{
int count, c;
#if defined (HANDLE_MULTIBYTE)
mbstate_t state, state_bak;
size_t slength, mblength;
#endif
#if defined (HANDLE_MULTIBYTE)
memset (&state, '\0', sizeof (mbstate_t));
slength = strlen (s + i);
#endif
count = 1;
while (count)
{
/* Advance one (possibly multibyte) character in S starting at I. */
#if defined (HANDLE_MULTIBYTE)
if (MB_CUR_MAX > 1)
{
state_bak = state;
mblength = mbrlen (s + i, slength, &state);
if (MB_INVALIDCH (mblength))
{
state = state_bak;
i++;
slength--;
}
else if (MB_NULLWCH (mblength))
return i;
else
{
i += mblength;
slength -= mblength;
}
}
else
#endif
++i;
c = s[i];
if (c == 0)
break;
else if (c == '[')
count++;
else if (c == ']')
count--;
}
return i;
}
/* skipsubscript moved to subst.c to use private functions. 2009/02/24. */
/* This function is called with SUB pointing to just after the beginning
`[' of an array subscript and removes the array element to which SUB

View file

@ -3388,7 +3388,6 @@ bash_execute_unix_command (count, key)
Keymap xkmap; /* unix command executing keymap */
register int i;
intmax_t mi;
int save_point;
sh_parser_state_t ps;
char *cmd, *value, *l;
SHELL_VAR *v;
@ -3432,7 +3431,6 @@ bash_execute_unix_command (count, key)
if (v)
VSETATTR (v, att_exported);
l = value_cell (v);
save_point = rl_point;
value = inttostr (rl_point, ibuf, sizeof (ibuf));
v = bind_int_variable ("READLINE_POINT", value);
if (v)
@ -3450,7 +3448,7 @@ bash_execute_unix_command (count, key)
if (v && legal_number (value_cell (v), &mi))
{
i = mi;
if (i != save_point)
if (i != rl_point)
{
rl_point = i;
if (rl_point > rl_end)

View file

@ -295,6 +295,13 @@ declare_internal (list, local_var)
subscript_start = (char *)NULL;
if (t = strchr (name, '[')) /* ] */
{
/* If offset != 0 we have already validated any array reference */
if (offset == 0 && valid_array_reference (name) == 0)
{
sh_invalidid (name);
assign_error++;
NEXT_VARIABLE ();
}
subscript_start = t;
*t = '\0';
making_array_special = 1;
@ -484,7 +491,7 @@ declare_internal (list, local_var)
}
/* declare -a name[[n]] or declare name[n] makes name an indexed
array variable. */
else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0)
else if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0 && assoc_p (var) == 0)
var = convert_var_to_array (var);
#endif /* ARRAY_VARS */

View file

@ -113,7 +113,7 @@ exit_or_logout (list)
for (i = stopmsg = 0; i < js.j_jobslots; i++)
if (jobs[i] && STOPPED (i))
stopmsg = JSTOPPED;
else if (check_jobs_at_exit && stopmsg == 0 && RUNNING (i))
else if (check_jobs_at_exit && stopmsg == 0 && jobs[i] && RUNNING (i))
stopmsg = JRUNNING;
if (stopmsg == JSTOPPED)

View file

@ -88,6 +88,7 @@ extern int errno;
extern int current_command_line_count;
extern int literal_history;
extern int posixly_correct;
extern int subshell_environment, interactive_shell;
extern int unlink __P((const char *));
@ -172,7 +173,7 @@ fc_builtin (list)
register int i;
register char *sep;
int numbering, reverse, listing, execute;
int histbeg, histend, last_hist, retval, opt;
int histbeg, histend, last_hist, retval, opt, rh;
FILE *stream;
REPL *rlist, *rl;
char *ename, *command, *newcom, *fcedit;
@ -275,6 +276,8 @@ fc_builtin (list)
fprintf (stderr, "%s\n", command);
fc_replhist (command); /* replace `fc -s' with command */
/* Posix says that the re-executed commands should be entered into the
history. */
return (parse_and_execute (command, "fc", SEVAL_NOHIST));
}
@ -293,7 +296,12 @@ fc_builtin (list)
line was actually added (HISTIGNORE may have caused it to not be),
so we check hist_last_line_added. */
last_hist = i - remember_on_history - hist_last_line_added;
/* Even though command substitution through parse_and_execute turns off
remember_on_history, command substitution in a shell when set -o history
has been enabled (interactive or not) should use it in the last_hist
calculation as if it were on. */
rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
last_hist = i - rh - hist_last_line_added;
if (list)
{
@ -456,7 +464,7 @@ fc_gethnum (command, hlist)
char *command;
HIST_ENTRY **hlist;
{
int sign, n, clen;
int sign, n, clen, rh;
register int i, j;
register char *s;
@ -472,7 +480,12 @@ fc_gethnum (command, hlist)
line was actually added (HISTIGNORE may have caused it to not be),
so we check hist_last_line_added. This needs to agree with the
calculation of last_hist in fc_builtin above. */
i -= remember_on_history + hist_last_line_added;
/* Even though command substitution through parse_and_execute turns off
remember_on_history, command substitution in a shell when set -o history
has been enabled (interactive or not) should use it in the last_hist
calculation as if it were on. */
rh = remember_on_history || ((subshell_environment & SUBSHELL_COMSUB) && enable_history_list);
i -= rh + hist_last_line_added;
/* No specification defaults to most recent command. */
if (command == NULL)

View file

@ -369,14 +369,14 @@ read_builtin (list)
code = setjmp (alrmbuf);
if (code)
{
#if 0
/* 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");
return (EXECUTION_FAILURE);
#else
input_string[i] = '\0'; /* make sure it's terminated */
retval = 128+SIGALRM;;
retval = 128+SIGALRM;
goto assign_vars;
#endif
}
old_alrm = set_signal_handler (SIGALRM, sigalrm);
add_unwind_protect (reset_alarm, (char *)NULL);
@ -601,14 +601,15 @@ 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--;
#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. */
@ -763,7 +764,10 @@ assign_vars:
if (*input_string == 0)
tofree = input_string = t;
else
input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
{
input_string = strip_trailing_ifs_whitespace (t1, ifs_chars, saw_escape);
tofree = t;
}
}
#endif

4
configure vendored
View file

@ -5806,7 +5806,7 @@ _ACEOF
# static version specified as -llibname to override the
# dynamic version
case "${host_os}" in
darwin[89]*) READLINE_LIB='${READLINE_LIBRARY}' ;;
darwin[89]*|darwin10*) READLINE_LIB='${READLINE_LIBRARY}' ;;
*) READLINE_LIB=-lreadline ;;
esac
fi
@ -5847,7 +5847,7 @@ _ACEOF
# static version specified as -llibname to override the
# dynamic version
case "${host_os}" in
darwin[89]*) HISTORY_LIB='${HISTORY_LIBRARY}' ;;
darwin[89]*|darwin10*) HISTORY_LIB='${HISTORY_LIBRARY}' ;;
*) HISTORY_LIB=-lhistory ;;
esac
fi

View file

@ -533,7 +533,7 @@ if test $opt_readline = yes; then
# static version specified as -llibname to override the
# dynamic version
case "${host_os}" in
darwin[[89]]*) READLINE_LIB='${READLINE_LIBRARY}' ;;
darwin[[89]]*|darwin10*) READLINE_LIB='${READLINE_LIBRARY}' ;;
*) READLINE_LIB=-lreadline ;;
esac
fi
@ -568,7 +568,7 @@ if test $opt_history = yes || test $opt_bang_history = yes; then
# static version specified as -llibname to override the
# dynamic version
case "${host_os}" in
darwin[[89]]*) HISTORY_LIB='${HISTORY_LIBRARY}' ;;
darwin[[89]]*|darwin10*) HISTORY_LIB='${HISTORY_LIBRARY}' ;;
*) HISTORY_LIB=-lhistory ;;
esac
fi

View file

@ -8257,9 +8257,10 @@ and group ids to be set to the real user and group ids.
Exit after reading and executing one command.
.TP 8
.B \-u
Treat unset variables as an error when performing
Treat unset variables and parameters other than the special
parameters "@" and "*" as an error when performing
parameter expansion. If expansion is attempted on an
unset variable, the shell prints an error message, and,
unset variable or parameter, the shell prints an error message, and,
if not interactive, exits with a non-zero status.
.TP 8
.B \-v

View file

@ -4138,7 +4138,8 @@ and group ids to be set to the real user and group ids.
Exit after reading and executing one command.
@item -u
Treat unset variables as an error when performing parameter expansion.
Treat unset variables and parameters other than the special parameters
@samp{@@} or @samp{*} as an error when performing parameter expansion.
An error message will be written to the standard error, and a non-interactive
shell will exit.

View file

@ -568,6 +568,7 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
/* Fork a subshell, turn off the subshell bit, turn off job
control and call execute_command () on the command again. */
line_number_for_err_trap = line_number;
paren_pid = make_child (savestring (make_command_string (command)),
asynchronous);
if (paren_pid == 0)
@ -610,7 +611,10 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
if (user_subshell && was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
{
last_command_exit_value = exec_result;
save_line_number = line_number;
line_number = line_number_for_err_trap;
run_error_trap ();
line_number = save_line_number;
}
if (user_subshell && ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
@ -766,7 +770,9 @@ execute_command_internal (command, asynchronous, pipe_in, pipe_out,
if (was_error_trap && ignore_return == 0 && invert == 0 && pipe_in == NO_PIPE && pipe_out == NO_PIPE && exec_result != EXECUTION_SUCCESS)
{
last_command_exit_value = exec_result;
line_number = line_number_for_err_trap;
run_error_trap ();
line_number = save_line_number;
}
if (ignore_return == 0 && invert == 0 &&
@ -2105,6 +2111,7 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
REDIRECT *rp;
COMMAND *tc, *second;
int ignore_return, exec_result, was_error_trap, invert;
volatile int save_line_number;
ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
@ -2174,12 +2181,16 @@ execute_connection (command, asynchronous, pipe_in, pipe_out, fds_to_close)
invert = (command->flags & CMD_INVERT_RETURN) != 0;
ignore_return = (command->flags & CMD_IGNORE_RETURN) != 0;
line_number_for_err_trap = line_number;
exec_result = execute_pipeline (command, asynchronous, pipe_in, pipe_out, fds_to_close);
if (was_error_trap && ignore_return == 0 && invert == 0 && exec_result != EXECUTION_SUCCESS)
{
last_command_exit_value = exec_result;
save_line_number = line_number;
line_number = line_number_for_err_trap;
run_error_trap ();
line_number = save_line_number;
}
if (ignore_return == 0 && invert == 0 && exit_immediately_on_error && exec_result != EXECUTION_SUCCESS)
@ -2930,7 +2941,7 @@ execute_case_command (case_command)
retval = execute_command (clauses->action);
}
while ((clauses->flags & CASEPAT_FALLTHROUGH) && (clauses = clauses->next));
if ((clauses->flags & CASEPAT_TESTNEXT) == 0)
if (clauses == 0 || (clauses->flags & CASEPAT_TESTNEXT) == 0)
EXIT_CASE ();
else
break;

View file

@ -192,6 +192,8 @@ extern char *fmtullong __P((unsigned long long int, int, char *, size_t, int));
extern char *fmtumax __P((uintmax_t, int, char *, size_t, int));
/* Declarations for functions defined in lib/sh/fpurge.c */
#if defined NEED_FPURGE_DECL
#if !HAVE_DECL_FPURGE
#if HAVE_FPURGE
@ -200,7 +202,7 @@ extern char *fmtumax __P((uintmax_t, int, char *, size_t, int));
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)

21
jobs.c
View file

@ -442,7 +442,7 @@ restore_pipeline (discard)
old_pipeline = the_pipeline;
the_pipeline = saved_pipeline;
already_making_children = saved_already_making_children;
if (discard)
if (discard && old_pipeline)
discard_pipeline (old_pipeline);
}
@ -4202,4 +4202,23 @@ close_pgrp_pipe ()
sh_closepipe (pgrp_pipe);
}
void
save_pgrp_pipe (p, clear)
int *p;
int clear;
{
p[0] = pgrp_pipe[0];
p[1] = pgrp_pipe[1];
if (clear)
pgrp_pipe[0] = pgrp_pipe[1] = -1;
}
void
restore_pgrp_pipe (p)
int *p;
{
pgrp_pipe[0] = p[0];
pgrp_pipe[1] = p[1];
}
#endif /* PGRP_PIPE */

2
jobs.h
View file

@ -235,6 +235,8 @@ extern void default_tty_job_signals __P((void));
extern void init_job_stats __P((void));
extern void close_pgrp_pipe __P((void));
extern void save_pgrp_pipe __P((int *, int));
extern void restore_pgrp_pipe __P((int *));
#if defined (JOB_CONTROL)
extern int job_control;

View file

@ -356,7 +356,7 @@ finddirs (pat, sdir, flags, ep, np)
*np = 0;
if (ep)
*ep = 0;
if (r)
if (r && r != &glob_error_return)
free (r);
return (struct globval *)0;
}
@ -665,7 +665,9 @@ glob_vector (pat, dir, flags)
(void) closedir (d);
}
/* compat: if GX_ALLDIRS, add the passed directory also */
/* compat: if GX_ADDCURDIR, add the passed directory also. Add an empty
directory name as a placeholder if GX_NULLDIR (in which case the passed
directory name is "."). */
if (add_current)
{
sdlen = strlen (dir);
@ -917,11 +919,14 @@ glob_filename (pathname, flags)
{
char **temp_results;
/* XXX -- we've recursively scanned any directories resulting from
a `**', so turn off the flag. We turn it on again below if
filename is `**' */
/* Scan directory even on a NULL filename. That way, `*h/'
returns only directories ending in `h', instead of all
files ending in `h' with a `/' appended. */
dname = directories[i];
dflags = flags & ~GX_MARKDIRS;
dflags = flags & ~(GX_MARKDIRS|GX_ALLDIRS|GX_ADDCURDIR);
if ((flags & GX_GLOBSTAR) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
if (dname[0] == '\0' && filename[0])
@ -942,7 +947,12 @@ glob_filename (pathname, flags)
char **array;
register unsigned int l;
array = glob_dir_to_array (directories[i], temp_results, flags);
/* If we're expanding **, we don't need to glue the directory
name to the results; we've already done it in glob_vector */
if ((dflags & GX_ALLDIRS) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
array = temp_results;
else
array = glob_dir_to_array (directories[i], temp_results, flags);
l = 0;
while (array[l] != NULL)
++l;
@ -959,7 +969,8 @@ glob_filename (pathname, flags)
result[result_size - 1] = NULL;
/* Note that the elements of ARRAY are not freed. */
free ((char *) array);
if (array != temp_results)
free ((char *) array);
}
}
/* Free the directories. */
@ -1003,11 +1014,24 @@ glob_filename (pathname, flags)
/* Just return what glob_vector () returns appended to the
directory name. */
/* If flags & GX_ALLDIRS, we're called recursively */
dflags = flags & ~GX_MARKDIRS;
if (directory_len == 0)
dflags |= GX_NULLDIR;
if ((flags & GX_GLOBSTAR) && filename[0] == '*' && filename[1] == '*' && filename[2] == '\0')
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
{
dflags |= GX_ALLDIRS|GX_ADDCURDIR;
#if 0
/* If we want all directories (dflags & GX_ALLDIRS) and we're not
being called recursively as something like `echo **/*.o'
((flags & GX_ALLDIRS) == 0), we want to prevent glob_vector from
adding a null directory name to the front of the temp_results
array. We turn off ADDCURDIR if not called recursively and
dlen == 0 */
#endif
if (directory_len == 0 && (flags & GX_ALLDIRS) == 0)
dflags &= ~GX_ADDCURDIR;
}
temp_results = glob_vector (filename,
(directory_len == 0 ? "." : directory_name),
dflags);

View file

@ -2208,7 +2208,7 @@ rl_old_menu_complete (count, invoking_key)
/* The first time through, we generate the list of matches and set things
up to insert them. */
if (rl_last_func != rl_menu_complete)
if (rl_last_func != rl_old_menu_complete)
{
/* Clean up from previous call, if any. */
FREE (orig_text);
@ -2220,6 +2220,8 @@ rl_old_menu_complete (count, invoking_key)
rl_completion_invoking_key = invoking_key;
RL_SETSTATE(RL_STATE_COMPLETING);
/* Only the completion entry function can change these. */
set_completion_defaults ('%');
@ -2259,9 +2261,12 @@ rl_old_menu_complete (count, invoking_key)
FREE (orig_text);
orig_text = (char *)0;
completion_changed_buffer = 0;
RL_UNSETSTATE(RL_STATE_COMPLETING);
return (0);
}
RL_UNSETSTATE(RL_STATE_COMPLETING);
for (match_list_size = 0; matches[match_list_size]; match_list_size++)
;
/* matches[0] is lcd if match_list_size > 1, but the circular buffer
@ -2337,6 +2342,8 @@ rl_menu_complete (count, ignore)
full_completion = 0;
RL_SETSTATE(RL_STATE_COMPLETING);
/* Only the completion entry function can change these. */
set_completion_defaults ('%');
@ -2378,9 +2385,12 @@ rl_menu_complete (count, ignore)
FREE (orig_text);
orig_text = (char *)0;
completion_changed_buffer = 0;
RL_UNSETSTATE(RL_STATE_COMPLETING);
return (0);
}
RL_UNSETSTATE(RL_STATE_COMPLETING);
for (match_list_size = 0; matches[match_list_size]; match_list_size++)
;

View file

@ -512,6 +512,7 @@ rl_redisplay ()
/* Block keyboard interrupts because this function manipulates global
data structures. */
_rl_block_sigint ();
RL_SETSTATE (RL_STATE_REDISPLAYING);
if (!rl_display_prompt)
rl_display_prompt = "";
@ -1188,9 +1189,11 @@ rl_redisplay ()
if (t < out)
line[t - 1] = '>';
if (!rl_display_fixed || forced_display || lmargin != last_lmargin)
if (rl_display_fixed == 0 || forced_display || lmargin != last_lmargin)
{
forced_display = 0;
o_cpos = _rl_last_c_pos;
cpos_adjusted = 0;
update_line (&visible_line[last_lmargin],
&invisible_line[lmargin],
0,
@ -1198,6 +1201,13 @@ rl_redisplay ()
_rl_screenwidth + (lmargin ? 0 : wrap_offset),
0);
if ((MB_CUR_MAX > 1 && rl_byte_oriented == 0) &&
cpos_adjusted == 0 &&
_rl_last_c_pos != o_cpos &&
_rl_last_c_pos > wrap_offset &&
o_cpos < prompt_last_invisible)
_rl_last_c_pos -= prompt_invis_chars_first_line; /* XXX - was wrap_offset */
/* If the visible new line is shorter than the old, but the number
of invisible characters is greater, and we are at the end of
the new line, we need to clear to eol. */
@ -1236,6 +1246,7 @@ rl_redisplay ()
visible_wrap_offset = wrap_offset;
}
RL_UNSETSTATE (RL_STATE_REDISPLAYING);
_rl_release_sigint ();
}
@ -1772,7 +1783,7 @@ update_line (old, new, current_line, omax, nmax, inv_botlin)
space_to_eol will insert too many spaces. XXX - maybe we should
adjust col_lendiff based on the difference between _rl_last_c_pos
and _rl_screenwidth */
if (col_lendiff && (_rl_last_c_pos < _rl_screenwidth))
if (col_lendiff && ((MB_CUR_MAX == 1 || rl_byte_oriented) || (_rl_last_c_pos < _rl_screenwidth)))
#endif
{
if (_rl_term_autowrap && current_line < inv_botlin)
@ -1892,6 +1903,10 @@ _rl_move_cursor_relative (new, data)
woff = WRAP_OFFSET (_rl_last_v_pos, wrap_offset);
cpos = _rl_last_c_pos;
if (cpos == 0 && cpos == new)
return;
#if defined (HANDLE_MULTIBYTE)
/* If we have multibyte characters, NEW is indexed by the buffer point in
a multibyte string, but _rl_last_c_pos is the display position. In
@ -1905,9 +1920,9 @@ _rl_move_cursor_relative (new, data)
prompt string, since they're both buffer indices and DPOS is a
desired display position. */
if ((new > prompt_last_invisible) || /* XXX - don't use woff here */
(prompt_physical_chars > _rl_screenwidth &&
(prompt_physical_chars >= _rl_screenwidth &&
_rl_last_v_pos == prompt_last_screen_line &&
wrap_offset >= woff &&
wrap_offset >= woff && dpos >= woff &&
new > (prompt_last_invisible-(_rl_screenwidth*_rl_last_v_pos)-wrap_offset)))
/* XXX last comparison might need to be >= */
{

View file

@ -814,8 +814,9 @@ extern int rl_inhibit_completion;
#define RL_STATE_VIMOTION 0x100000 /* reading vi motion arg */
#define RL_STATE_MULTIKEY 0x200000 /* reading multiple-key command */
#define RL_STATE_VICMDONCE 0x400000 /* entered vi command mode at least once */
#define RL_STATE_REDISPLAYING 0x800000 /* updating terminal display */
#define RL_STATE_DONE 0x800000 /* done; accepted line */
#define RL_STATE_DONE 0x1000000 /* done; accepted line */
#define RL_SETSTATE(x) (rl_readline_state |= (x))
#define RL_UNSETSTATE(x) (rl_readline_state &= ~(x))

View file

@ -355,7 +355,7 @@ rl_resize_terminal ()
_rl_get_screen_size (fileno (rl_instream), 1);
if (CUSTOM_REDISPLAY_FUNC ())
rl_forced_update_display ();
else
else if (RL_ISSTATE(RL_STATE_REDISPLAYING) == 0)
_rl_redisplay_after_sigwinch ();
}
}

View file

@ -30,16 +30,29 @@
#include <sys/ioctl.h>
#if !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
/* For struct winsize on SCO */
/* sys/ptem.h has winsize but needs mblk_t from sys/stream.h */
# if defined (HAVE_SYS_PTEM_H) && defined (TIOCGWINSZ) && defined (SIGWINCH)
# if defined (HAVE_SYS_STREAM_H)
# include <sys/stream.h>
# endif
/* Try to find the definitions of `struct winsize' and TIOGCWINSZ */
#if defined (GWINSZ_IN_SYS_IOCTL) && !defined (TIOCGWINSZ)
# include <sys/ioctl.h>
#endif /* GWINSZ_IN_SYS_IOCTL && !TIOCGWINSZ */
#if defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
# include <termios.h>
#endif /* STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
/* Not in either of the standard places, look around. */
#if !defined (STRUCT_WINSIZE_IN_TERMIOS) && !defined (STRUCT_WINSIZE_IN_SYS_IOCTL)
# if defined (HAVE_SYS_STREAM_H)
# include <sys/stream.h>
# endif /* HAVE_SYS_STREAM_H */
# if defined (HAVE_SYS_PTEM_H) /* SVR4.2, at least, has it here */
# include <sys/ptem.h>
# endif /* HAVE_SYS_PTEM_H && TIOCGWINSZ && SIGWINCH */
#endif /* !STRUCT_WINSIZE_IN_SYS_IOCTL */
# define _IO_PTEM_H /* work around SVR4.2 1.1.4 bug */
# endif /* HAVE_SYS_PTEM_H */
# if defined (HAVE_SYS_PTE_H) /* ??? */
# include <sys/pte.h>
# endif /* HAVE_SYS_PTE_H */
#endif /* !STRUCT_WINSIZE_IN_TERMIOS && !STRUCT_WINSIZE_IN_SYS_IOCTL */
#include <stdio.h>

114
parse.y
View file

@ -1122,7 +1122,7 @@ pipeline: pipeline '|' newline_list pipeline
REDIRECTEE rd;
REDIRECT *r;
tc = $1;
tc = $1->type == cm_simple ? (COMMAND *)$1->value.Simple : $1;
rd.dest = 1;
r = make_redirection (2, r_duplicating_output, rd);
if (tc->redirects)
@ -1615,10 +1615,11 @@ save_token_state ()
{
int *ret;
ret = (int *)xmalloc (3 * sizeof (int));
ret = (int *)xmalloc (4 * sizeof (int));
ret[0] = last_read_token;
ret[1] = token_before_that;
ret[2] = two_tokens_ago;
ret[3] = current_token;
return ret;
}
@ -1631,6 +1632,7 @@ restore_token_state (ts)
last_read_token = ts[0];
token_before_that = ts[1];
two_tokens_ago = ts[2];
current_token = ts[3];
}
/*
@ -1877,7 +1879,7 @@ read_secondary_line (remove_quoted_newline)
prompt_again ();
ret = read_a_line (remove_quoted_newline);
#if defined (HISTORY)
if (remember_on_history && (parser_state & PST_HEREDOC))
if (ret && remember_on_history && (parser_state & PST_HEREDOC))
{
/* To make adding the the here-document body right, we need to rely
on history_delimiting_chars() returning \n for the first line of
@ -2668,6 +2670,7 @@ reset_parser ()
FREE (word_desc_to_read);
word_desc_to_read = (WORD_DESC *)NULL;
current_token = '\n'; /* XXX */
last_read_token = '\n';
token_to_read = '\n';
}
@ -2915,6 +2918,7 @@ tokword:
#define P_DQUOTE 0x04
#define P_COMMAND 0x08 /* parsing a command, so look for comments */
#define P_BACKQUOTE 0x10 /* parsing a backquoted command substitution */
#define P_ARRAYSUB 0x20 /* parsing a [...] array subscript for assignment */
/* Lexical state while parsing a grouping construct or $(...). */
#define LEX_WASDOL 0x001
@ -2927,6 +2931,7 @@ tokword:
#define LEX_INHEREDOC 0x080
#define LEX_HEREDELIM 0x100 /* reading here-doc delimiter */
#define LEX_STRIPDOC 0x200 /* <<- strip tabs from here doc delim */
#define LEX_INWORD 0x400
#define COMSUB_META(ch) ((ch) == ';' || (ch) == '&' || (ch) == '|')
@ -3129,6 +3134,8 @@ parse_matched_pair (qc, open, close, lenp, flags)
APPEND_NESTRET ();
FREE (nestret);
}
else if ((flags & P_ARRAYSUB) && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
goto parse_dollar_word;
}
/* Parse an old-style command substitution within double quotes as a
single word. */
@ -3145,6 +3152,7 @@ parse_matched_pair (qc, open, close, lenp, flags)
else if MBTEST(open != '`' && (tflags & LEX_WASDOL) && (ch == '(' || ch == '{' || ch == '[')) /* ) } ] */
/* check for $(), $[], or ${} inside quoted string. */
{
parse_dollar_word:
if (open == ch) /* undo previous increment */
count--;
if (ch == '(') /* ) */
@ -3179,7 +3187,7 @@ parse_comsub (qc, open, close, lenp, flags)
int open, close;
int *lenp, flags;
{
int count, ch, peekc, tflags, lex_rwlen, lex_firstind;
int count, ch, peekc, tflags, lex_rwlen, lex_wlen, lex_firstind;
int nestlen, ttranslen, start_lineno;
char *ret, *nestret, *ttrans, *heredelim;
int retind, retsize, rflags, hdlen;
@ -3200,7 +3208,7 @@ parse_comsub (qc, open, close, lenp, flags)
retind = 0;
start_lineno = line_number;
lex_rwlen = 0;
lex_rwlen = lex_wlen = 0;
heredelim = 0;
lex_firstind = -1;
@ -3267,6 +3275,46 @@ eof_error:
continue;
}
if (tflags & LEX_PASSNEXT) /* last char was backslash */
{
/*itrace("parse_comsub:%d: lex_passnext -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
tflags &= ~LEX_PASSNEXT;
if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
{
if (retind > 0)
retind--; /* swallow previously-added backslash */
continue;
}
RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
if MBTEST(ch == CTLESC || ch == CTLNUL)
ret[retind++] = CTLESC;
ret[retind++] = ch;
continue;
}
/* If this is a shell break character, we are not in a word. If not,
we either start or continue a word. */
if MBTEST(shellbreak (ch))
{
tflags &= ~LEX_INWORD;
/*itrace("parse_comsub:%d: lex_inword -> 0 ch = `%c' (%d)", line_number, ch, __LINE__);*/
}
else
{
if (tflags & LEX_INWORD)
{
lex_wlen++;
/*itrace("parse_comsub:%d: lex_inword == 1 ch = `%c' lex_wlen = %d (%d)", line_number, ch, lex_wlen, __LINE__);*/
}
else
{
/*itrace("parse_comsub:%d: lex_inword -> 1 ch = `%c' (%d)", line_number, ch, __LINE__);*/
tflags |= LEX_INWORD;
lex_wlen = 0;
}
}
/* Skip whitespace */
if MBTEST(shellblank (ch) && lex_rwlen == 0)
{
@ -3306,7 +3354,7 @@ eof_error:
}
/* Meta-characters that can introduce a reserved word. Not perfect yet. */
if MBTEST((tflags & LEX_RESWDOK) == 0 && (tflags & LEX_CKCASE) && (tflags & LEX_INCOMMENT) == 0 && shellmeta(ch))
if MBTEST((tflags & LEX_RESWDOK) == 0 && (tflags & LEX_CKCASE) && (tflags & LEX_INCOMMENT) == 0 && (shellmeta(ch) || ch == '\n'))
{
/* Add this character. */
RESIZE_MALLOCED_BUFFER (ret, retind, 1, retsize, 64);
@ -3364,9 +3412,21 @@ eof_error:
}
tflags &= ~LEX_RESWDOK;
}
else if (shellbreak (ch) == 0)
else if MBTEST((tflags & LEX_CKCOMMENT) && ch == '#' && (lex_rwlen == 0 || ((tflags & LEX_INWORD) && lex_wlen == 0)))
; /* don't modify LEX_RESWDOK if we're starting a comment */
else if MBTEST((tflags & LEX_INCASE) && ch != '\n')
/* If we can read a reserved word and we're in case, we're at the
point where we can read a new pattern list or an esac. We
handle the esac case above. If we read a newline, we want to
leave LEX_RESWDOK alone. If we read anything else, we want to
turn off LEX_RESWDOK, since we're going to read a pattern list. */
{
tflags &= ~LEX_RESWDOK;
tflags &= ~LEX_RESWDOK;
/*itrace("parse_comsub:%d: lex_incase == 1 found `%c', lex_reswordok -> 0", line_number, ch);*/
}
else if MBTEST(shellbreak (ch) == 0)
{
tflags &= ~LEX_RESWDOK;
/*itrace("parse_comsub:%d: found `%c', lex_reswordok -> 0", line_number, ch);*/
}
}
@ -3394,36 +3454,23 @@ eof_error:
}
else
shell_ungetc (peekc);
tflags |= LEX_HEREDELIM;
lex_firstind = -1;
if (peekc != '<')
{
tflags |= LEX_HEREDELIM;
lex_firstind = -1;
}
continue;
}
else
ch = peekc; /* fall through and continue XXX - this skips comments if peekc == '#' */
ch = peekc; /* fall through and continue XXX */
}
/* Not exactly right yet, should handle shell metacharacters, too. If
any changes are made to this test, make analogous changes to subst.c:
extract_delimited_string(). */
else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (retind == 0 || ret[retind-1] == '\n' || shellblank (ret[retind - 1])))
else if MBTEST((tflags & LEX_CKCOMMENT) && (tflags & LEX_INCOMMENT) == 0 && ch == '#' && (((tflags & LEX_RESWDOK) && lex_rwlen == 0) || ((tflags & LEX_INWORD) && lex_wlen == 0)))
{
/*itrace("parse_comsub:%d: lex_incomment -> 1 (%d)", line_number, __LINE__);*/
tflags |= LEX_INCOMMENT;
}
if (tflags & LEX_PASSNEXT) /* last char was backslash */
{
tflags &= ~LEX_PASSNEXT;
if (qc != '\'' && ch == '\n') /* double-quoted \<newline> disappears. */
{
if (retind > 0)
retind--; /* swallow previously-added backslash */
continue;
}
RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
if MBTEST(ch == CTLESC || ch == CTLNUL)
ret[retind++] = CTLESC;
ret[retind++] = ch;
continue;
}
else if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
if MBTEST(ch == CTLESC || ch == CTLNUL) /* special shell escapes */
{
RESIZE_MALLOCED_BUFFER (ret, retind, 2, retsize, 64);
ret[retind++] = CTLESC;
@ -4248,7 +4295,7 @@ read_token_word (character)
((token_index > 0 && assignment_acceptable (last_read_token) && token_is_ident (token, token_index)) ||
(token_index == 0 && (parser_state&PST_COMPASSIGN))))
{
ttok = parse_matched_pair (cd, '[', ']', &ttoklen, 0);
ttok = parse_matched_pair (cd, '[', ']', &ttoklen, P_ARRAYSUB);
if (ttok == &matched_pair_error)
return -1; /* Bail immediately. */
RESIZE_MALLOCED_BUFFER (token, token_index, ttoklen + 2,
@ -4449,6 +4496,7 @@ reserved_word_acceptable (toksym)
case '}': /* XXX */
case AND_AND:
case BANG:
case BAR_AND:
case DO:
case DONE:
case ELIF:

View file

@ -25,6 +25,6 @@
regexp `^#define[ ]*PATCHLEVEL', since that's what support/mkversion.sh
looks for to find the patch level (for the sccs version string). */
#define PATCHLEVEL 0
#define PATCHLEVEL 38
#endif /* _PATCHLEVEL_H_ */

View file

@ -1032,6 +1032,7 @@ gen_shell_function_matches (cs, text, line, ind, lwords, nw, cw)
cmdlist = build_arg_list (funcname, text, lwords, cw);
pps = &ps;
save_parser_state (pps);
begin_unwind_frame ("gen-shell-function-matches");
add_unwind_protect (restore_parser_state, (char *)pps);
add_unwind_protect (dispose_words, (char *)cmdlist);
@ -1174,13 +1175,15 @@ command_line_to_word_list (line, llen, sentinel, nwp, cwp)
{
WORD_LIST *ret;
char *delims;
int i, j;
#if 0
delims = "()<>;&| \t\n"; /* shell metacharacters break words */
#else
delims = rl_completer_word_break_characters;
#endif
delims = xmalloc (strlen (rl_completer_word_break_characters) + 1);
for (i = j = 0; rl_completer_word_break_characters[i]; i++)
if (rl_completer_word_break_characters[i] != '\'' && rl_completer_word_break_characters[i] != '"')
delims[j++] = rl_completer_word_break_characters[i];
delims[j] = '\0';
ret = split_at_delims (line, llen, delims, sentinel, nwp, cwp);
free (delims);
return (ret);
}

42
sig.c
View file

@ -448,6 +448,48 @@ sighandler
termsig_sighandler (sig)
int sig;
{
/* If we get called twice with the same signal before handling it,
terminate right away. */
if (
#ifdef SIGHUP
sig != SIGHUP &&
#endif
#ifdef SIGINT
sig != SIGINT &&
#endif
#ifdef SIGDANGER
sig != SIGDANGER &&
#endif
#ifdef SIGPIPE
sig != SIGPIPE &&
#endif
#ifdef SIGALRM
sig != SIGALRM &&
#endif
#ifdef SIGTERM
sig != SIGTERM &&
#endif
#ifdef SIGXCPU
sig != SIGXCPU &&
#endif
#ifdef SIGXFSZ
sig != SIGXFSZ &&
#endif
#ifdef SIGVTALRM
sig != SIGVTALRM &&
#endif
#ifdef SIGLOST
sig != SIGLOST &&
#endif
#ifdef SIGUSR1
sig != SIGUSR1 &&
#endif
#ifdef SIGUSR2
sig != SIGUSR2 &&
#endif
sig == terminating_signal)
terminate_immediately = 1;
terminating_signal = sig;
/* XXX - should this also trigger when interrupt_immediately is set? */

151
subst.c
View file

@ -85,6 +85,7 @@ extern int errno;
/* Flags for the `pflags' argument to param_expand() */
#define PF_NOCOMSUB 0x01 /* Do not perform command substitution */
#define PF_IGNUNBOUND 0x02 /* ignore unbound vars even if -u set */
/* These defs make it easier to use the editor. */
#define LBRACE '{'
@ -222,6 +223,7 @@ static inline int skip_single_quoted __P((const char *, size_t, int));
static int skip_double_quoted __P((char *, size_t, int));
static char *extract_delimited_string __P((char *, int *, char *, char *, char *, int));
static char *extract_dollar_brace_string __P((char *, int *, int, int));
static int skip_matched_pair __P((const char *, int, int, int, int));
static char *pos_params __P((char *, int, int, int));
@ -262,7 +264,7 @@ static int valid_brace_expansion_word __P((char *, int));
static int chk_atstar __P((char *, int, int *, int *));
static int chk_arithsub __P((const char *, int));
static WORD_DESC *parameter_brace_expand_word __P((char *, int, int));
static WORD_DESC *parameter_brace_expand_word __P((char *, int, int, int));
static WORD_DESC *parameter_brace_expand_indir __P((char *, int, int, int *, int *));
static WORD_DESC *parameter_brace_expand_rhs __P((char *, char *, int, int, int *, int *));
static void parameter_brace_expand_error __P((char *, char *));
@ -1374,6 +1376,107 @@ unquote_bang (string)
#define CQ_RETURN(x) do { no_longjmp_on_fatal_error = 0; return (x); } while (0)
/* This function assumes s[i] == open; returns with s[ret] == close; used to
parse array subscripts. FLAGS currently unused. */
static int
skip_matched_pair (string, start, open, close, flags)
const char *string;
int start, open, close, flags;
{
int i, pass_next, backq, si, c, count;
size_t slen;
char *temp, *ss;
DECLARE_MBSTATE;
slen = strlen (string + start) + start;
no_longjmp_on_fatal_error = 1;
i = start + 1; /* skip over leading bracket */
count = 1;
pass_next = backq = 0;
ss = (char *)string;
while (c = string[i])
{
if (pass_next)
{
pass_next = 0;
if (c == 0)
CQ_RETURN(i);
ADVANCE_CHAR (string, slen, i);
continue;
}
else if (c == '\\')
{
pass_next = 1;
i++;
continue;
}
else if (backq)
{
if (c == '`')
backq = 0;
ADVANCE_CHAR (string, slen, i);
continue;
}
else if (c == '`')
{
backq = 1;
i++;
continue;
}
else if (c == open)
{
count++;
i++;
continue;
}
else if (c == close)
{
count--;
if (count == 0)
break;
i++;
continue;
}
else if (c == '\'' || c == '"')
{
i = (c == '\'') ? skip_single_quoted (ss, slen, ++i)
: skip_double_quoted (ss, slen, ++i);
/* no increment, the skip functions increment past the closing quote. */
}
else if (c == '$' && (string[i+1] == LPAREN || string[i+1] == LBRACE))
{
si = i + 2;
if (string[si] == '\0')
CQ_RETURN(si);
if (string[i+1] == LPAREN)
temp = extract_delimited_string (ss, &si, "$(", "(", ")", SX_NOALLOC|SX_COMMAND); /* ) */
else
temp = extract_dollar_brace_string (ss, &si, 0, SX_NOALLOC);
i = si;
if (string[i] == '\0') /* don't increment i past EOS in loop */
break;
i++;
continue;
}
else
ADVANCE_CHAR (string, slen, i);
}
CQ_RETURN(i);
}
#if defined (ARRAY_VARS)
int
skipsubscript (string, start)
const char *string;
int start;
{
return (skip_matched_pair (string, start, '[', ']', 0));
}
#endif
/* Skip characters in STRING until we find a character in DELIMS, and return
the index of that character. START is the index into string at which we
begin. This is similar in spirit to strpbrk, but it returns an index into
@ -5093,9 +5196,9 @@ chk_atstar (name, quoted, quoted_dollar_atp, contains_dollar_at)
the shell, e.g., "@", "$", "*", etc. QUOTED, if non-zero, means that
NAME was found inside of a double-quoted expression. */
static WORD_DESC *
parameter_brace_expand_word (name, var_is_special, quoted)
parameter_brace_expand_word (name, var_is_special, quoted, pflags)
char *name;
int var_is_special, quoted;
int var_is_special, quoted, pflags;
{
WORD_DESC *ret;
char *temp, *tt;
@ -5127,7 +5230,7 @@ parameter_brace_expand_word (name, var_is_special, quoted)
strcpy (tt + 1, name);
ret = param_expand (tt, &sindex, quoted, (int *)NULL, (int *)NULL,
(int *)NULL, (int *)NULL, 0);
(int *)NULL, (int *)NULL, pflags);
free (tt);
}
#if defined (ARRAY_VARS)
@ -5188,7 +5291,7 @@ parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, c
char *temp, *t;
WORD_DESC *w;
w = parameter_brace_expand_word (name, var_is_special, quoted);
w = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
t = w->word;
/* Have to dequote here if necessary */
if (t)
@ -5205,7 +5308,7 @@ parameter_brace_expand_indir (name, var_is_special, quoted, quoted_dollar_atp, c
if (t == 0)
return (WORD_DESC *)NULL;
w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted);
w = parameter_brace_expand_word (t, SPECIAL_VAR(t, 0), quoted, 0);
free (t);
return w;
@ -6503,7 +6606,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
*contains_dollar_at = 1;
}
free (x);
free (xlist);
dispose_words (xlist);
free (temp1);
*indexp = sindex;
@ -6556,7 +6659,7 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
if (want_indir)
tdesc = parameter_brace_expand_indir (name + 1, var_is_special, quoted, quoted_dollar_atp, contains_dollar_at);
else
tdesc = parameter_brace_expand_word (name, var_is_special, quoted);
tdesc = parameter_brace_expand_word (name, var_is_special, quoted, PF_IGNUNBOUND);
if (tdesc)
{
@ -6664,13 +6767,13 @@ parameter_brace_expand (string, indexp, quoted, quoted_dollar_atp, contains_doll
return &expand_wdesc_error;
case RBRACE:
if (var_is_set == 0 && unbound_vars_is_error)
if (var_is_set == 0 && unbound_vars_is_error && ((name[0] != '@' && name[0] != '*') || name[1]))
{
last_command_exit_value = EXECUTION_FAILURE;
err_unboundvar (name);
FREE (value);
FREE (temp);
free (name);
last_command_exit_value = EXECUTION_FAILURE;
return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
}
break;
@ -6887,15 +6990,25 @@ param_expand (string, sindex, quoted, expanded_something,
case '*': /* `$*' */
list = list_rest_of_args ();
if (list == 0 && unbound_vars_is_error)
#if 0
/* According to austin-group posix proposal by Geoff Clare in
<20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
"The shell shall write a message to standard error and
immediately exit when it tries to expand an unset parameter
other than the '@' and '*' special parameters."
*/
if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
{
uerror[0] = '$';
uerror[1] = '*';
uerror[2] = '\0';
err_unboundvar (uerror);
last_command_exit_value = EXECUTION_FAILURE;
err_unboundvar (uerror);
return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
}
#endif
/* If there are no command-line arguments, this should just
disappear if there are other characters in the expansion,
@ -6949,15 +7062,25 @@ param_expand (string, sindex, quoted, expanded_something,
case '@': /* `$@' */
list = list_rest_of_args ();
if (list == 0 && unbound_vars_is_error)
#if 0
/* According to austin-group posix proposal by Geoff Clare in
<20090505091501.GA10097@squonk.masqnet> of 5 May 2009:
"The shell shall write a message to standard error and
immediately exit when it tries to expand an unset parameter
other than the '@' and '*' special parameters."
*/
if (list == 0 && unbound_vars_is_error && (pflags & PF_IGNUNBOUND) == 0)
{
uerror[0] = '$';
uerror[1] = '@';
uerror[2] = '\0';
err_unboundvar (uerror);
last_command_exit_value = EXECUTION_FAILURE;
err_unboundvar (uerror);
return (interactive_shell ? &expand_wdesc_error : &expand_wdesc_fatal);
}
#endif
/* We want to flag the fact that we saw this. We can't turn
off quoting entirely, because other characters in the

26
trap.c
View file

@ -755,7 +755,7 @@ _run_trap_internal (sig, tag)
}
flags = SEVAL_NONINT|SEVAL_NOHIST;
if (sig != DEBUG_TRAP && sig != RETURN_TRAP)
if (sig != DEBUG_TRAP && sig != RETURN_TRAP && sig != ERROR_TRAP)
flags |= SEVAL_RESETLINE;
if (function_code == 0)
parse_and_execute (trap_command, tag, flags);
@ -798,12 +798,36 @@ int
run_debug_trap ()
{
int trap_exit_value;
pid_t save_pgrp;
int save_pipe[2];
/* XXX - question: should the DEBUG trap inherit the RETURN trap? */
trap_exit_value = 0;
if ((sigmodes[DEBUG_TRAP] & SIG_TRAPPED) && ((sigmodes[DEBUG_TRAP] & SIG_IGNORED) == 0) && ((sigmodes[DEBUG_TRAP] & SIG_INPROGRESS) == 0))
{
#if defined (JOB_CONTROL)
save_pgrp = pipeline_pgrp;
pipeline_pgrp = 0;
save_pipeline (1);
# if defined (PGRP_PIPE)
save_pgrp_pipe (save_pipe, 1);
# endif
stop_making_children ();
#endif
trap_exit_value = _run_trap_internal (DEBUG_TRAP, "debug trap");
#if defined (JOB_CONTROL)
pipeline_pgrp = save_pgrp;
restore_pipeline (1);
# if defined (PGRP_PIPE)
close_pgrp_pipe ();
restore_pgrp_pipe (save_pipe);
# endif
if (pipeline_pgrp > 0)
give_terminal_to (pipeline_pgrp, 1);
notify_and_cleanup ();
#endif
#if defined (DEBUGGER)
/* If we're in the debugger and the DEBUG trap returns 2 while we're in

View file

@ -252,6 +252,7 @@ static SHELL_VAR **fapply __P((sh_var_map_func_t *));
static int visible_var __P((SHELL_VAR *));
static int visible_and_exported __P((SHELL_VAR *));
static int export_environment_candidate __P((SHELL_VAR *));
static int local_and_exported __P((SHELL_VAR *));
static int variable_in_context __P((SHELL_VAR *));
#if defined (ARRAY_VARS)
@ -375,10 +376,17 @@ initialize_shell_variables (env, privmode)
}
# endif
#endif
#if 0
else if (legal_identifier (name))
#else
else
#endif
{
temp_var = bind_variable (name, string, 0);
VSETATTR (temp_var, (att_exported | att_imported));
if (legal_identifier (name))
VSETATTR (temp_var, (att_exported | att_imported));
else
VSETATTR (temp_var, (att_exported | att_imported | att_invisible));
array_needs_making = 1;
}
@ -2209,7 +2217,7 @@ bind_variable_internal (name, value, table, hflags, aflags)
}
else if (assoc_p (entry))
{
assoc_insert (assoc_cell (entry), "0", newval);
assoc_insert (assoc_cell (entry), savestring ("0"), newval);
free (newval);
}
else
@ -3082,6 +3090,16 @@ visible_and_exported (var)
return (invisible_p (var) == 0 && exported_p (var));
}
/* Candidate variables for the export environment are either valid variables
with the export attribute or invalid variables inherited from the initial
environment and simply passed through. */
static int
export_environment_candidate (var)
SHELL_VAR *var;
{
return (exported_p (var) && (invisible_p (var) == 0 || imported_p (var)));
}
/* Return non-zero if VAR is a local variable in the current context and
is exported. */
static int
@ -3438,7 +3456,11 @@ make_var_export_array (vcxt)
char **list;
SHELL_VAR **vars;
#if 0
vars = map_over (visible_and_exported, vcxt);
#else
vars = map_over (export_environment_candidate, vcxt);
#endif
if (vars == 0)
return (char **)NULL;