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 <James.M.Botte@lowes.com>
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
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);
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
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
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
${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
$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
--- /dev/null
+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 <config.h>
+
+#if defined (HAVE_UNISTD_H)
+# ifdef _MINIX
+# include <sys/types.h>
+# endif
+# include <unistd.h>
+#endif
+
+#include <stdio.h>
+
+#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));
+}
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);
$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
--- /dev/null
+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 <config.h>
+
+#include "../bashtypes.h"
+#include "posixstat.h"
+#include <signal.h>
+#include <errno.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#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);
+}
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
$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
$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
ARGUMENTS are supplied, they become the positional parameters when
FILENAME is executed.
$END
-/* source.c - Implements the `.' and `source' builtins. */
#include <config.h>
.\" 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.
.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
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}.
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
/* 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));
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);
rl_clear_signals ();
#endif
+#if 0
if (in_callback)
RL_SETSTATE (RL_STATE_CALLBACK);
+#endif
return (value);
}
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.
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
wcsdup.o: wcsdup.c
xstrchr.o: xstrchr.c
zcatfd.o: zcatfd.c
+zmapfd.o: zmapfd.c
zread.o: zread.c
zwrite.o: zwrite.c
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
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;
} \
} while (0)
-#if defined (HAVE_LOCALE_H)
+#if defined (HAVE_LOCALE_H) && defined (HAVE_LOCALECONV)
# define GETLOCALEDATA(d, t, g) \
do \
{ \
--- /dev/null
+/* 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 <config.h>
+
+#include <sys/types.h>
+
+#if defined (HAVE_UNISTD_H)
+# include <unistd.h>
+#endif
+
+#include <errno.h>
+
+#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;
+}
-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
--- /dev/null
+./comsub.tests: line 7: hijkl: command not found
+argv[1] = <ab>
+argv[2] = <cd>
+argv[1] = <abmn>
+argv[2] = <opyz>
+argv[1] = <b>
+argv[1] = <a\>
+argv[2] = <b>
+argv[1] = <$>
+argv[2] = <bab>
+argv[1] = <`>
+argv[2] = <ab>
+argv[1] = <\>
+argv[2] = <ab>
+argv[1] = <foo \\^Jbar>
+argv[1] = <foo \^Jbar>
+argv[1] = <sed> argv[2] = <-e> argv[3] = <s/[^I:]/\^J/g>
+argv[1] = <sed> argv[2] = <-e> argv[3] = <s/[^I:]//g>
+argv[1] = <foo\^Jbar>
+argv[1] = <foobar>
+argv[1] = <foo\^Jbar>
--- /dev/null
+# command substution parsing tests
+
+TABSIZE=`grep -v '^[ #]' $CAPS </dev/null | grep -v "^$" | grep -v "^capalias"| grep -v "^infoalias" | wc -l`
+
+recho `echo ab cd #efg
+hijkl`
+
+recho ab$(echo mn; echo op)yz
+
+a=`echo 'a b c' | sed 's/ /\\
+/g' | grep 'b'`
+recho $a
+
+recho `echo 'a\' b`
+
+recho `echo '\$' bab`
+
+recho `echo '\`' ab`
+
+recho `echo '\\' ab`
+
+# old-style command substitution parsing compatibility tests -- post bash-3.1
+recho 'foo \\
+bar'
+
+recho 'foo \
+bar'
+
+echo `recho sed -e 's/[ :]/\\
+/g'`
+
+echo `recho sed -e 's/[ :]/\
+/g'`
+
+echo `recho 'foo\\
+bar'`
+
+echo `recho 'foo\
+bar'`
+
+echo $(recho 'foo\
+bar')
debug lineno: 24 fn1
debug lineno: 25 fn1
./dbg-support.tests: line 25: caller: foo: invalid number
-caller: usage: caller [EXPR]
+caller: usage: caller [expr]
debug lineno: 25 fn1
debug lineno: 17 fn1
debug lineno: 12 print_return_trap
debug lineno: 24 fn1 71 main ./dbg-support.tests
debug lineno: 25 fn1
./dbg-support.tests: line 25: caller: foo: invalid number
-caller: usage: caller [EXPR]
+caller: usage: caller [expr]
debug lineno: 25 fn1
debug lineno: 17 fn1
debug lineno: 12 print_return_trap
79 main ./dbg-support.tests
./dbg-support.tests: line 25: caller: foo: invalid number
-caller: usage: caller [EXPR]
+caller: usage: caller [expr]
debug lineno: 80 main
fn2 here. Calling fn1...
30 fn2 ./dbg-support.tests
80 main ./dbg-support.tests
./dbg-support.tests: line 25: caller: foo: invalid number
-caller: usage: caller [EXPR]
+caller: usage: caller [expr]
debug lineno: 81 main
LINENO 34
./dstack.tests: line 9: pushd: no other directory
./dstack.tests: line 10: popd: directory stack empty
./dstack.tests: line 13: pushd: -m: invalid number
-pushd: usage: pushd [dir | +N | -N] [-n]
+pushd: usage: pushd [-n] [+N | -N | dir]
./dstack.tests: line 14: popd: -m: invalid number
-popd: usage: popd [+N | -N] [-n]
+popd: usage: popd [-n] [+N | -N]
./dstack.tests: line 15: dirs: -m: invalid number
dirs: usage: dirs [-clpv] [+N] [-N]
./dstack.tests: line 16: dirs: 7: invalid option
./errors.tests: line 184: .: -i: invalid option
.: usage: . filename [arguments]
./errors.tests: line 187: set: -q: invalid option
-set: usage: set [--abefhkmnptuvxBCHP] [-o option] [arg ...]
+set: usage: set [--abefhkmnptuvxBCHP] [-o option-name] [arg ...]
./errors.tests: line 190: enable: sh: not a shell builtin
./errors.tests: line 190: enable: bash: not a shell builtin
./errors.tests: line 193: shopt: cannot set and unset shell options simultaneously
history: usage: history [-c] [-d offset] [n] or history -awrn [filename] or history -ps arg [arg...]
./history.tests: line 6: history: cannot use more than one of -anrw
./history.tests: line 9: fc: -v: invalid option
-fc: usage: fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [cmd]
+fc: usage: fc [-e ename] [-nlr] [first] [last] or fc -s [pat=rep] [command]
1 for i in one two three; do echo $i; done
2 /bin/sh -c 'echo this is $0'
3 ls
-export LANG=en_US.UTF-8
+export LC_ALL=en_US.UTF-8
a=$'\303\251'
argv[1] = <>
argv[1] = <>
argv[1] = <12>
+argv[1] = <>
+argv[1] = <>
+argv[1] = </tmp/test/TEST>
./new-exp.tests: line 560: ABXD: parameter unset
recho "${snul##$snul}"
recho "${str##$str}"
recho "${str##$nul}"
+
+A=""
+B="${A:0}"
+
+recho "$B"
+recho "${A:0}"
+recho "/tmp/test/TEST${A:0}"
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"
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"
./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
--- /dev/null
+${THIS_SH} ./comsub.tests > /tmp/xx 2>&1
+diff /tmp/xx comsub.right && rm -f /tmp/xx