From: Chet Ramey Date: Sun, 4 Dec 2011 03:49:22 +0000 (-0500) Subject: commit bash-20060606 snapshot X-Git-Tag: bash-3.2-alpha~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2872b01afcff39bc460653bfc5d5269fcfecb845;p=thirdparty%2Fbash.git commit bash-20060606 snapshot --- diff --git a/CHANGES b/CHANGES index b168b407a..1fb74a7a7 100644 --- a/CHANGES +++ b/CHANGES @@ -114,6 +114,12 @@ ii. Fixed a bug that could cause file descriptors > 10 to not be closed even jj. Fixed a bug that caused single quotes to be stripped from ANSI-C quoting inside double-quoted command substitutions. +kk. Fixed a bug that could cause core dumps when `return' was executed as the + last element of a pipeline inside a shell function. + +ll. Fixed a bug that caused DEBUG trap strings to overwrite commands stored in + the jobs list. + 2. Changes to Readline a. Fixed a problem that caused segmentation faults when using readline in diff --git a/CHANGES~ b/CHANGES~ index 5b3157f53..b168b407a 100644 --- a/CHANGES~ +++ b/CHANGES~ @@ -111,6 +111,9 @@ hh. Fixed a bug that caused `unset LANG' to not properly reset the locale ii. Fixed a bug that could cause file descriptors > 10 to not be closed even when closed explicitly by a script. +jj. Fixed a bug that caused single quotes to be stripped from ANSI-C quoting + inside double-quoted command substitutions. + 2. Changes to Readline a. Fixed a problem that caused segmentation faults when using readline in @@ -156,6 +159,9 @@ l. Fixed a problem with the callback interface that caused it to fail when m. Fixed a bug that could cause a core dump when an edited history entry was re-executed under certain conditions. +n. Fixed a bug that caused readline to reference freed memory when attmpting + to display a portion of the prompt. + 3. New Features in Bash a. Changed the parameter pattern replacement functions to not anchor the diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index eea5e4be1..60df377f0 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -13438,4 +13438,21 @@ subst.c - make sure that parameter_brace_substring leaves this_command_name set to either NULL or its previous value after setting it so that arithmetic evaluation errors while expanding substring values - contain meaningful informationn + contain meaningful information + + 6/9 + --- +execute_cmd.c + - make sure that SUBSHELL_ASYNC and SUBSHELL_PIPE are set as flag bits + in subshell_environment, rather than setting only a single value + - change execute_subshell_builtin_or_function to give the `return' + builtin a place to longjmp to when executed in a subshell or pipeline + (mostly as the last command in a pipeline). Bug reported by + Oleg Verych + - in execute_simple_command, make sure to call execute_disk_command + with the_printed_command_except_trap to keep DEBUG trap command + strings from overwriting the command strings associated with jobs + and printed in job control messages. Bug reported by Daniel Kahn + Gillmor + +[bash-3.2-alpha frozen] diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index 9bb6c1de7..72c13ae8f 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -13414,6 +13414,43 @@ lib/readline/undo.c - new function, alloc_undo_entry (enum undo_code what, int start, int end, char *text) takes care of allocating and populating a struct for an individual undo list entry + - new function: _rl_copy_undo_entry(UNDO_LIST *entry) + - new function: _rl_copy_undo_list(UNDO_LIST *head) +lib/readline/rlprivate.h + - new extern declarations for _rl_copy_undo_{entry,list} + +execute_cmd.c + - change execute_cond_node so that quoting the rhs of the =~ + operator forces string matching, like the == and != operators + + 5/23 + ---- +redir.c + - add_undo_redirect now takes as an additional argument the type of + redirection we're trying to undo + - don't add a "preservation" redirection for fds > SHELL_FD_BASE if + the redirection is closing the fd - + 5/24 + ---- +subst.c + - make sure that parameter_brace_substring leaves this_command_name + set to either NULL or its previous value after setting it so that + arithmetic evaluation errors while expanding substring values + contain meaningful information + + 6/9 + --- +execute_cmd.c + - make sure that SUBSHELL_ASYNC and SUBSHELL_PIPE are set as flag bits + in subshell_environment, rather than setting only a single value + - change execute_subshell_builtin_or_function to give the `return' + builtin a place to longjmp to when executed in a subshell or pipeline + (mostly as the last command in a pipeline). Bug reported by + Oleg Verych + - in execute_simple_command, make sure to call execute_disk_command + with the_printed_command_except_trap to keep DEBUG trap command + strings from overwriting the command strings associated with jobs + and printed in job control messages. Bug reported by Daniel Kahn + Gillmor diff --git a/Makefile.in b/Makefile.in index f22ededb0..8220f3b8e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -499,7 +499,7 @@ CREATED_SUPPORT = signames.h recho$(EXEEXT) zecho$(EXEEXT) printenv$(EXEEXT) \ tests/recho$(EXEEXT) tests/zecho$(EXEEXT) \ tests/printenv$(EXEEXT) mksignames$(EXEEXT) lsignames.h \ mksyntax${EXEEXT} syntax.c $(VERSPROG) $(VERSOBJ) \ - buildversion.o mksignames.o signames.o + buildversion.o mksignames.o signames.o buildsignames.o CREATED_CONFIGURE = config.h config.cache config.status config.log \ stamp-h po/POTFILES CREATED_MAKEFILES = Makefile builtins/Makefile doc/Makefile \ diff --git a/autom4te.cache/output.0 b/autom4te.cache/output.0 index 1fd75528f..78f0a3187 100644 --- a/autom4te.cache/output.0 +++ b/autom4te.cache/output.0 @@ -1,7 +1,7 @@ @%:@! /bin/sh @%:@ From configure.in for Bash 3.2, version 3.188. @%:@ Guess values for system-dependent variables and create Makefiles. -@%:@ Generated by GNU Autoconf 2.59 for bash 3.2-alpha. +@%:@ Generated by GNU Autoconf 2.59 for bash 3.2-devel. @%:@ @%:@ Report bugs to . @%:@ @@ -270,8 +270,8 @@ SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='bash' PACKAGE_TARNAME='bash' -PACKAGE_VERSION='3.2-alpha' -PACKAGE_STRING='bash 3.2-alpha' +PACKAGE_VERSION='3.2-devel' +PACKAGE_STRING='bash 3.2-devel' PACKAGE_BUGREPORT='bug-bash@gnu.org' ac_unique_file="shell.h" @@ -785,7 +785,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures bash 3.2-alpha to adapt to many kinds of systems. +\`configure' configures bash 3.2-devel to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -846,7 +846,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of bash 3.2-alpha:";; + short | recursive ) echo "Configuration of bash 3.2-devel:";; esac cat <<\_ACEOF @@ -1039,7 +1039,7 @@ fi test -n "$ac_init_help" && exit 0 if $ac_init_version; then cat <<\_ACEOF -bash configure 3.2-alpha +bash configure 3.2-devel generated by GNU Autoconf 2.59 Copyright (C) 2003 Free Software Foundation, Inc. @@ -1053,7 +1053,7 @@ cat >&5 <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by bash $as_me 3.2-alpha, which was +It was created by bash $as_me 3.2-devel, which was generated by GNU Autoconf 2.59. Invocation command line was $ $0 $@ @@ -1422,7 +1422,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. BASHVERS=3.2 -RELSTATUS=alpha +RELSTATUS=devel case "$RELSTATUS" in alp*|bet*|dev*|rc*) DEBUG='-DDEBUG' MALLOC_DEBUG='-DMALLOC_DEBUG' ;; @@ -27484,7 +27484,7 @@ _ASBOX } >&5 cat >&5 <<_CSEOF -This file was extended by bash $as_me 3.2-alpha, which was +This file was extended by bash $as_me 3.2-devel, which was generated by GNU Autoconf 2.59. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -27547,7 +27547,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\ -bash config.status 3.2-alpha +bash config.status 3.2-devel configured by $0, generated by GNU Autoconf 2.59, with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" diff --git a/autom4te.cache/traces.0 b/autom4te.cache/traces.0 index cda7348f5..bb415349f 100644 --- a/autom4te.cache/traces.0 +++ b/autom4te.cache/traces.0 @@ -1,4 +1,4 @@ -m4trace:configure.in:30: -1- AC_INIT([bash], [3.2-alpha], [bug-bash@gnu.org]) +m4trace:configure.in:30: -1- AC_INIT([bash], [3.2-devel], [bug-bash@gnu.org]) m4trace:configure.in:30: -1- m4_pattern_forbid([^_?A[CHUM]_]) m4trace:configure.in:30: -1- m4_pattern_forbid([_AC_]) m4trace:configure.in:30: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS']) diff --git a/configure.in b/configure.in index cf8aa00c1..cc862da22 100644 --- a/configure.in +++ b/configure.in @@ -25,7 +25,7 @@ dnl Process this file with autoconf to produce a configure script. AC_REVISION([for Bash 3.2, version 3.188])dnl define(bashvers, 3.2) -define(relstatus, alpha) +define(relstatus, devel) AC_INIT([bash], bashvers-relstatus, [bug-bash@gnu.org]) diff --git a/execute_cmd.c b/execute_cmd.c index 38833e3bf..1359cbbd2 100644 --- a/execute_cmd.c +++ b/execute_cmd.c @@ -1242,7 +1242,16 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) /* Subshells are neither login nor interactive. */ login_shell = interactive = 0; - subshell_environment = user_subshell ? SUBSHELL_PAREN : SUBSHELL_ASYNC; + if (user_subshell) + subshell_environment = SUBSHELL_PAREN; + else + { + subshell_environment = 0; /* XXX */ + if (asynchronous) + subshell_environment |= SUBSHELL_ASYNC; + if (pipe_in != NO_PIPE || pipe_out != NO_PIPE) + subshell_environment |= SUBSHELL_PIPE; + } reset_terminating_signals (); /* in sig.c */ /* Cancel traps, in trap.c. */ @@ -1330,8 +1339,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) if (function_value) return_code = return_catch_value; else - return_code = execute_command_internal - (tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close); + return_code = execute_command_internal (tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close); /* If we are asked to, invert the return value. */ if (invert) @@ -2641,7 +2649,10 @@ execute_null_command (redirects, pipe_in, pipe_out, async) do_piping (pipe_in, pipe_out); - subshell_environment = SUBSHELL_ASYNC; + if (async) + subshell_environment |= SUBSHELL_ASYNC; + if (pipe_in != NO_PIPE || pipe_out != NO_PIPE) + subshell_environment |= SUBSHELL_PIPE; if (do_redirections (redirects, RX_ACTIVE) == 0) exit (EXECUTION_SUCCESS); @@ -3010,7 +3021,7 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close) } if (command_line == 0) - command_line = savestring (the_printed_command); + command_line = savestring (the_printed_command_except_trap); execute_disk_command (words, simple_command->redirects, command_line, pipe_in, pipe_out, async, fds_to_close, @@ -3369,7 +3380,7 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var, struct fd_bitmap *fds_to_close; int flags; { - int result, r; + int result, r, funcvalue; #if defined (JOB_CONTROL) int jobs_hack; @@ -3380,7 +3391,10 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var, /* A subshell is neither a login shell nor interactive. */ login_shell = interactive = 0; - subshell_environment = SUBSHELL_ASYNC; + if (async) + subshell_environment |= SUBSHELL_ASYNC; + if (pipe_in != NO_PIPE || pipe_out != NO_PIPE) + subshell_environment |= SUBSHELL_PIPE; maybe_make_export_env (); /* XXX - is this needed? */ @@ -3414,10 +3428,18 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var, so we don't go back up to main(). */ result = setjmp (top_level); + /* Give the return builtin a place to jump to when executed in a subshell + or pipeline */ + funcvalue = 0; + if (return_catch_flag && builtin == return_builtin) + funcvalue = setjmp (return_catch); + if (result == EXITPROG) exit (last_command_exit_value); else if (result) exit (EXECUTION_FAILURE); + else if (funcvalue) + exit (return_catch_value); else { r = execute_builtin (builtin, words, flags, 1); diff --git a/execute_cmd.c~ b/execute_cmd.c~ index e52905d54..99266440b 100644 --- a/execute_cmd.c~ +++ b/execute_cmd.c~ @@ -1242,7 +1242,16 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) /* Subshells are neither login nor interactive. */ login_shell = interactive = 0; - subshell_environment = user_subshell ? SUBSHELL_PAREN : SUBSHELL_ASYNC; + if (user_subshell) + subshell_environment = SUBSHELL_PAREN; + else + { + subshell_environment = 0; /* XXX */ + if (asynchronous) + subshell_environment |= SUBSHELL_ASYNC; + if (pipe_in != NO_PIPE || pipe_out != NO_PIPE) + subshell_environment |= SUBSHELL_PIPE; + } reset_terminating_signals (); /* in sig.c */ /* Cancel traps, in trap.c. */ @@ -1330,8 +1339,7 @@ execute_in_subshell (command, asynchronous, pipe_in, pipe_out, fds_to_close) if (function_value) return_code = return_catch_value; else - return_code = execute_command_internal - (tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close); + return_code = execute_command_internal (tcom, asynchronous, NO_PIPE, NO_PIPE, fds_to_close); /* If we are asked to, invert the return value. */ if (invert) @@ -2503,6 +2511,7 @@ execute_cond_node (cond) } else if (cond->type == COND_BINARY) { + rmatch = 0; patmatch = ((cond->op->word[1] == '=') && (cond->op->word[2] == '\0') && (cond->op->word[0] == '!' || cond->op->word[0] == '=') || (cond->op->word[0] == '=' && cond->op->word[1] == '\0')); @@ -2514,7 +2523,7 @@ execute_cond_node (cond) arg1 = cond_expand_word (cond->left->op, 0); if (arg1 == 0) arg1 = nullstr; - arg2 = cond_expand_word (cond->right->op, patmatch); + arg2 = cond_expand_word (cond->right->op, patmatch||rmatch); if (arg2 == 0) arg2 = nullstr; @@ -2640,7 +2649,10 @@ execute_null_command (redirects, pipe_in, pipe_out, async) do_piping (pipe_in, pipe_out); - subshell_environment = SUBSHELL_ASYNC; + if (async) + subshell_environment |= SUBSHELL_ASYNC; + if (pipe_in != NO_PIPE || pipe_out != NO_PIPE) + subshell_environment |= SUBSHELL_PIPE; if (do_redirections (redirects, RX_ACTIVE) == 0) exit (EXECUTION_SUCCESS); @@ -3009,7 +3021,11 @@ execute_simple_command (simple_command, pipe_in, pipe_out, async, fds_to_close) } if (command_line == 0) +#if 0 command_line = savestring (the_printed_command); +#else + command_line = savestring (the_printed_command_except_trap); +#endif execute_disk_command (words, simple_command->redirects, command_line, pipe_in, pipe_out, async, fds_to_close, @@ -3368,7 +3384,7 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var, struct fd_bitmap *fds_to_close; int flags; { - int result, r; + int result, r, funcvalue; #if defined (JOB_CONTROL) int jobs_hack; @@ -3379,7 +3395,10 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var, /* A subshell is neither a login shell nor interactive. */ login_shell = interactive = 0; - subshell_environment = SUBSHELL_ASYNC; + if (async) + subshell_environment |= SUBSHELL_ASYNC; + if (pipe_in != NO_PIPE || pipe_out != NO_PIPE) + subshell_environment |= SUBSHELL_PIPE; maybe_make_export_env (); /* XXX - is this needed? */ @@ -3413,10 +3432,18 @@ execute_subshell_builtin_or_function (words, redirects, builtin, var, so we don't go back up to main(). */ result = setjmp (top_level); + /* Give the return builtin a place to jump to when executed in a subshell + or pipeline */ + funcvalue = 0; + if (return_catch_flag && builtin == return_builtin) + funcvalue = setjmp (return_catch); + if (result == EXITPROG) exit (last_command_exit_value); else if (result) exit (EXECUTION_FAILURE); + else if (funcvalue) + exit (return_catch_value); else { r = execute_builtin (builtin, words, flags, 1); diff --git a/jobs.c b/jobs.c index 37cb85f4f..32df5a0a3 100644 --- a/jobs.c +++ b/jobs.c @@ -146,6 +146,7 @@ extern int interrupt_immediately; extern int last_command_exit_value, last_command_exit_signal; extern int loop_level, breaking; extern int sourcelevel; +extern int running_trap; extern sh_builtin_func_t *this_shell_builtin; extern char *shell_name, *this_command_name; extern sigset_t top_level_mask; diff --git a/jobs.c~ b/jobs.c~ index fcd146e38..bdd0e0ab0 100644 --- a/jobs.c~ +++ b/jobs.c~ @@ -77,8 +77,8 @@ extern int errno; #endif /* !errno */ #define DEFAULT_CHILD_MAX 32 -#if 1 -#define MAX_JOBS_IN_ARRAY 4096 /* production*/ +#if !defined (DEBUG) +#define MAX_JOBS_IN_ARRAY 4096 /* production */ #else #define MAX_JOBS_IN_ARRAY 128 /* testing */ #endif @@ -146,6 +146,7 @@ extern int interrupt_immediately; extern int last_command_exit_value, last_command_exit_signal; extern int loop_level, breaking; extern int sourcelevel; +extern int running_trap; extern sh_builtin_func_t *this_shell_builtin; extern char *shell_name, *this_command_name; extern sigset_t top_level_mask; @@ -962,7 +963,7 @@ compact_jobs_list (flags) reap_dead_jobs (); realloc_jobs_list (); - + return (js.j_lastj); } @@ -1078,6 +1079,7 @@ add_process (name, pid) { PROCESS *t, *p; +itrace("add_process: name = %s running_trap = %d", name, running_trap); #if defined (RECYCLES_PIDS) int j; p = find_process (pid, 0, &j); @@ -1230,8 +1232,9 @@ hangup_all_jobs () { if (jobs[i]) { - if ((jobs[i]->flags & J_NOHUP) == 0) - killpg (jobs[i]->pgrp, SIGHUP); + if (jobs[i]->flags & J_NOHUP) + continue; + killpg (jobs[i]->pgrp, SIGHUP); if (STOPPED (i)) killpg (jobs[i]->pgrp, SIGCONT); } @@ -1667,6 +1670,7 @@ make_child (command, async_p) sigemptyset (&oset); sigprocmask (SIG_BLOCK, &set, &oset); +itrace("make_child: command = %s", command ? command : ""); making_children (); #if defined (BUFFERED_INPUT) @@ -2968,6 +2972,7 @@ waitchld (wpid, block) : 0; if (sigchld || block == 0) waitpid_flags |= WNOHANG; + CHECK_TERMSIG; pid = WAITPID (-1, &status, waitpid_flags); /* WCONTINUED may be rejected by waitpid as invalid even when defined */ @@ -2994,6 +2999,7 @@ waitchld (wpid, block) /* If waitpid returns 0, there are running children. If it returns -1, the only other error POSIX says it can return is EINTR. */ + CHECK_TERMSIG; if (pid <= 0) continue; /* jumps right to the test */ @@ -3228,7 +3234,7 @@ set_job_status_and_cleanup (job) temp_handler = trap_to_sighandler (SIGINT); restore_sigint_handler (); if (temp_handler == SIG_DFL) - termination_unwind_protect (SIGINT); + termsig_handler (SIGINT); else if (temp_handler != SIG_IGN) (*temp_handler) (SIGINT); } @@ -3430,6 +3436,7 @@ notify_of_job_status () fprintf (stderr, "\n"); if (dir == 0) dir = current_working_directory (); +itrace("calling pretty_print_job for job %d", job); pretty_print_job (job, JLIST_STANDARD, stderr); if (dir && (strcmp (dir, jobs[job]->wd) != 0)) fprintf (stderr, @@ -3704,7 +3711,7 @@ give_terminal_to (pgrp, force) if (tcsetpgrp (shell_tty, pgrp) < 0) { /* Maybe we should print an error message? */ -#ifdef DEBUG +#if 0 sys_error ("tcsetpgrp(%d) failed: pid %ld to pgrp %ld", shell_tty, (long)getpid(), (long)pgrp); #endif diff --git a/tests/RUN-ONE-TEST b/tests/RUN-ONE-TEST index 3efcf32d6..72ec06a2c 100755 --- a/tests/RUN-ONE-TEST +++ b/tests/RUN-ONE-TEST @@ -1,4 +1,4 @@ -BUILD_DIR=/usr/local/build/chet/bash/bash-current +BUILD_DIR=/usr/local/build/bash/bash-current THIS_SH=$BUILD_DIR/bash PATH=$PATH:$BUILD_DIR diff --git a/tests/func.right b/tests/func.right index e51d92b10..1bd12e121 100644 --- a/tests/func.right +++ b/tests/func.right @@ -148,3 +148,4 @@ expect 2 40 2 40 expect 5 20 5 20 +5 diff --git a/tests/func.right~ b/tests/func.right~ new file mode 100644 index 000000000..e51d92b10 --- /dev/null +++ b/tests/func.right~ @@ -0,0 +1,150 @@ +a returns 5 +b returns 4 +c returns 3 +d returns 2 +in e +e returned 25 +x is 25 +ZZ +abcde +defghi +ZZ +5 +0 +AVAR +AVAR +foo +foo +AVAR +5 +5 +f1 +f1 () +{ + ( return 5 ); + status=$?; + echo $status; + return $status +} +before: try to assign to FUNCNAME +outside: FUNCNAME = +before: FUNCNAME = func +FUNCNAME = func2 +after: FUNCNAME = func +outside2: FUNCNAME = +function +zf is a function +zf () +{ + echo this is zf +} +f is a function +f () +{ + echo f-x; + echo f-y +} 1>&2 +subshell +f is a function +f () +{ + echo f-x; + echo f-y +} 1>&2 +f2 is a function +f2 () +{ + echo f2-a; + function f3 () + { + echo f3-a; + echo f3-b + } 1>&2; + f3 +} +subshell +f2 is a function +f2 () +{ + echo f2-a; + function f3 () + { + echo f3-a; + echo f3-b + } 1>&2; + f3 +} +f4 is a function +f4 () +{ + echo f4-a; + function f5 () + { + echo f5-a; + echo f5-b + } 1>&2; + f5 +} 2>&1 +subshell +f4 is a function +f4 () +{ + echo f4-a; + function f5 () + { + echo f5-a; + echo f5-b + } 1>&2; + f5 +} 2>&1 +testgrp is a function +testgrp () +{ + echo testgrp-a; + { + echo tg-x; + echo tg-y + } 1>&2; + echo testgrp-b +} +subshell +testgrp is a function +testgrp () +{ + echo testgrp-a; + { + echo tg-x; + echo tg-y + } 1>&2; + echo testgrp-b +} +funca is a function +funca () +{ + ( echo func-a ) +} +funcb is a function +funcb () +{ + ( echo func-b ) +} +funcc is a function +funcc () +{ + ( echo func-c ) 2>&1 +} +func-a +func-b +func-c +expect 5 10 +5 10 +expect 20 +20 +expect 5 20 +5 20 +expect 5 30 +5 30 +expect 2 40 +2 40 +expect 5 20 +5 20 diff --git a/tests/func.tests b/tests/func.tests index 063f4e0b8..cbbbdb035 100644 --- a/tests/func.tests +++ b/tests/func.tests @@ -165,4 +165,12 @@ myfunction() { myfunction myfunction | cat +segv() +{ + echo foo | return 5 +} + +segv +echo $? + exit 0 diff --git a/tests/func.tests~ b/tests/func.tests~ new file mode 100644 index 000000000..063f4e0b8 --- /dev/null +++ b/tests/func.tests~ @@ -0,0 +1,168 @@ +a() +{ + x=$((x - 1)) + return 5 +} + +b() +{ + x=$((x - 1)) + a + echo a returns $? + return 4 +} + +c() +{ + x=$((x - 1)) + b + echo b returns $? + return 3 +} + +d() +{ + x=$((x - 1)) + c + echo c returns $? + return 2 +} + +e() +{ + d + echo d returns $? + echo in e + x=$((x - 1)) + return $x +} + +f() +{ + e + echo e returned $? + echo x is $x + return 0 +} + +x=30 +f + +# make sure unsetting a local variable preserves the `local' attribute +f1() +{ + local zz + zz=abcde + echo $zz + unset zz + zz=defghi + echo $zz +} + +zz=ZZ +echo $zz +f1 +echo $zz + +unset -f f1 +f1() +{ + return 5 +} + +( f1 ) +echo $? + +unset -f f1 +f1() +{ + sleep 5 + return 5 +} + +f1 & +wait +echo $? + +unset -f f1 + +f1() +{ + echo $AVAR + printenv AVAR +} + +AVAR=AVAR +echo $AVAR +f1 +AVAR=foo f1 +echo $AVAR + +unset -f f1 +# make sure subshells can do a `return' if we're executing in a function +f1() +{ + ( return 5 ) + status=$? + echo $status + return $status +} + +f1 +echo $? + +declare -F f1 # should print just the name +declare -f f1 # should print the definition, too + +# no functions should be exported, right? +declare -xF +declare -xf + +# FUNCNAME tests +func2() +{ + echo FUNCNAME = $FUNCNAME +} + +func() +{ + echo before: FUNCNAME = $FUNCNAME + func2 + echo after: FUNCNAME = $FUNCNAME +} + +echo before: try to assign to FUNCNAME +FUCNAME=7 + +echo outside: FUNCNAME = $FUNCNAME +func +echo outside2: FUNCNAME = $FUNCNAME + +# test exported functions (and cached exportstr) +zf() +{ + echo this is zf +} +export -f zf + +${THIS_SH} -c 'type -t zf' +${THIS_SH} -c 'type zf' + +${THIS_SH} ./func1.sub + +# tests for functions whose bodies are not group commands, with and without +# attached redirections +${THIS_SH} ./func2.sub + +# test for some posix-specific function behavior +${THIS_SH} ./func3.sub + +unset -f myfunction +myfunction() { + echo "bad shell function redirection" +} >> /dev/null + +myfunction +myfunction | cat + +exit 0