From 39393a5bd6ff3025d21fc6c7a8779c811601fc26 Mon Sep 17 00:00:00 2001 From: Chet Ramey Date: Wed, 7 Dec 2011 09:00:59 -0500 Subject: [PATCH] commit bash-20061130 snapshot --- CWRU/CWRU.chlog | 29 +++ CWRU/CWRU.chlog~ | 30 +++ CWRU/devfd.c | 2 +- MANIFEST | 4 + Makefile.in | 3 +- builtins/declare.def | 27 ++- builtins/declare.def~ | 475 ++++++++++++++++++++++++++++++++++++++++ builtins/evalfile.c | 11 +- builtins/exec.def | 4 +- builtins/exec.def~ | 229 +++++++++++++++++++ builtins/reserved.def | 4 +- builtins/reserved.def~ | 8 +- builtins/source.def | 1 - doc/bash.1 | 11 +- doc/bashref.texi | 5 +- doc/version.texi | 4 +- externs.h | 3 + lib/readline/readline.c | 7 +- lib/sh/Makefile.in | 6 +- lib/sh/snprintf.c | 2 + lib/sh/snprintf.c~ | 2 +- lib/sh/zmapfd.c | 88 ++++++++ tests/RUN-ONE-TEST | 2 +- tests/comsub.right | 21 ++ tests/comsub.tests | 42 ++++ tests/dbg-support.right | 8 +- tests/dstack.right | 4 +- tests/errors.right | 2 +- tests/history.right | 2 +- tests/intl.tests | 2 +- tests/new-exp.right | 3 + tests/new-exp6.sub | 7 + tests/printf.right | Bin 1479 -> 1504 bytes tests/printf.tests | 15 ++ tests/printf.tests~ | 45 ++++ tests/rsh.right | 2 +- tests/run-comsub | 2 + 37 files changed, 1062 insertions(+), 50 deletions(-) create mode 100644 builtins/declare.def~ create mode 100644 builtins/exec.def~ create mode 100644 lib/sh/zmapfd.c create mode 100644 tests/comsub.right create mode 100644 tests/comsub.tests create mode 100644 tests/run-comsub diff --git a/CWRU/CWRU.chlog b/CWRU/CWRU.chlog index 1d2f877ab..173e876c5 100644 --- a/CWRU/CWRU.chlog +++ b/CWRU/CWRU.chlog @@ -13981,3 +13981,32 @@ lib/readline/readline.c variable _rl_revert_all_at_newline is non-zero - declare _rl_revert_all_lines initially 0 + 11/27 + ----- +doc/{bash.1,bashref.texi} + - make sure to be explicit that `typeset +r' cannot remove the readonly + attribute from a variable + + 11/28 + ----- +lib/sh/zmapfd.c + - new file, implements zmapfd(), which takes a file and returns its + contents in a string + +externs.h + - extern declaration for zmapfd + + 11/29 + ----- +builtins/evalfile.c + - in _evalfile, use zmapfd to read the contents of the file into a + string, rather than using the size reported by stat and reading that + many characters, if the file is not a regular file (for things like + named pipes, stat reports the size as 0) + + 12/3 + ---- +lib/sh/snprintf.c + - make sure number() sets the FL_UNSIGNED flag for %x and %X, so + fmtulong treats them as unsigned numbers. Fixes bug reported by + James Botte diff --git a/CWRU/CWRU.chlog~ b/CWRU/CWRU.chlog~ index 21a0c1ce8..6ec5722ba 100644 --- a/CWRU/CWRU.chlog~ +++ b/CWRU/CWRU.chlog~ @@ -13979,3 +13979,33 @@ rldefs.h lib/readline/readline.c - call _rl_revert_all_lines from readline_internal_teardown if the variable _rl_revert_all_at_newline is non-zero + - declare _rl_revert_all_lines initially 0 + + 11/27 + ----- +doc/{bash.1,bashref.texi} + - make sure to be explicit that `typeset +r' cannot remove the readonly + attribute from a variable + + 11/28 + ----- +lib/sh/zmapfd.c + - new file, implements zmapfd(), which takes a file and returns its + contents in a string + +externs.h + - extern declaration for zmapfd + + 11/29 + ----- +builtins/evalfile.c + - in _evalfile, use zmapfd to read the contents of the file into a + string, rather than using the size reported by stat and reading that + many characters, if the file is not a regular file (for things like + named pipes, stat reports the size as 0) + + 12/3 + ---- +lib/sh/snprintf.c + - make sure number() sets the FL_UNSIGNED flag for %x and %X, so + fmtulong treats them as unsigned numbers diff --git a/CWRU/devfd.c b/CWRU/devfd.c index db443a617..e5a357487 100644 --- a/CWRU/devfd.c +++ b/CWRU/devfd.c @@ -31,7 +31,7 @@ char **v; fd = open("/dev/null", O_RDONLY, 0666); if (fd == -1) exit (2); - if (dup2(fd, 3) == -1) + if (fd != 3 && (dup2(fd, 3) == -1)) exit (1); /* test -r /dev/fd/3 */ r = access("/dev/fd/3", R_OK); diff --git a/MANIFEST b/MANIFEST index 195c3f380..69c36c3f6 100644 --- a/MANIFEST +++ b/MANIFEST @@ -426,6 +426,7 @@ lib/sh/wcsdup.c f lib/sh/winsize.c f lib/sh/xstrchr.c f lib/sh/zcatfd.c f +lib/sh/zmapfd.c f lib/sh/zread.c f lib/sh/zwrite.c f lib/termcap/Makefile.in f @@ -712,6 +713,8 @@ tests/source2.sub f tests/source3.sub f tests/source4.sub f tests/source5.sub f +tests/comsub.tests f +tests/comsub.right f tests/cond.tests f tests/cond.right f tests/cprint.tests f @@ -859,6 +862,7 @@ tests/run-array f tests/run-array2 f tests/run-braces f tests/run-builtins f +tests/run-comsub f tests/run-cond f tests/run-cprint f tests/run-dbg-support f diff --git a/Makefile.in b/Makefile.in index b5339b72b..e89181814 100644 --- a/Makefile.in +++ b/Makefile.in @@ -204,7 +204,8 @@ SHLIB_SOURCE = ${SH_LIBSRC}/clktck.c ${SH_LIBSRC}/getcwd.c \ ${SH_LIBSRC}/memset.c ${SH_LIBSRC}/xstrchr.c \ ${SH_LIBSRC}/zcatfd.c ${SH_LIBSRC}/shmatch.c \ ${SH_LIBSRC}/strnlen.c ${SH_LIBSRC}/winsize.c \ - ${SH_LIBSRC}/eaccess.c ${SH_LIBSRC}/wcsdup.c + ${SH_LIBSRC}/eaccess.c ${SH_LIBSRC}/wcsdup.c \ + ${SH_LIBSRC}/zmapfd.c SHLIB_LIB = -lsh SHLIB_LIBNAME = libsh.a diff --git a/builtins/declare.def b/builtins/declare.def index 4d94face6..c472a86c4 100644 --- a/builtins/declare.def +++ b/builtins/declare.def @@ -24,30 +24,29 @@ $PRODUCES declare.c $BUILTIN declare $FUNCTION declare_builtin $SHORT_DOC declare [-afFirtx] [-p] [name[=value] ...] -Declare variables and/or give them attributes. If no NAMEs are -given, then display the values of variables instead. The -p option -will display the attributes and values of each NAME. +Declare variables and give them attributes. If no NAMEs are +given, then display the values of variables instead. When +displaying variable values, the -f option restricts the display +to function names and definitions; the -F option restricts the +display to function names only (plus line number and source file +when debugging). The -p option will display the attributes and +values of each NAME. -The flags are: +The options which set attributes are: -a to make NAMEs arrays (if supported) - -f to select from among function names only - -F to display function names (and line number and source file name if - debugging) without definitions -i to make NAMEs have the `integer' attribute -r to make NAMEs readonly -t to make NAMEs have the `trace' attribute -x to make NAMEs export -Variables with the integer attribute have arithmetic evaluation (see -`let') done when the variable is assigned to. +Using `+' instead of `-' turns off the given attribute. -When displaying values of variables, -f displays a function's name -and definition. The -F option restricts the display to function -name only. +Variables with the integer attribute have arithmetic evaluation (see +the `let' command) done when the variable is assigned a value. -Using `+' instead of `-' turns off the given attribute instead. When -used in a function, makes NAMEs local, as with the `local' command. +When used in a function, `declare' makes NAMEs local, as with the `local' +command. $END $BUILTIN typeset diff --git a/builtins/declare.def~ b/builtins/declare.def~ new file mode 100644 index 000000000..4d94face6 --- /dev/null +++ b/builtins/declare.def~ @@ -0,0 +1,475 @@ +This file is declare.def, from which is created declare.c. +It implements the builtins "declare" and "local" in Bash. + +Copyright (C) 1987-2004 Free Software Foundation, Inc. + +This file is part of GNU Bash, the Bourne Again SHell. + +Bash is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +Bash is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with Bash; see the file COPYING. If not, write to the Free Software +Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +$PRODUCES declare.c + +$BUILTIN declare +$FUNCTION declare_builtin +$SHORT_DOC declare [-afFirtx] [-p] [name[=value] ...] +Declare variables and/or give them attributes. If no NAMEs are +given, then display the values of variables instead. The -p option +will display the attributes and values of each NAME. + +The flags are: + + -a to make NAMEs arrays (if supported) + -f to select from among function names only + -F to display function names (and line number and source file name if + debugging) without definitions + -i to make NAMEs have the `integer' attribute + -r to make NAMEs readonly + -t to make NAMEs have the `trace' attribute + -x to make NAMEs export + +Variables with the integer attribute have arithmetic evaluation (see +`let') done when the variable is assigned to. + +When displaying values of variables, -f displays a function's name +and definition. The -F option restricts the display to function +name only. + +Using `+' instead of `-' turns off the given attribute instead. When +used in a function, makes NAMEs local, as with the `local' command. +$END + +$BUILTIN typeset +$FUNCTION declare_builtin +$SHORT_DOC typeset [-afFirtx] [-p] name[=value] ... +Obsolete. See `declare'. +$END + +#include + +#if defined (HAVE_UNISTD_H) +# ifdef _MINIX +# include +# endif +# include +#endif + +#include + +#include "../bashansi.h" +#include "../bashintl.h" + +#include "../shell.h" +#include "common.h" +#include "builtext.h" +#include "bashgetopt.h" + +extern int array_needs_making; +extern int posixly_correct; + +static int declare_internal __P((register WORD_LIST *, int)); + +/* Declare or change variable attributes. */ +int +declare_builtin (list) + register WORD_LIST *list; +{ + return (declare_internal (list, 0)); +} + +$BUILTIN local +$FUNCTION local_builtin +$SHORT_DOC local name[=value] ... +Create a local variable called NAME, and give it VALUE. LOCAL +can only be used within a function; it makes the variable NAME +have a visible scope restricted to that function and its children. +$END +int +local_builtin (list) + register WORD_LIST *list; +{ + if (variable_context) + return (declare_internal (list, 1)); + else + { + builtin_error (_("can only be used in a function")); + return (EXECUTION_FAILURE); + } +} + +#if defined (ARRAY_VARS) +# define DECLARE_OPTS "+afiprtxF" +#else +# define DECLARE_OPTS "+fiprtxF" +#endif + +/* The workhorse function. */ +static int +declare_internal (list, local_var) + register WORD_LIST *list; + int local_var; +{ + int flags_on, flags_off, *flags, any_failed, assign_error, pflag, nodefs, opt; + char *t, *subscript_start; + SHELL_VAR *var; + FUNCTION_DEF *shell_fn; + + flags_on = flags_off = any_failed = assign_error = pflag = nodefs = 0; + reset_internal_getopt (); + while ((opt = internal_getopt (list, DECLARE_OPTS)) != EOF) + { + flags = list_opttype == '+' ? &flags_off : &flags_on; + + switch (opt) + { + case 'a': +#if defined (ARRAY_VARS) + *flags |= att_array; +#endif + break; + case 'p': + if (local_var == 0) + pflag++; + break; + case 'F': + nodefs++; + *flags |= att_function; + break; + case 'f': + *flags |= att_function; + break; + case 'i': + *flags |= att_integer; + break; + case 'r': + *flags |= att_readonly; + break; + case 't': + *flags |= att_trace; + break; + case 'x': + *flags |= att_exported; + array_needs_making = 1; + break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + + list = loptend; + + /* If there are no more arguments left, then we just want to show + some variables. */ + if (list == 0) /* declare -[afFirtx] */ + { + /* Show local variables defined at this context level if this is + the `local' builtin. */ + if (local_var) + { + register SHELL_VAR **vlist; + register int i; + + vlist = all_local_variables (); + + if (vlist) + { + for (i = 0; vlist[i]; i++) + print_assignment (vlist[i]); + + free (vlist); + } + } + else + { + if (flags_on == 0) + set_builtin ((WORD_LIST *)NULL); + else + set_or_show_attributes ((WORD_LIST *)NULL, flags_on, nodefs); + } + + fflush (stdout); + return (EXECUTION_SUCCESS); + } + + if (pflag) /* declare -p [-afFirtx] name [name...] */ + { + for (any_failed = 0; list; list = list->next) + { + pflag = show_name_attributes (list->word->word, nodefs); + if (pflag) + { + sh_notfound (list->word->word); + any_failed++; + } + } + return (any_failed ? EXECUTION_FAILURE : EXECUTION_SUCCESS); + } + +#define NEXT_VARIABLE() free (name); list = list->next; continue + + /* There are arguments left, so we are making variables. */ + while (list) /* declare [-afFirx] name [name ...] */ + { + char *value, *name; + int offset, aflags; +#if defined (ARRAY_VARS) + int making_array_special, compound_array_assign, simple_array_assign; +#endif + + name = savestring (list->word->word); + offset = assignment (name, 0); + aflags = 0; + + if (offset) /* declare [-afFirx] name=value */ + { + name[offset] = '\0'; + value = name + offset + 1; + if (name[offset - 1] == '+') + { + aflags |= ASS_APPEND; + name[offset - 1] = '\0'; + } + } + else + value = ""; + +#if defined (ARRAY_VARS) + compound_array_assign = simple_array_assign = 0; + subscript_start = (char *)NULL; + if (t = strchr (name, '[')) /* ] */ + { + subscript_start = t; + *t = '\0'; + making_array_special = 1; + } + else + making_array_special = 0; +#endif + + /* If we're in posix mode or not looking for a shell function (since + shell function names don't have to be valid identifiers when the + shell's not in posix mode), check whether or not the argument is a + valid, well-formed shell identifier. */ + if ((posixly_correct || (flags_on & att_function) == 0) && legal_identifier (name) == 0) + { + sh_invalidid (name); + assign_error++; + NEXT_VARIABLE (); + } + + /* If VARIABLE_CONTEXT has a non-zero value, then we are executing + inside of a function. This means we should make local variables, + not global ones. */ + + /* XXX - this has consequences when we're making a local copy of a + variable that was in the temporary environment. Watch out + for this. */ + if (variable_context && ((flags_on & att_function) == 0)) + { +#if defined (ARRAY_VARS) + if ((flags_on & att_array) || making_array_special) + var = make_local_array_variable (name); + else +#endif + var = make_local_variable (name); + if (var == 0) + { + any_failed++; + NEXT_VARIABLE (); + } + } + else + var = (SHELL_VAR *)NULL; + + /* If we are declaring a function, then complain about it in some way. + We don't let people make functions by saying `typeset -f foo=bar'. */ + + /* There should be a way, however, to let people look at a particular + function definition by saying `typeset -f foo'. */ + + if (flags_on & att_function) + { + if (offset) /* declare -f [-rix] foo=bar */ + { + builtin_error (_("cannot use `-f' to make functions")); + free (name); + return (EXECUTION_FAILURE); + } + else /* declare -f [-rx] name [name...] */ + { + var = find_function (name); + + if (var) + { + if (readonly_p (var) && (flags_off & att_readonly)) + { + builtin_error (_("%s: readonly function"), name); + any_failed++; + NEXT_VARIABLE (); + } + + /* declare -[Ff] name [name...] */ + if (flags_on == att_function && flags_off == 0) + { +#if defined (DEBUGGER) + if (nodefs && debugging_mode) + { + shell_fn = find_function_def (var->name); + if (shell_fn) + printf ("%s %d %s\n", var->name, shell_fn->line, shell_fn->source_file); + else + printf ("%s\n", var->name); + } + else +#endif /* DEBUGGER */ + { + t = nodefs ? var->name + : named_function_string (name, function_cell (var), 1); + printf ("%s\n", t); + } + } + else /* declare -[fF] -[rx] name [name...] */ + { + VSETATTR (var, flags_on); + VUNSETATTR (var, flags_off); + } + } + else + any_failed++; + NEXT_VARIABLE (); + } + } + else /* declare -[airx] name [name...] */ + { + /* Non-null if we just created or fetched a local variable. */ + if (var == 0) + var = find_variable (name); + + if (var == 0) + { +#if defined (ARRAY_VARS) + if ((flags_on & att_array) || making_array_special) + var = make_new_array_variable (name); + else +#endif + var = bind_variable (name, "", 0); + } + + /* Cannot use declare +r to turn off readonly attribute. */ + if (readonly_p (var) && (flags_off & att_readonly)) + { + sh_readonly (name); + any_failed++; + NEXT_VARIABLE (); + } + + /* Cannot use declare to assign value to readonly or noassign + variable. */ + if ((readonly_p (var) || noassign_p (var)) && offset) + { + if (readonly_p (var)) + sh_readonly (name); + assign_error++; + NEXT_VARIABLE (); + } + +#if defined (ARRAY_VARS) + if ((making_array_special || (flags_on & att_array) || array_p (var)) && offset) + { + int vlen; + vlen = STRLEN (value); +#if 0 + if (value[0] == '(' && strchr (value, ')')) +#else + if (value[0] == '(' && value[vlen-1] == ')') +#endif + compound_array_assign = 1; + else + simple_array_assign = 1; + } + + /* Cannot use declare +a name to remove an array variable. */ + if ((flags_off & att_array) && array_p (var)) + { + builtin_error (_("%s: cannot destroy array variables in this way"), name); + any_failed++; + NEXT_VARIABLE (); + } + + /* declare -a name makes name an array variable. */ + if ((making_array_special || (flags_on & att_array)) && array_p (var) == 0) + var = convert_var_to_array (var); +#endif /* ARRAY_VARS */ + + VSETATTR (var, flags_on); + VUNSETATTR (var, flags_off); + +#if defined (ARRAY_VARS) + if (offset && compound_array_assign) + assign_array_var_from_string (var, value, aflags); + else if (simple_array_assign && subscript_start) + { + /* declare [-a] name[N]=value */ + *subscript_start = '['; /* ] */ + var = assign_array_element (name, value, 0); /* XXX - not aflags */ + *subscript_start = '\0'; + } + else if (simple_array_assign) + /* let bind_array_variable take care of this. */ + bind_array_variable (name, 0, value, aflags); + else +#endif + /* bind_variable_value duplicates the essential internals of + bind_variable() */ + if (offset) + bind_variable_value (var, value, aflags); + + /* If we found this variable in the temporary environment, as with + `var=value declare -x var', make sure it is treated identically + to `var=value export var'. Do the same for `declare -r' and + `readonly'. Preserve the attributes, except for att_tempvar. */ + /* XXX -- should this create a variable in the global scope, or + modify the local variable flags? ksh93 has it modify the + global scope. + Need to handle case like in set_var_attribute where a temporary + variable is in the same table as the function local vars. */ + if ((flags_on & (att_exported|att_readonly)) && tempvar_p (var)) + { + SHELL_VAR *tv; + char *tvalue; + + tv = find_tempenv_variable (var->name); + if (tv) + { + tvalue = var_isset (var) ? savestring (value_cell (var)) : savestring (""); + tv = bind_variable (var->name, tvalue, 0); + tv->attributes |= var->attributes & ~att_tempvar; + if (tv->context > 0) + VSETATTR (tv, att_propagate); + free (tvalue); + } + VSETATTR (var, att_propagate); + } + } + + stupidly_hack_special_variables (name); + + NEXT_VARIABLE (); + } + + return (assign_error ? EX_BADASSIGN + : ((any_failed == 0) ? EXECUTION_SUCCESS + : EXECUTION_FAILURE)); +} diff --git a/builtins/evalfile.c b/builtins/evalfile.c index d05bc7bb3..89d39e042 100644 --- a/builtins/evalfile.c +++ b/builtins/evalfile.c @@ -147,9 +147,14 @@ file_error_and_exit: setmode (fd, O_TEXT); #endif - string = (char *)xmalloc (1 + file_size); - result = read (fd, string, file_size); - string[result] = '\0'; + if (S_ISREG (finfo.st_mode)) + { + string = (char *)xmalloc (1 + file_size); + result = read (fd, string, file_size); + string[result] = '\0'; + } + else + result = zmapfd (fd, &string, 0); return_val = errno; close (fd); diff --git a/builtins/exec.def b/builtins/exec.def index 0818a25e2..dd34ad53a 100644 --- a/builtins/exec.def +++ b/builtins/exec.def @@ -24,12 +24,12 @@ $PRODUCES exec.c $BUILTIN exec $FUNCTION exec_builtin $SHORT_DOC exec [-cl] [-a name] file [redirection ...] -Exec FILE, replacing this shell with the specified program. +Execute FILE, replacing this shell with the specified program. If FILE is not specified, the redirections take effect in this shell. If the first argument is `-l', then place a dash in the zeroth arg passed to FILE, as login does. If the `-c' option is supplied, FILE is executed with a null environment. The `-a' -option means to make set argv[0] of the executed process to NAME. +option means set argv[0] of the executed process to NAME. If the file cannot be executed and the shell is not interactive, then the shell exits, unless the shell option `execfail' is set. $END diff --git a/builtins/exec.def~ b/builtins/exec.def~ new file mode 100644 index 000000000..0818a25e2 --- /dev/null +++ b/builtins/exec.def~ @@ -0,0 +1,229 @@ +This file is exec.def, from which is created exec.c. +It implements the builtin "exec" in Bash. + +Copyright (C) 1987-2003 Free Software Foundation, Inc. + +This file is part of GNU Bash, the Bourne Again SHell. + +Bash is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +Bash is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License along +with Bash; see the file COPYING. If not, write to the Free Software +Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. + +$PRODUCES exec.c + +$BUILTIN exec +$FUNCTION exec_builtin +$SHORT_DOC exec [-cl] [-a name] file [redirection ...] +Exec FILE, replacing this shell with the specified program. +If FILE is not specified, the redirections take effect in this +shell. If the first argument is `-l', then place a dash in the +zeroth arg passed to FILE, as login does. If the `-c' option +is supplied, FILE is executed with a null environment. The `-a' +option means to make set argv[0] of the executed process to NAME. +If the file cannot be executed and the shell is not interactive, +then the shell exits, unless the shell option `execfail' is set. +$END + +#include + +#include "../bashtypes.h" +#include "posixstat.h" +#include +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include "../bashansi.h" +#include "../bashintl.h" + +#include "../shell.h" +#include "../execute_cmd.h" +#include "../findcmd.h" +#if defined (JOB_CONTROL) +# include "../jobs.h" +#endif +#include "../flags.h" +#include "../trap.h" +#if defined (HISTORY) +# include "../bashhist.h" +#endif +#include "common.h" +#include "bashgetopt.h" + +/* Not all systems declare ERRNO in errno.h... and some systems #define it! */ +#if !defined (errno) +extern int errno; +#endif /* !errno */ + +extern int subshell_environment; +extern REDIRECT *redirection_undo_list; + +int no_exit_on_failed_exec; + +/* If the user wants this to look like a login shell, then + prepend a `-' onto NAME and return the new name. */ +static char * +mkdashname (name) + char *name; +{ + char *ret; + + ret = (char *)xmalloc (2 + strlen (name)); + ret[0] = '-'; + strcpy (ret + 1, name); + return ret; +} + +int +exec_builtin (list) + WORD_LIST *list; +{ + int exit_value = EXECUTION_FAILURE; + int cleanenv, login, opt; + char *argv0, *command, **args, **env, *newname, *com2; + + cleanenv = login = 0; + argv0 = (char *)NULL; + + reset_internal_getopt (); + while ((opt = internal_getopt (list, "cla:")) != -1) + { + switch (opt) + { + case 'c': + cleanenv = 1; + break; + case 'l': + login = 1; + break; + case 'a': + argv0 = list_optarg; + break; + default: + builtin_usage (); + return (EX_USAGE); + } + } + list = loptend; + + /* First, let the redirections remain. */ + dispose_redirects (redirection_undo_list); + redirection_undo_list = (REDIRECT *)NULL; + + if (list == 0) + return (EXECUTION_SUCCESS); + +#if defined (RESTRICTED_SHELL) + if (restricted) + { + sh_restricted ((char *)NULL); + return (EXECUTION_FAILURE); + } +#endif /* RESTRICTED_SHELL */ + + args = strvec_from_word_list (list, 1, 0, (int *)NULL); + + /* A command with a slash anywhere in its name is not looked up in $PATH. */ + command = absolute_program (args[0]) ? args[0] : search_for_command (args[0]); + + if (command == 0) + { + sh_notfound (args[0]); + exit_value = EX_NOTFOUND; /* As per Posix.2, 3.14.6 */ + goto failed_exec; + } + + com2 = full_pathname (command); + if (com2) + { + if (command != args[0]) + free (command); + command = com2; + } + + if (argv0) + { + free (args[0]); + args[0] = login ? mkdashname (argv0) : savestring (argv0); + } + else if (login) + { + newname = mkdashname (args[0]); + free (args[0]); + args[0] = newname; + } + + /* Decrement SHLVL by 1 so a new shell started here has the same value, + preserving the appearance. After we do that, we need to change the + exported environment to include the new value. */ + if (cleanenv == 0) + adjust_shell_level (-1); + + if (cleanenv) + env = (char **)NULL; + else + { + maybe_make_export_env (); + env = export_env; + } + +#if defined (HISTORY) + if (interactive_shell && subshell_environment == 0) + maybe_save_shell_history (); +#endif /* HISTORY */ + + restore_original_signals (); + +#if defined (JOB_CONTROL) + if (subshell_environment == 0) + end_job_control (); +#endif /* JOB_CONTROL */ + + shell_execve (command, args, env); + + /* We have to set this to NULL because shell_execve has called realloc() + to stuff more items at the front of the array, which may have caused + the memory to be freed by realloc(). We don't want to free it twice. */ + args = (char **)NULL; + if (cleanenv == 0) + adjust_shell_level (1); + + if (executable_file (command) == 0) + { + builtin_error (_("%s: cannot execute: %s"), command, strerror (errno)); + exit_value = EX_NOEXEC; /* As per Posix.2, 3.14.6 */ + } + else + file_error (command); + +failed_exec: + FREE (command); + + if (subshell_environment || (interactive == 0 && no_exit_on_failed_exec == 0)) + exit_shell (exit_value); + + if (args) + strvec_dispose (args); + + initialize_traps (); + initialize_signals (1); + +#if defined (JOB_CONTROL) + if (interactive_shell || job_control) + restart_job_control (); +#endif /* JOB_CONTROL */ + + return (exit_value); +} diff --git a/builtins/reserved.def b/builtins/reserved.def index 28b48d0b5..584b944b0 100644 --- a/builtins/reserved.def +++ b/builtins/reserved.def @@ -61,8 +61,8 @@ $SHORT_DOC time [-p] pipeline Execute PIPELINE and print a summary of the real time, user CPU time, and system CPU time spent executing PIPELINE when it terminates. The return status is the return status of PIPELINE. The `-p' option -prints the timing summary in a slightly different format. This uses -the value of the TIMEFORMAT variable as the output format. +prints the timing summary in the portable Posix format; otherwise, the +the value of the TIMEFORMAT variable is used as the output format. $END $BUILTIN case diff --git a/builtins/reserved.def~ b/builtins/reserved.def~ index e968ec7cf..2ef303b3c 100644 --- a/builtins/reserved.def~ +++ b/builtins/reserved.def~ @@ -57,12 +57,12 @@ until a break command is executed. $END $BUILTIN time -$SHORT_DOC time [-p] PIPELINE +$SHORT_DOC time [-p] pipeline Execute PIPELINE and print a summary of the real time, user CPU time, and system CPU time spent executing PIPELINE when it terminates. The return status is the return status of PIPELINE. The `-p' option -prints the timing summary in a slightly different format. This uses -the value of the TIMEFORMAT variable as the output format. +prints the timing summary in the standard Posix format; otherwise, the +the value of the TIMEFORMAT variable is used as the output format. $END $BUILTIN case @@ -110,7 +110,7 @@ $END $BUILTIN % $DOCNAME fg_percent -$SHORT_DOC JOB_SPEC [&] +$SHORT_DOC job_spec [&] Equivalent to the JOB_SPEC argument to the `fg' command. Resume a stopped or background job. JOB_SPEC can specify either a job name or a job number. Following JOB_SPEC with a `&' places the job in diff --git a/builtins/source.def b/builtins/source.def index 9576f09e1..0a8eb0ffa 100644 --- a/builtins/source.def +++ b/builtins/source.def @@ -38,7 +38,6 @@ in $PATH are used to find the directory containing FILENAME. If any ARGUMENTS are supplied, they become the positional parameters when FILENAME is executed. $END -/* source.c - Implements the `.' and `source' builtins. */ #include diff --git a/doc/bash.1 b/doc/bash.1 index 8116270f8..bd29b8aac 100644 --- a/doc/bash.1 +++ b/doc/bash.1 @@ -6,12 +6,12 @@ .\" Case Western Reserve University .\" chet@po.cwru.edu .\" -.\" Last Change: Tue Nov 21 10:50:26 EST 2006 +.\" Last Change: Mon Nov 27 12:02:01 EST 2006 .\" .\" bash_builtins, strip all but Built-Ins section .if \n(zZ=1 .ig zZ .if \n(zY=1 .ig zY -.TH BASH 1 "2006 November 21" "GNU Bash-3.2" +.TH BASH 1 "2006 November 27" "GNU Bash-3.2" .\" .\" There's some problem with having a `@' .\" in a tagged paragraph with the BSD man macros. @@ -6499,8 +6499,11 @@ Mark \fIname\fPs for export to subsequent commands via the environment. .PD .PP Using `+' instead of `\-' -turns off the attribute instead, with the exception that \fB+a\fP -may not be used to destroy an array variable. When used in a function, +turns off the attribute instead, +with the exceptions that \fB+a\fP +may not be used to destroy an array variable and \fB+r\fB will not +remove the readonly attribute. +When used in a function, makes each \fIname\fP local, as with the .B local diff --git a/doc/bashref.texi b/doc/bashref.texi index 0f8094706..2460df768 100644 --- a/doc/bashref.texi +++ b/doc/bashref.texi @@ -3287,7 +3287,10 @@ Mark each @var{name} for export to subsequent commands via the environment. @end table -Using @samp{+} instead of @samp{-} turns off the attribute instead. +Using @samp{+} instead of @samp{-} turns off the attribute instead, +with the exceptions that @samp{+a} +may not be used to destroy an array variable and @samp{+r} will not +remove the readonly attribute. When used in a function, @code{declare} makes each @var{name} local, as with the @code{local} command. If a variable name is followed by =@var{value}, the value of the variable is set to @var{value}. diff --git a/doc/version.texi b/doc/version.texi index 1f386b4c1..530e495b7 100644 --- a/doc/version.texi +++ b/doc/version.texi @@ -2,9 +2,9 @@ Copyright (C) 1988-2006 Free Software Foundation, Inc. @end ignore -@set LASTCHANGE Tue Nov 21 10:50:07 EST 2006 +@set LASTCHANGE Mon Nov 27 12:02:15 EST 2006 @set EDITION 3.2 @set VERSION 3.2 -@set UPDATED 21 November 2006 +@set UPDATED 27 November 2006 @set UPDATED-MONTH November 2006 diff --git a/externs.h b/externs.h index bc28eda2f..834b767b6 100644 --- a/externs.h +++ b/externs.h @@ -383,6 +383,9 @@ extern char *xstrchr __P((const char *, int)); /* declarations for functions defined in lib/sh/zcatfd.c */ extern int zcatfd __P((int, int, char *)); +/* declarations for functions defined in lib/sh/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 zreadintr __P((int, char *, size_t)); diff --git a/lib/readline/readline.c b/lib/readline/readline.c index e0f76b1d4..8b1ad7d0d 100644 --- a/lib/readline/readline.c +++ b/lib/readline/readline.c @@ -314,11 +314,14 @@ readline (prompt) return ((char *)NULL); } +#if 0 /* If readline() is called after installing a callback handler, temporarily turn off the callback state to avoid ensuing messiness. Patch supplied - by the gdb folks. */ + by the gdb folks. XXX -- disabled. This can be fooled and readline + left in a strange state by a poorly-timed longjmp. */ if (in_callback = RL_ISSTATE (RL_STATE_CALLBACK)) RL_UNSETSTATE (RL_STATE_CALLBACK); +#endif rl_set_prompt (prompt); @@ -338,8 +341,10 @@ readline (prompt) rl_clear_signals (); #endif +#if 0 if (in_callback) RL_SETSTATE (RL_STATE_CALLBACK); +#endif return (value); } diff --git a/lib/sh/Makefile.in b/lib/sh/Makefile.in index bf95d1922..53e5ca5d1 100644 --- a/lib/sh/Makefile.in +++ b/lib/sh/Makefile.in @@ -88,7 +88,7 @@ CSOURCES = clktck.c clock.c getcwd.c getenv.c oslib.c setlinebuf.c \ shquote.c strtrans.c strindex.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 xstrchr.c zcatfd.c winsize.c eaccess.c \ + mktime.c strftime.c xstrchr.c zcatfd.c zmapfd.c winsize.c eaccess.c \ wcsdup.c # The header files for this library. @@ -101,7 +101,7 @@ OBJECTS = clktck.o clock.o getenv.o oslib.o setlinebuf.o strnlen.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 strindex.o snprintf.o mailstat.o fmtulong.o \ - fmtullong.o fmtumax.o xstrchr.o zcatfd.o winsize.o wcsdup.o \ + fmtullong.o fmtumax.o xstrchr.o zcatfd.o zmapfd.o winsize.o wcsdup.o \ ${LIBOBJS} SUPPORT = Makefile @@ -182,6 +182,7 @@ vprint.o: vprint.c wcsdup.o: wcsdup.c xstrchr.o: xstrchr.c zcatfd.o: zcatfd.c +zmapfd.o: zmapfd.c zread.o: zread.c zwrite.o: zwrite.c @@ -241,6 +242,7 @@ vprint.o: ${BUILD_DIR}/config.h wcsdup.o: ${BUILD_DIR}/config.h xstrchr.o: ${BUILD_DIR}/config.h zcatfd.o: ${BUILD_DIR}/config.h +zmapfd.o: ${BUILD_DIR}/config.h zread.o: ${BUILD_DIR}/config.h zwrite.o: ${BUILD_DIR}/config.h diff --git a/lib/sh/snprintf.c b/lib/sh/snprintf.c index 7bbf2c359..d05523e6a 100644 --- a/lib/sh/snprintf.c +++ b/lib/sh/snprintf.c @@ -674,6 +674,8 @@ number(p, d, base) sd = d; /* signed for ' ' padding in base 10 */ flags = (*p->pf == 'u' || *p->pf == 'U') ? FL_UNSIGNED : 0; + if (*p->pf == 'x' || *p->pf == 'X') + flags |= FL_UNSIGNED; /* %x, %X treated as unsigned */ if (*p->pf == 'X') flags |= FL_HEXUPPER; diff --git a/lib/sh/snprintf.c~ b/lib/sh/snprintf.c~ index 95e191b41..7bbf2c359 100644 --- a/lib/sh/snprintf.c~ +++ b/lib/sh/snprintf.c~ @@ -406,7 +406,7 @@ static void xfree __P((void *)); } \ } while (0) -#if defined (HAVE_LOCALE_H) +#if defined (HAVE_LOCALE_H) && defined (HAVE_LOCALECONV) # define GETLOCALEDATA(d, t, g) \ do \ { \ diff --git a/lib/sh/zmapfd.c b/lib/sh/zmapfd.c new file mode 100644 index 000000000..9add0654c --- /dev/null +++ b/lib/sh/zmapfd.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2006 Free Software Foundation, Inc. + + This file is part of GNU Bash, the Bourne Again SHell. + + Bash is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2, or (at your option) any later + version. + + Bash is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License along + with Bash; see the file COPYING. If not, write to the Free Software + Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */ + +#include + +#include + +#if defined (HAVE_UNISTD_H) +# include +#endif + +#include + +#include "bashansi.h" +#include "command.h" +#include "general.h" + +#if !defined (errno) +extern int errno; +#endif + +extern ssize_t zread __P((int, char *, size_t)); + +/* Dump contents of file descriptor FD to *OSTR. FN is the filename for + error messages (not used right now). */ +int +zmapfd (fd, ostr, fn) + int fd; + char **ostr; + char *fn; +{ + ssize_t nr; + int rval; + char lbuf[128]; + char *result; + int rsize, rind; + + rval = 0; + result = (char *)xmalloc (rsize = 64); + rind = 0; + + while (1) + { + nr = zread (fd, lbuf, sizeof (lbuf)); + if (nr == 0) + { + rval = rind; + break; + } + else if (nr < 0) + { + rval = -1; + free (result); + if (ostr) + *ostr = (char *)NULL; + break; + } + + RESIZE_MALLOCED_BUFFER (result, rind, nr, rsize, 128); + memcpy (result+rind, lbuf, nr); + rind += nr; + } + + RESIZE_MALLOCED_BUFFER (result, rind, 1, rsize, 128); + result[rind] = '\0'; + + if (ostr) + *ostr = result; + else + free (result); + + return rval; +} 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/comsub.right b/tests/comsub.right new file mode 100644 index 000000000..a4aed2fe5 --- /dev/null +++ b/tests/comsub.right @@ -0,0 +1,21 @@ +./comsub.tests: line 7: hijkl: command not found +argv[1] = +argv[2] = +argv[1] = +argv[2] = +argv[1] = +argv[1] = +argv[2] = +argv[1] = <$> +argv[2] = +argv[1] = <`> +argv[2] = +argv[1] = <\> +argv[2] = +argv[1] = +argv[1] = +argv[1] = argv[2] = <-e> argv[3] = +argv[1] = argv[2] = <-e> argv[3] = +argv[1] = +argv[1] = +argv[1] = diff --git a/tests/comsub.tests b/tests/comsub.tests new file mode 100644 index 000000000..d481dc32d --- /dev/null +++ b/tests/comsub.tests @@ -0,0 +1,42 @@ +# command substution parsing tests + +TABSIZE=`grep -v '^[ #]' $CAPS argv[1] = <> argv[1] = <> argv[1] = <12> +argv[1] = <> +argv[1] = <> +argv[1] = ./new-exp.tests: line 560: ABXD: parameter unset diff --git a/tests/new-exp6.sub b/tests/new-exp6.sub index c2fbd73c9..532ec1af7 100644 --- a/tests/new-exp6.sub +++ b/tests/new-exp6.sub @@ -20,3 +20,10 @@ recho "${str/$str/}" recho "${snul##$snul}" recho "${str##$str}" recho "${str##$nul}" + +A="" +B="${A:0}" + +recho "$B" +recho "${A:0}" +recho "/tmp/test/TEST${A:0}" diff --git a/tests/printf.right b/tests/printf.right index 43c0574155d102fcaa4074e17fec3ccca62d7d3b..5a8749ef162ac464abd76bb60fe75e678ddd1465 100644 GIT binary patch delta 33 kc-lM8{eXMJaaKu7Cu2ubOGi_#LN0Z65Gv;4;z|Ny0HPlUYybcN delta 7 Oc-niweVlv4aaI5h8v{B3 diff --git a/tests/printf.tests b/tests/printf.tests index bd3bcc10e..7cfeebd02 100644 --- a/tests/printf.tests +++ b/tests/printf.tests @@ -285,3 +285,18 @@ printf "%E\n" 4 printf "%e\n" 4 printf "%4.2E\n" 4 printf "%4.2e\n" 4 + +printf "%08X\n" 2604292517 + +# make sure these format specifiers all output '' for empty string arguments +echo q +printf "%q\n" "" +printf "%q\n" + +echo s +printf "%s\n" '' +printf "%s\n" + +echo b +printf "%b\n" '' +printf "%b\n" diff --git a/tests/printf.tests~ b/tests/printf.tests~ index 60928d6bb..04241085f 100644 --- a/tests/printf.tests~ +++ b/tests/printf.tests~ @@ -253,3 +253,48 @@ printf '%0.5d\n' 1 printf '%05d\n' 1 printf '%5d\n' 1 printf '%0d\n' 1 + +# failures with various floating point formats and 0 after bash-3.2 + +printf "%G\n" 0 +printf "%g\n" 0 +printf "%4.2G\n" 0 +printf "%4.2g\n" 0 + +printf "%G\n" 4 +printf "%g\n" 4 +printf "%4.2G\n" 4 +printf "%4.2g\n" 4 + +printf "%F\n" 0 +printf "%f\n" 0 +printf "%4.2F\n" 0 +printf "%4.2f\n" 0 + +printf "%F\n" 4 +printf "%f\n" 4 +printf "%4.2F\n" 4 +printf "%4.2f\n" 4 + +printf "%E\n" 0 +printf "%e\n" 0 +printf "%4.2E\n" 0 +printf "%4.2e\n" 0 + +printf "%E\n" 4 +printf "%e\n" 4 +printf "%4.2E\n" 4 +printf "%4.2e\n" 4 + +# make sure these format specifiers all output '' for empty string arguments +echo q +printf "%q\n" "" +printf "%q\n" + +echo s +printf "%s\n" '' +printf "%s\n" + +echo b +printf "%b\n" '' +printf "%b\n" diff --git a/tests/rsh.right b/tests/rsh.right index e673b94d4..04c697108 100644 --- a/tests/rsh.right +++ b/tests/rsh.right @@ -7,7 +7,7 @@ ./rsh.tests: line 21: /tmp/restricted: restricted: cannot redirect output ./rsh.tests: line 26: command: -p: restricted ./rsh.tests: line 28: set: +r: invalid option -set: usage: set [--abefhkmnptuvxBCHP] [-o option] [arg ...] +set: usage: set [--abefhkmnptuvxBCHP] [-o option-name] [arg ...] ./rsh.tests: line 29: set: restricted: invalid option name ./rsh.tests: line 31: exec: restricted ./rsh.tests: after exec diff --git a/tests/run-comsub b/tests/run-comsub new file mode 100644 index 000000000..0bbcad5e8 --- /dev/null +++ b/tests/run-comsub @@ -0,0 +1,2 @@ +${THIS_SH} ./comsub.tests > /tmp/xx 2>&1 +diff /tmp/xx comsub.right && rm -f /tmp/xx -- 2.47.3